Files
EasySoft-ZenTaoPMS/module/cne/model.php
T
2025-09-15 15:06:12 +08:00

1162 lines
41 KiB
PHP

<?php
declare(strict_types=1);
/**
* The model file of CNE(Cloud Native Engine) module of ZenTaoPMS.
*
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
* @license ZPL (http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Jianhua Wang <wangjianhua@easycorp.ltd>
* @package CNE
* @link https://www.zentao.net
*/
class cneModel extends model
{
public $error;
/**
* Construct function: set api headers.
*
* @param string $appName
* @access public
* @return void
*/
public function __construct($appName = '')
{
parent::__construct($appName);
$this->error = new stdclass();
global $config, $app;
$config->CNE->api->headers[] = "{$config->CNE->api->auth}: {$config->CNE->api->token}";
$config->cloud->api->headers[] = "{$config->cloud->api->auth}: {$config->cloud->api->token}";
if($config->cloud->api->switchChannel && $app->session->cloudChannel)
{
$config->cloud->api->channel = $app->session->cloudChannel;
$config->CNE->api->channel = $app->session->cloudChannel;
}
}
/**
* 更新实例配置。例如:cpu、内存大小、LDAP设置...
* Update instance config. For example: cpu, memory size, LDAP settings...
*
* @link https://yapi.qc.oop.cc/project/21/interface/api/725
* @param object $instance
* @param object $settings
* @access public
* @return bool
*/
public function updateConfig(object $instance, ?object $settings = null): bool
{
$apiParams = array();
$apiParams['cluster'] = '';
$apiParams['namespace'] = $instance->spaceData->k8space;
$apiParams['name'] = $instance->k8name;
$apiParams['channel'] = empty($instance->channel) ? $this->config->CNE->api->channel : $instance->channel;
$apiParams['chart'] = $instance->chart;
if(isset($instance->version)) $apiParams['version'] = $instance->version;
if(isset($settings->force_restart)) $apiParams['force_restart'] = $settings->force_restart;
if(isset($settings->settings)) $apiParams['settings'] = $settings->settings;
if(isset($settings->settings_map)) $apiParams['settings_map'] = $settings->settings_map;
if(isset($settings->settings_snippets)) $apiParams['settings_snippets'] = $settings->settings_snippets;
$apiUrl = "/api/cne/app/settings";
$result = $this->apiPost($apiUrl, $apiParams, $this->config->CNE->api->headers);
if($result && $result->code == 200) return true;
return false;
}
/**
* 校验证书。
* Valid Certificate.
*
* @param string $certName
* @param string $pem
* @param string $key
* @param string $domain
* @access public
* @return object
*/
public function validateCert(string $certName, string $pem, string $key, string $domain)
{
$apiParams = array();
$apiParams['name'] = $certName;
$apiParams['certificate_pem'] = $pem;
$apiParams['private_key_pem'] = $key;
$apiUrl = "/api/cne/system/tls/validator";
$result = $this->apiPost($apiUrl, $apiParams, $this->config->CNE->api->headers);
if($result && $result->code != 200) return $result;
$match = false;
foreach($result->data->sans as $domainPattern)
{
if(stripos($domainPattern, $domain) !== false)
{
$match = true;
break;
}
}
if(!$match)
{
$result->code = 40004;
$result->message = zget($this->lang->CNE->errorList, 40004);
}
return $result;
}
/**
* 更新证书。
* Upload cert.
*
* @param object $cert
* @param string $channel
* @access public
* @return object
*/
public function uploadCert(object $cert, string $channel = ''): ?object
{
$apiParams = array();
$apiParams['cluster'] = '';
$apiParams['channel'] = empty($channel) ? $this->config->CNE->api->channel : $channel;
$apiParams['name'] = $cert->name;
$apiParams['certificate_pem'] = $cert->certificate_pem;
$apiParams['private_key_pem'] = $cert->private_key_pem;
return $this->apiPost('/api/cne/system/tls/upload', $apiParams, $this->config->CNE->api->headers);
}
/**
* 获取证书信息。
* Get cert info.
*
* @param string $certName
* @param string $channel
* @access public
* @return object|null success: return cert info, fail: return null.
*/
public function certInfo(string $certName, string $channel = ''): ?object
{
$apiParams = array();
$apiParams['cluster'] = '';
$apiParams['channel'] = empty($channel) ? $this->config->CNE->api->channel : $channel;
$apiParams['name'] = $certName;
$apiUrl = "/api/cne/system/tls/info";
$result = $this->apiGet($apiUrl, $apiParams, $this->config->CNE->api->headers);
if($result && $result->code == 200) return $result->data;
return null;
}
/**
* 获取实例的默认账号密码。
* Get default username and password of app.
*
* @param object $instance
* @param string $component
* @access public
* @return object|null
*/
public function getDefaultAccount(object $instance, string $component = ''): ?object
{
$apiUrl = '/api/cne/app/account?channel='. (empty($instance->channel) ? $this->config->CNE->api->channel : $instance->channel);
$apiParams = array();
$apiParams['name'] = $instance->k8name;
$apiParams['namespace'] = $instance->spaceData->k8space;
$apiParams['cluster'] = '';
if($component) $apiParams['component'] = $component;
$result = $this->apiGet($apiUrl, $apiParams, $this->config->CNE->api->headers, $this->config->CNE->api->host);
if(!isset($result->code) || $result->code != 200) return null;
$account = $result->data;
if(isset($account->username) && $account->username && isset($account->password) && $account->password) return $account;
return null;
}
/**
* 获取域名后缀。
* Get suffix domain.
*
* @access public
* @return string
*/
public function sysDomain(): string
{
$customDomain = $this->loadModel('setting')->getItem('owner=system&module=common&section=domain&key=customDomain');
if($customDomain) return $customDomain;
if(getenv('APP_DOMAIN')) return getenv('APP_DOMAIN');
if(!empty($this->config->CNE->app->domain)) return $this->config->CNE->app->domain;
return '';
}
/**
* 获取实例的域名。
* Get domain.
*
* @param object $instance
* @param string $component
* @access public
* @return object|null
*/
public function getDomain(object $instance, string $component = ''): ?object
{
$apiUrl = '/api/cne/app/domain?channel='. (empty($instance->channel) ? $this->config->CNE->api->channel : $instance->channel);
$apiParams = array();
$apiParams['name'] = $instance->k8name;
$apiParams['namespace'] = $instance->spaceData->k8space;
$apiParams['cluster'] = '';
if($component) $apiParams['component'] = $component;
$result = $this->apiGet($apiUrl, $apiParams, $this->config->CNE->api->headers, $this->config->CNE->api->host);
if(!isset($result->code) || $result->code != 200) return null;
return empty($result->data->internal_host) ? null : $result->data;
}
/**
* 获取CNE平台的集群度量。
* Get cluster metrics of CNE platform.
*
* @access public
* @return object
*/
public function cneMetrics(): object
{
$metrics = new stdclass();
$metrics->cpu = new stdclass();
$metrics->cpu->usage = 0;
$metrics->cpu->capacity = 0;
$metrics->cpu->allocatable = 0;
$metrics->cpu->rate = 0;
$metrics->memory = new stdclass();
$metrics->memory->usage = 0;
$metrics->memory->capacity = 0;
$metrics->memory->allocatable = 0;
$metrics->memory->rate = 0;
$statistics = new stdclass();
$statistics->status = 'unknown';
$statistics->node_count = 0;
$statistics->metrics = $metrics;
$result = $this->apiGet('/api/cne/statistics/cluster', array('cluster' => ''), $this->config->CNE->api->headers);
if($result->code != 200) return $statistics;
$nodes = $this->apiGet('/api/cne/cluster/nodes', array('cluster' => ''), $this->config->CNE->api->headers);
if($nodes->code != 200) return $statistics;
$readyNode = 0;
$nodeError = '';
foreach($nodes->data as $node)
{
if($node->ready)
{
$readyNode++;
}
else
{
if(empty($node->issues)) continue;
$nodeError .= sprintf($this->lang->system->nodeNotice, $node->name, implode(',', array_unique($node->issues))) . "\n";
}
}
$statistics = $result->data;
$statistics->node_count = count($nodes->data);
$statistics->ready_count = $readyNode;
$statistics->nodeError = $nodeError;
$statistics->metrics->cpu->usage = max(round($statistics->metrics->cpu->usage, 4), 0);
$statistics->metrics->cpu->capacity = max(round($statistics->metrics->cpu->capacity, 4), $statistics->metrics->cpu->usage);
$statistics->metrics->cpu->allocatable = round($statistics->metrics->cpu->allocatable, 4);
$statistics->metrics->cpu->rate = $statistics->metrics->cpu->capacity > 0 ? round( $statistics->metrics->cpu->usage / $statistics->metrics->cpu->capacity * 100, 2) : 0;
$statistics->metrics->cpu->rate = min($statistics->metrics->cpu->rate, 100);
$statistics->metrics->memory->usage = max(round($statistics->metrics->memory->usage, 4), 0);
$statistics->metrics->memory->capacity = max($statistics->metrics->memory->capacity, $statistics->metrics->memory->usage);
$statistics->metrics->memory->rate = $statistics->metrics->memory->capacity > 0 ? round($statistics->metrics->memory->usage / $statistics->metrics->memory->capacity * 100, 2) : 0;
$statistics->metrics->memory->rate = min($statistics->metrics->memory->rate, 100);
return $statistics;
}
/**
* Get the volumes metrics of the instance.
*
* @param object $instance
* @return object
*/
public function getVolumesMetrics(object $instance): object
{
$metric = new stdclass;
$metric->limit = 0;
$metric->usage = 0;
$metric->rate = 0;
$volumes = $this->getAppVolumes($instance);
if($volumes)
{
foreach($volumes as $volume)
{
if(!$volume->is_block_device) return $metric;
$metric->limit = $volume->size;
$metric->usage = $volume->actual_size;
break;
}
}
$metric->rate = $metric->limit != 0 ? round($metric->usage / $metric->limit * 100, 2) : 0.01;
return $metric;
}
/**
* 获取磁盘配置信息。
* Get the disk settings.
*
* @param object $instance
* @return object
*/
public function getDiskSettings(object $instance, bool|string $component = false): object
{
$diskSetting = new stdclass;
$diskSetting->resizable = false;
$diskSetting->size = 0;
$diskSetting->used = 0;
$diskSetting->limit = 0;
$diskSetting->name = '';
$diskSetting->requestSize = 0;
$volumes = $this->getAppVolumes($instance, $component);
if($volumes)
{
foreach($volumes as $volume)
{
if(!$volume->is_block_device) return $diskSetting;
$diskSetting->resizable = true;
$diskSetting->size = ceil($volume->size / 1073741824);
$diskSetting->used = ceil($volume->actual_size / 1073741824);
$diskSetting->limit = floor($volume->max_increase_size / 1073741824);
$diskSetting->name = $volume->setting_keys->size->path;
$diskSetting->requestSize = ceil($volume->request_size / 1073741824);
break;
}
}
return $diskSetting;
}
/**
* 获取平台实例的度量。
* Get instance metrics.
*
* @param array $instances
* @param bool $volumesMetrics
* @access public
* @return array
*/
public function instancesMetrics(array $instances, bool $volumesMetrics = true): array
{
$instancesMetrics = array();
$apiData = array('cluster' => '', 'apps' => array());
foreach($instances as $instance)
{
if($instance->source == 'external') continue;
$appData = new stdclass();
$appData->name = $instance->k8name;
$appData->namespace = $instance->spaceData->k8space;
$apiData['apps'][] = $appData;
$instanceMetric = new stdclass();
$instanceMetric->id = $instance->id;
$instanceMetric->name = $instance->k8name;
$instanceMetric->namespace = $instance->spaceData->k8space;
$instanceMetric->cpu = new stdclass();
$instanceMetric->cpu->limit = 0;
$instanceMetric->cpu->usage = 0;
$instanceMetric->cpu->rate = 0;
$instanceMetric->memory = new stdclass();
$instanceMetric->memory->limit = 0;
$instanceMetric->memory->usage = 0;
$instanceMetric->memory->rate = 0;
if($volumesMetrics) $instanceMetric->disk = $this->getVolumesMetrics($instance);
$instancesMetrics[$instance->k8name] = $instanceMetric;
}
$result = $this->apiPost('/api/cne/statistics/app', $apiData, $this->config->CNE->api->headers);
if(!isset($result->code) || $result->code != 200)return array_combine(helper::arrayColumn($instancesMetrics, 'id'), $instancesMetrics);
foreach($result->data as $k8sMetric)
{
if(!isset($k8sMetric->metrics)) continue;
$instancesMetrics[$k8sMetric->name]->cpu->usage = isset($k8sMetric->metrics->cpu) && isset($k8sMetric->metrics->cpu->usage) ? round($k8sMetric->metrics->cpu->usage, 4) : 0;
$instancesMetrics[$k8sMetric->name]->cpu->usage = max($instancesMetrics[$k8sMetric->name]->cpu->usage, 0);
$instancesMetrics[$k8sMetric->name]->cpu->limit = isset($k8sMetric->metrics->cpu) && isset($k8sMetric->metrics->cpu->limit) ? round($k8sMetric->metrics->cpu->limit, 4) : 0;
$instancesMetrics[$k8sMetric->name]->cpu->limit = max($instancesMetrics[$k8sMetric->name]->cpu->limit, $instancesMetrics[$k8sMetric->name]->cpu->usage);
$instancesMetrics[$k8sMetric->name]->cpu->rate = $instancesMetrics[$k8sMetric->name]->cpu->limit > 0 ? round($instancesMetrics[$k8sMetric->name]->cpu->usage / $instancesMetrics[$k8sMetric->name]->cpu->limit * 100, 2) : 0;
$instancesMetrics[$k8sMetric->name]->memory->usage = isset($k8sMetric->metrics->memory) && isset($k8sMetric->metrics->memory->usage) ? $k8sMetric->metrics->memory->usage : 0;
$instancesMetrics[$k8sMetric->name]->memory->usage = max($instancesMetrics[$k8sMetric->name]->memory->usage, 0);
$instancesMetrics[$k8sMetric->name]->memory->limit = isset($k8sMetric->metrics->memory) && isset($k8sMetric->metrics->memory->limit) ? $k8sMetric->metrics->memory->limit : 0;
$instancesMetrics[$k8sMetric->name]->memory->limit = max( $instancesMetrics[$k8sMetric->name]->memory->limit, $instancesMetrics[$k8sMetric->name]->memory->usage);
$instancesMetrics[$k8sMetric->name]->memory->rate = $instancesMetrics[$k8sMetric->name]->memory->limit > 0 ? round($instancesMetrics[$k8sMetric->name]->memory->usage / $instancesMetrics[$k8sMetric->name]->memory->limit * 100, 2) : 0;
}
return array_combine(helper::arrayColumn($instancesMetrics, 'id'), $instancesMetrics);
}
/**
* 备份一个应用实例。
* Backup a instance with account.
*
* @param object $instance
* @param string $account
* @param string $mode |manual|system|upgrade|downgrade
* @access public
* @return object
*/
public function backup(object $instance, string|null $account = '', string $mode = ''): object
{
$apiParams = new stdclass;
$apiParams->username = $account ?: $this->app->user->account;
$apiParams->cluster = '';
$apiParams->namespace = $instance->spaceData->k8space;
$apiParams->name = $instance->k8name;
$apiParams->channel = empty($instance->channel) ? $this->config->CNE->api->channel : $instance->channel;
if(!empty($mode)) $apiParams->mode = $mode;
$apiUrl = "/api/cne/app/backup";
return $this->apiPost($apiUrl, $apiParams, $this->config->CNE->api->headers);
}
/**
* 获取备份的进度。
* Get the status of backup progress.
*
* @param object $instance
* @param string $backupName
* @access public
* @return object
*/
public function getBackupStatus(object $instance, string $backupName): object
{
$apiParams = new stdclass;
$apiParams->cluster = '';
$apiParams->namespace = $instance->spaceData->k8space;
$apiParams->name = $instance->k8name;
$apiParams->backup_name = $backupName;
$apiParams->channel = empty($instance->channel) ? $this->config->CNE->api->channel : $instance->channel;
$apiUrl = "/api/cne/app/backup/status";
return $this->apiGet($apiUrl, $apiParams, $this->config->CNE->api->headers);
}
/**
* 获取备份列表。
* Get the backup list.
*
* @param object $instance
* @access public
* @return object
*/
public function getBackupList(object $instance): object
{
$apiParams = new stdclass;
$apiParams->cluster = '';
$apiParams->namespace = $instance->spaceData->k8space;
$apiParams->name = $instance->k8name;
$apiParams->channel = empty($instance->channel) ? $this->config->CNE->api->channel : $instance->channel;
$apiUrl = "/api/cne/app/backups";
return $this->apiGet($apiUrl, $apiParams, $this->config->CNE->api->headers);
}
/**
* 删除一个备份.
* Delete backup.
*
* @param object $instance
* @param string $backupName
* @access public
* @return object
*/
public function deleteBackup(object $instance, string $backupName): object
{
$apiParams = new stdclass;
$apiParams->cluster = '';
$apiParams->namespace = $instance->spaceData->k8space;
$apiParams->name = $instance->k8name;
$apiParams->backup_name = $backupName;
$apiParams->channel = empty($instance->channel) ? $this->config->CNE->api->channel : $instance->channel;
$apiUrl = "/api/cne/app/backup/remove";
return $this->apiPost($apiUrl, $apiParams, $this->config->CNE->api->headers);
}
/**
* 恢复一个备份。
* Restore from the backup.
*
* @param object $instance
* @param object $backupName
* @param string $account
* @access public
* @return object
*/
public function restore(object $instance, string $backupName, string $account = ''): object
{
$apiParams = new stdclass;
$apiParams->username = $account ?: $this->app->user->account;
$apiParams->cluster = '';
$apiParams->namespace = $instance->spaceData->k8space;
$apiParams->name = $instance->k8name;
$apiParams->backup_name = $backupName;
$apiParams->channel = empty($instance->channel) ? $this->config->CNE->api->channel : $instance->channel;
$apiUrl = "/api/cne/app/restore";
return $this->apiPost($apiUrl, $apiParams, $this->config->CNE->api->headers);
}
/**
* 获取备份恢复的状态。
* Get the status of restore progress.
*
* @param object $instance
* @param string $backupName
* @access public
* @return object
*/
public function getRestoreStatus(object $instance, string $backupName): object
{
$apiParams = new stdclass;
$apiParams->cluster = '';
$apiParams->namespace = $instance->spaceData->k8space;
$apiParams->name = $instance->k8name;
$apiParams->restore_name = $backupName;
$apiParams->channel = empty($instance->channel) ? $this->config->CNE->api->channel : $instance->channel;
$apiUrl = "/api/cne/app/restore/status";
return $this->apiGet($apiUrl, $apiParams, $this->config->CNE->api->headers);
}
/**
* 启动一个应用实例。
* Start an app instance.
*
* @param object $apiParams
* @access public
* @return object
*/
public function startApp(object $apiParams): ?object
{
if(empty($apiParams->channel)) $apiParams->channel = $this->config->CNE->api->channel;
$apiUrl = "/api/cne/app/start";
return $this->apiPost($apiUrl, $apiParams, $this->config->CNE->api->headers);
}
/**
* 停止一个应用实例。
* Stop an app instance.
*
* @param object $apiParams
* @access public
* @return object
*/
public function stopApp(object $apiParams): ?object
{
if(empty($apiParams->channel)) $apiParams->channel = $this->config->CNE->api->channel;
$apiUrl = "/api/cne/app/stop";
return $this->apiPost($apiUrl, $apiParams, $this->config->CNE->api->headers);
}
/**
* 安装应用。
* Install app.
*
* @param object $apiParams
* @access public
* @return object
*/
public function installApp(object $apiParams): ?object
{
if(empty($apiParams->channel)) $apiParams->channel = $this->config->CNE->api->channel;
$apiUrl = "/api/cne/app/install";
return $this->apiPost($apiUrl, $apiParams, $this->config->CNE->api->headers);
}
/**
* 卸载应用。
* Uninstall an app instance.
*
* @param object $apiParams
* @access public
* @return object
*/
public function uninstallApp(object $apiParams): ?object
{
if(empty($apiParams->name)) return null;
if(empty($apiParams->channel)) $apiParams->channel = $this->config->CNE->api->channel;
$apiUrl = "/api/cne/app/uninstall";
return $this->apiPost($apiUrl, $apiParams, $this->config->CNE->api->headers);
}
/**
* 获取应用组件列表
* Get app components.
*
* @link https://yapi.qc.oop.cc/project/21/interface/api/1043
* @param object $instance
* @return object|null
*/
public function getComponents(object $instance): ?object
{
$apiParams = new stdClass();
$apiParams->cluster = '';
$apiParams->namespace = $instance->spaceData->k8space;
$apiParams->name = $instance->k8name;
return $this->apiGet('/api/cne/app/components', $apiParams, $this->config->CNE->api->headers);
}
/**
* 获取应用 pod 列表
* Get app pods.
*
* @link https://yapi.qc.oop.cc/project/21/interface/api/189
* @param object $instance 应用实例对象
* @param string $component 组件名称
* @return object|null
*/
public function getPods(object $instance, string $component = ''): ?object
{
$apiParams = new stdClass();
$apiParams->cluster = '';
$apiParams->namespace = $instance->spaceData->k8space;
$apiParams->name = $instance->k8name;
!empty($component) && $apiParams->component = $component;
return $this->apiGet('/api/cne/app/pods', $apiParams, $this->config->CNE->api->headers);
}
/**
* 获取应用事件列表。
* Get app events.
*
* @param object $instance
* @param string $component
* @return object|null
*/
public function getEvents(object $instance, string $component = ''): ?object
{
$apiParams = new stdClass();
$apiParams->cluster = '';
$apiParams->namespace = $instance->spaceData->k8space;
$apiParams->name = $instance->k8name;
!empty($component) && $apiParams->component = $component;
return $this->apiGet('/api/cne/app/events', $apiParams, $this->config->CNE->api->headers);
}
/**
* 获取应用的安装日志。
* Get app install logs.
*
* @param ?object $instance
* @access public
* @return object
*/
public function getAppLogs(?object $instance, string $component = '', string $pod = '', string $container = '', bool $previous = false): ?object
{
if(!isset($this->app->user->account))
{
$this->app->user = new stdClass();
$this->app->user->account = $this->dao->select('*')->from(TABLE_USER)->where('deleted')->eq(0)->fetch('account');
}
$defaultSpace = $this->loadModel('space')->defaultSpace($this->app->user->account);
$apiParams = new stdClass();
$apiParams->cluster = '';
$apiParams->namespace = !empty($instance->spaceData->k8space) ? $instance->spaceData->k8space : $defaultSpace->k8space;
$apiParams->name = $instance->k8name;
$apiParams->tail = 500;
!empty($component) && $apiParams->component = $component;
!empty($pod) && $apiParams->pod_name = $pod;
!empty($container) && $apiParams->container_name = $container;
$previous && $apiParams->previous = $previous;
return $this->apiGet('/api/cne/app/logs', $apiParams, $this->config->CNE->api->headers);
}
/**
* 查询应用的数据卷。
* Get app volumes.
*
* @link https://yapi.qc.oop.cc/project/21/interface/api/168
* @param object $instance
* @param bool|string $component true|'mysql'
* @return object|array|false
*/
public function getAppVolumes(object $instance, bool|string $component = false): object|array|false
{
$apiParams = new stdclass();
$apiParams->cluster = '';
$apiParams->namespace = $instance->spaceData->k8space;
$apiParams->name = $instance->k8name;
$apiParams->channel = $this->config->CNE->api->channel;
if($component === true) $apiParams->component = 'mysql';
if(!empty($component) && is_string($component)) $apiParams->component = $component;
$apiUrl = "/api/cne/app/volumes";
$result = $this->apiGet($apiUrl, $apiParams, $this->config->CNE->api->headers);
if(!$result || $result->code != 200) return false;
return $result->data;
}
/**
* 按实例获取设置映射。
* Get settings mapping by instance.
*
* @param object $instance
* @param array $mappings
* @access public
* @return object|null
*/
public function getSettingsMapping(object $instance, array $mappings = array()): ?object
{
if(empty($mappings)) $mappings = array(
array(
"key" => "admin_username",
"type" => "helm",
"path" => "auth.username"
),
array(
"key" => "z_username",
"path" => "z_username",
"type" => "secret"
),
array(
"key" => "z_password",
"path" => "z_password",
"type" => "secret"
),
array(
"key" => "api_token",
"path" => "api_token",
"type" => "secret"
)
);
$apiParams = new stdclass();
$apiParams->cluster = '';
$apiParams->namespace = $instance->spaceData->k8space;
$apiParams->name = $instance->k8name;
$apiParams->mappings = $mappings;
$apiUrl = "/api/cne/app/settings/mapping";
$result = $this->apiPost($apiUrl, $apiParams, $this->config->CNE->api->headers);
if($result && $result->code != 200) return null;
return $result->data;
}
/**
* 获取应用配置和资源。
* Get app config and resource.
*
* @param object $instance
* @access public
* @return object|false
*/
public function getAppConfig(object $instance): object|false
{
$apiParams = new stdclass();
$apiParams->cluster = '';
$apiParams->namespace = $instance->spaceData->k8space;
$apiParams->name = $instance->k8name;
$apiParams->channel = $this->config->CNE->api->channel;
$apiUrl = "/api/cne/app/settings/common";
$result = $this->apiGet($apiUrl, $apiParams, $this->config->CNE->api->headers);
if($result && $result->code != 200) return false;
$resources = new stdclass();
$resources->cpu = 0;
$resources->memory = 0;
$result->data->min = zget($result->data, 'oversold', $resources);
$result->data->max = zget($result->data, 'resources', $resources);
return $result->data;
}
/**
* 获取应用实例状态。
* Query status of an app instance.
*
* @param object $instance
* @access public
* @return object
*/
public function queryStatus(object $instance): ?object
{
$apiParams = new stdclass();
$apiParams->cluster = '';
$apiParams->name = $instance->k8name;
$apiParams->chart = $instance->chart;
$apiParams->namespace = $instance->spaceData->k8space;
$apiParams->channel = empty($instance->channel) ? $this->config->CNE->api->channel : $instance->channel;
$apiUrl = "/api/cne/app/status";
$result = $this->apiGet($apiUrl, $apiParams, $this->config->CNE->api->headers);
if($result && $result->code == 200) return $result;
return $result;
}
/**
* 批量获取应用实例状态。
* Query status of instance list.
*
* @param array $instanceList
* @access public
* @return array
*/
public function batchQueryStatus(array $instanceList): array
{
$apiParams = new stdclass();
$apiParams->cluster = '';
$apiParams->apps = array();
foreach($instanceList as $instance)
{
$app = new stdclass();
$app->name = $instance->k8name;
$app->chart = $instance->chart;
$app->namespace = $instance->spaceData->k8space;
$app->channel = empty($instance->channel) ? $this->config->CNE->api->channel : $instance->channel;
$apiParams->apps[] = $app;
}
$apiUrl = "/api/cne/app/status/multi";
$result = $this->apiPost($apiUrl, $apiParams, $this->config->CNE->api->headers);
if(empty($result) || $result->code != 200) return array();
$statusList = array();
foreach($result->data as $status) $statusList[$status->name] = $status;
return $statusList;
}
/**
* 获取应用的数据库列表。
* Get all database list of app.
*
* @param object $instance
* @access public
* @return array
*/
public function appDBList(object $instance): array
{
$apiUrl = "/api/cne/app/dbs";
$apiParams = array();
$apiParams['cluster'] = '';
$apiParams['name'] = $instance->k8name;
$apiParams['namespace'] = $instance->spaceData->k8space;
$apiParams['channel'] = $this->config->CNE->api->channel;
$result = $this->apiGet($apiUrl, $apiParams, $this->config->CNE->api->headers);
if(empty($result) || $result->code != 200 || empty($result->data)) return array();
$dbList = $result->data;
return array_combine(helper::arrayColumn($dbList, 'name'), $dbList);
}
/**
* 获取应用数据库的详细信息。
* Get detail of app database.
*
* @param object $instance
* @param string $dbName
* @access public
* @return object|false
*/
public function appDBDetail(object $instance, string $dbName): object|false
{
$apiParams = array();
$apiParams['cluster'] = '';
$apiParams['name'] = $instance->k8name;
$apiParams['namespace'] = $instance->spaceData->k8space;
$apiParams['db'] = $dbName;
$apiParams['channel'] = $this->config->CNE->api->channel;
$apiUrl = "/api/cne/app/dbs/detail";
$result = $this->apiGet($apiUrl, $apiParams, $this->config->CNE->api->headers);
if(empty($result) || $result->code != 200 || empty($result->data)) return false;
return $result->data;
}
/**
* 获取数据库配置。
* Get database detail.
*
* @param string $dbService
* @param string $namespace
* @access public
* @return object|false
*/
public function dbDetail(string $dbService, string $namespace): object|false
{
$apiUrl = "/api/cne/component/dbservice/detail";
$apiParams = array('name' => $dbService, 'namespace' => $namespace, 'channel' => $this->config->CNE->api->channel);
$result = $this->apiGet($apiUrl, $apiParams, $this->config->CNE->api->headers);
if(empty($result) || $result->code != 200 || empty($result->data)) return false;
return $result->data;
}
/**
* 获取数据库列表。
* Get all database list.
*
* @access public
* @return array
*/
public function allDBList(): array
{
$apiUrl = "/api/cne/component/dbservice";
$apiParams = array('global' => 'true', 'namespace' => $this->config->k8space, 'channel' => $this->config->CNE->api->channel);
$result = $this->apiGet($apiUrl, $apiParams, $this->config->CNE->api->headers);
if(empty($result) || $result->code != 200 || empty($result->data)) return array();
$dbList = $result->data;
return array_combine(helper::arrayColumn($dbList, 'name'), $dbList);
}
/**
* 获取共享数据库列表。
* Get shared database list.
*
* @param string $dbType
* @access public
* @return array
*/
public function sharedDBList(string $dbType = 'mysql'): array
{
$apiUrl = "/api/cne/component/gdb";
$apiParams = array('kind' => $dbType, 'namespace' => 'default', 'channel' => $this->config->CNE->api->channel);
$result = $this->apiGet($apiUrl, $apiParams, $this->config->CNE->api->headers);
if(empty($result) || $result->code != 200 || empty($result->data)) return array();
$dbList = $result->data;
return array_combine(helper::arrayColumn($dbList, 'name'), $dbList);
}
/**
* 校验数据库名称和用户是否可用。
* Validate database name and user.
*
* @param string $dbService
* @param string $dbUser
* @param string $dbName
* @param string $namespace
* @access public
* @return object
*/
public function validateDB(string $dbService, string $dbUser, string $dbName, string $namespace): object
{
$apiParams = array();
$apiParams['name'] = $dbService;
$apiParams['user'] = $dbUser;
$apiParams['database'] = $dbName;
$apiParams['namespace'] = $namespace;
$apiUrl = "/api/cne/component/gdb/validation";
$result = $this->apiGet($apiUrl, $apiParams, $this->config->CNE->api->headers);
if($result && $result->code == 200) return $result->data->validation;
$validation = new stdclass();
$validation->user = true;
$validation->database = true;
return $validation;
}
/**
* 通过Get方式调用API。
* Get method of API.
*
* @param string $url
* @param array|object $data
* @param array $header example: array("key1:value1", "key2:value2")
* @param string $host
* @access public
* @return object
*/
public function apiGet(string $url, array|object $data, array $header = array(), string $host = ''): object
{
$requestUri = ($host ? $host : $this->config->CNE->api->host) . $url;
$requestUri .= (strpos($url, '?') !== false ? '&' : '?') . http_build_query($data, '', '&', PHP_QUERY_RFC3986);
$result = json_decode(commonModel::http($requestUri, $data, array(CURLOPT_CUSTOMREQUEST => 'GET'), $header, 'json', 'GET', 20));
if($result && $result->code == 200) return $result;
if($result) return $this->translateError($result);
return $this->cneServerError();
}
/**
* 通过Post方式调用API。
* Post method of API.
*
* @param string $url
* @param array|object $data
* @param array $header example: array("key1:value1", "key2:value2")
* @param string $host
* @access public
* @return object
*/
public function apiPost(string $url, array|object $data, array $header = array(), string $host = ''): object
{
$requestUri = ($host ? $host : $this->config->CNE->api->host) . $url;
$result = json_decode(commonModel::http($requestUri, $data, array(CURLOPT_CUSTOMREQUEST => 'POST'), $header, 'json', 'POST', 20));
if($result && in_array($result->code, array(200, 201)))
{
$result->code = 200;
return $result;
}
if($result) return $this->translateError($result);
return $this->cneServerError();
}
/**
* 返回API服务器错误对象。
* Return error object of api server.
*
* @access protected
* @return object
*/
protected function cneServerError(): object
{
$error = new stdclass();
$error->code = 600;
$error->message = $this->lang->CNE->serverError;
return $error;
}
/**
* 翻译错误信息。
* Translate error message for multi language.
*
* @param object $apiResult
* @access protected
* @return object
*/
protected function translateError(object &$apiResult): object
{
$this->error->code = $apiResult->code;
$this->error->message = zget($this->lang->CNE->errorList, $apiResult->code, $this->lang->CNE->serverError); // Translate CNE api error message to multi language.
if($this->config->debug)
{
if(isset($apiResult->code)) $this->error->message .= " [{$apiResult->code}]:";
if(isset($apiResult->message)) $this->error->message .= " [{$apiResult->message}]";
}
$apiResult->message = $this->error->message;
return $this->error;
}
/**
* app资源调度尝试。
* Try allocate for apps.
*
* @param array $apps
* @access public
* @return object
*/
public function tryAllocate(array $resources): object
{
$apiParams = new stdclass();
$apiParams->requests = $resources;
$apiUrl = "/api/cne/system/resource/try-allocate";
return $this->apiPost($apiUrl, $apiParams, $this->config->CNE->api->headers);
}
/**
* 升级禅道DevOps平台版。
* Upgrade the quickon system.
*
* @param string $edition oss|open|biz|max|ipd
* @return object|false
*/
public function upgrade($edition = 'oss'): object|false
{
$numArgs = func_num_args();
if($numArgs == 0) $edition = $this->config->edition;
if($edition == 'open') $edition = 'oss';
$version = $this->loadModel('system')->getLatestRelease();
if(!$version) return false;
$apiParams = array(
'channel' => getenv('CLOUD_DEFAULT_CHANNEL') ?: 'stable',
'version' => $version->version,
'product' => $edition
);
$apiUrl = "/api/cne/system/update";
return $this->apiPost($apiUrl, $apiParams, $this->config->CNE->api->headers);
}
/**
* 获取备份的详细信息。
* Get backup detail.
*
* @param object $instance
* @param string $backupName
* @access public
* @return object|false
*/
public function backupDetail(object $instance, string $backupName): object|false
{
if(empty($instance->k8name) || empty($instance->spaceData)) return false;
$apiUrl = "/api/cne/app/backup/detail";
$apiParams = array('name' => $instance->k8name, 'namespace' => $instance->spaceData->k8space, 'backup_name' => $backupName);
$result = $this->apiGet($apiUrl, $apiParams, $this->config->CNE->api->headers);
if(empty($result) || $result->code != 200 || empty($result->data)) return false;
return $result->data;
}
}