znt/module/cne/model.php

1162 lines
41 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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;
}
}