- [refactor] remove solution module
This commit is contained in:
@@ -621,7 +621,6 @@ define('TABLE_METRICRECORDS', '`' . $config->db->prefix . 'metricrecords`');
|
||||
|
||||
define('TABLE_SPACE', '`' . $config->db->prefix . 'space`');
|
||||
define('TABLE_INSTANCE', '`' . $config->db->prefix . 'instance`');
|
||||
define('TABLE_SOLUTION', '`' . $config->db->prefix . 'solution`');
|
||||
define('TABLE_ARTIFACTREPO', '`' . $config->db->prefix . 'artifactrepo`');
|
||||
|
||||
define('TABLE_AI_PROMPT', '`' . $config->db->prefix . 'ai_prompt`');
|
||||
@@ -723,7 +722,6 @@ $config->objectTables['serverroom'] = TABLE_SERVERROOM;
|
||||
$config->objectTables['host'] = TABLE_ZAHOST;
|
||||
$config->objectTables['instance'] = TABLE_INSTANCE;
|
||||
$config->objectTables['space'] = TABLE_SPACE;
|
||||
$config->objectTables['solution'] = TABLE_SOLUTION;
|
||||
$config->objectTables['artifactrepo'] = TABLE_ARTIFACTREPO;
|
||||
$config->objectTables['metric'] = TABLE_METRIC;
|
||||
$config->objectTables['cron'] = TABLE_CRON;
|
||||
|
||||
@@ -21,3 +21,5 @@ ALTER TABLE `zt_compile` ADD `branch` varchar(255) NOT NULL DEFAULT '' AFTER `st
|
||||
ALTER TABLE `zt_doc`
|
||||
ADD `templateDesc` text NULL AFTER `templateType`,
|
||||
ADD `builtIn` enum('0','1') NOT NULL DEFAULT '0' AFTER `version`;
|
||||
|
||||
DROP TABLE IF EXISTS `zt_solution`;
|
||||
|
||||
@@ -15668,29 +15668,6 @@ CREATE TABLE IF NOT EXISTS `zt_instance` (
|
||||
KEY `k8name` (`k8name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- DROP TABLE IF EXISTS `zt_solution`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_solution` (
|
||||
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` char(50) NOT NULL DEFAULT '',
|
||||
`appID` mediumint(8) unsigned NOT NULL DEFAULT 0,
|
||||
`appName` char(50) NOT NULL DEFAULT '',
|
||||
`appVersion` char(20) NOT NULL DEFAULT '',
|
||||
`version` char(50) NOT NULL DEFAULT '',
|
||||
`chart` char(50) NOT NULL DEFAULT '',
|
||||
`cover` varchar(255) NOT NULL DEFAULT '',
|
||||
`desc` text NULL,
|
||||
`introduction` varchar(255) NOT NULL DEFAULT '',
|
||||
`source` char(20) NOT NULL DEFAULT '',
|
||||
`channel` char(20) NOT NULL DEFAULT '',
|
||||
`components` text NULL,
|
||||
`status` char(20) NOT NULL DEFAULT '',
|
||||
`deleted` tinyint(1) NOT NULL DEFAULT 0,
|
||||
`createdBy` char(30) NOT NULL DEFAULT '',
|
||||
`createdAt` datetime NULL,
|
||||
`updatedDate` datetime NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
|
||||
-- DROP TABLE IF EXISTS `zt_demandpool`;
|
||||
CREATE TABLE IF NOT EXISTS `zt_demandpool` (
|
||||
`id` int(8) NOT NULL AUTO_INCREMENT,
|
||||
|
||||
@@ -455,133 +455,6 @@ class install extends control
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* 展示应用安装进度。
|
||||
* Show installation progress of solution.
|
||||
*
|
||||
* @param int $id
|
||||
* @param bool $startInstall
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function progress(int $id, bool $startInstall = false)
|
||||
{
|
||||
$solution = $this->loadModel('solution')->getByID($id);
|
||||
|
||||
$this->view->title = $this->lang->solution->progress;
|
||||
$this->view->solution = $solution;
|
||||
$this->view->startInstall = $startInstall;
|
||||
|
||||
$this->app->loadConfig('message');
|
||||
$this->config->message->browser->turnon = 0;
|
||||
$this->display();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取安装进度。
|
||||
* AJAX: Get installing progress of solution.
|
||||
*
|
||||
* @param int $id
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxProgress(int $id)
|
||||
{
|
||||
$this->loadModel('common');
|
||||
$solution = $this->loadModel('solution')->getByID($id);
|
||||
$result = 'success';
|
||||
$message = '';
|
||||
$logs = array();
|
||||
|
||||
if($solution->status == 'installed') return $this->send(array('result' => $result, 'message' => $message, 'data' => json_decode($solution->components), 'logs' => $logs));
|
||||
|
||||
if($solution->status != 'installing')
|
||||
{
|
||||
$result = 'fail';
|
||||
$message = zget($this->lang->solution->installationErrors, $solution->status, $this->lang->solution->errors->hasInstallationError);
|
||||
return $this->send(array('result' => $result, 'message' => $message, 'data' => json_decode($solution->components), 'logs' => $logs));
|
||||
}
|
||||
|
||||
if((time() - strtotime($solution->updatedDate)) > 60 * 20)
|
||||
{
|
||||
$this->solution->saveStatus($id, 'timeout');
|
||||
$result = 'fail';
|
||||
$message = $this->lang->solution->errors->timeout;
|
||||
return $this->send(array('result' => $result, 'message' => $message, 'data' => json_decode($solution->components), 'logs' => $logs));
|
||||
}
|
||||
|
||||
$components = json_decode($solution->components);
|
||||
foreach($components as $componentApp)
|
||||
{
|
||||
if($componentApp->status != 'installing') continue;
|
||||
|
||||
$instance = $this->loadModel('instance')->instanceOfSolution($solution, $componentApp->chart);
|
||||
if(!$instance) continue;
|
||||
|
||||
$chartLogs = $this->loadModel('cne')->getAppLogs($instance);
|
||||
$logs[$componentApp->chart] = !empty($chartLogs->data) ? $chartLogs->data : array();
|
||||
}
|
||||
return $this->send(array('result' => $result, 'message' => $message, 'data' => json_decode($solution->components), 'logs' => $logs));
|
||||
}
|
||||
|
||||
/**
|
||||
* 安装应用。
|
||||
* AJAX: Start install.
|
||||
*
|
||||
* @param int $solutionID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxInstall(int $solutionID)
|
||||
{
|
||||
$this->loadModel('solution')->install($solutionID);
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
|
||||
return $this->send(array('result' => 'success', 'message' => '', 'locate' => $this->inLink('step6')));
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消安装时卸载应用。
|
||||
* AJAX: Uninstall app.
|
||||
*
|
||||
* @param int $solutionID
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxUninstall(int $solutionID)
|
||||
{
|
||||
$this->loadModel('common');
|
||||
$this->loadModel('solution')->uninstall($solutionID);
|
||||
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
|
||||
|
||||
return $this->send(array('result' => 'success', 'message' => '', 'load' => $this->inLink('app')));
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查内存与CPU是否满足安装所需。
|
||||
* AJAX: Check memory and cpu.
|
||||
*
|
||||
* @access public
|
||||
* @return void
|
||||
*/
|
||||
public function ajaxCheck()
|
||||
{
|
||||
$this->loadModel('common');
|
||||
|
||||
$apps = (array)$this->post->apps;
|
||||
foreach($apps as $index => $app)
|
||||
{
|
||||
if($app == $this->lang->install->solution->skipInstall) unset($apps[$index]);
|
||||
}
|
||||
|
||||
$appMap = $this->loadModel('store')->getAppMapByNames($apps);
|
||||
$resources = array();
|
||||
foreach($apps as $app) $resources[] = array('cpu' => $appMap->$app->cpu, 'memory' => $appMap->$app->memory);
|
||||
|
||||
$result = $this->loadModel('cne')->tryAllocate($resources);
|
||||
return $this->send(array('result' => 'success', 'message' => '', 'code' => $result->code));
|
||||
}
|
||||
|
||||
/**
|
||||
* 安装DuckDB引擎界面。
|
||||
* Install duckdb.
|
||||
|
||||
@@ -45,7 +45,6 @@ class instanceModel extends model
|
||||
if(!$instance) return null;
|
||||
|
||||
$instance->spaceData = $this->dao->select('*')->from(TABLE_SPACE)->where('id')->eq($instance->space)->fetch();
|
||||
if($instance->solution) $instance->solutionData = $this->dao->select('*')->from(TABLE_SOLUTION)->where('id')->eq($instance->solution)->fetch();
|
||||
|
||||
return $instance;
|
||||
}
|
||||
@@ -98,34 +97,9 @@ class instanceModel extends model
|
||||
$spaces = $this->dao->select('*')->from(TABLE_SPACE)->where('deleted')->eq(0)->andWhere('id')->in(helper::arrayColumn($instances, 'space'))->fetchAll('id');
|
||||
foreach($instances as $instance) $instance->spaceData = zget($spaces, $instance->space, new stdclass);
|
||||
|
||||
$solutionIDList = helper::arrayColumn($instances, 'solution');
|
||||
$solutions = $this->dao->select('*')->from(TABLE_SOLUTION)->where('id')->in($solutionIDList)->fetchAll('id');
|
||||
foreach($instances as $instance) $instance->solutionData = zget($solutions, $instance->solution, new stdclass);
|
||||
|
||||
return $instances;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据解决方案ID获取应用实例列表。
|
||||
* Get instance list by solution.
|
||||
*
|
||||
* @param object $solution
|
||||
* @param string $chart
|
||||
* @access public
|
||||
* @return object|null
|
||||
*/
|
||||
public function instanceOfSolution(object $solution, string $chart): object|null
|
||||
{
|
||||
$instance = $this->dao->select('id')->from(TABLE_INSTANCE)->where('deleted')->eq(0)
|
||||
->andWhere('solution')->eq($solution->id)
|
||||
->andWhere('chart')->eq($chart)
|
||||
->fetch();
|
||||
|
||||
if($instance) return $this->getByID($instance->id);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取应用实例列表。
|
||||
* Get instances list.
|
||||
@@ -159,10 +133,6 @@ class instanceModel extends model
|
||||
|
||||
foreach($instances as $instance) $instance->spaceData = zget($spaces, $instance->space, new stdclass);
|
||||
|
||||
$solutionIDList = helper::arrayColumn($instances, 'solution');
|
||||
$solutions = $this->dao->select('*')->from(TABLE_SOLUTION)->where('id')->in($solutionIDList)->fetchAll('id');
|
||||
foreach($instances as $instance) $instance->solutionData = zget($solutions, $instance->solution, new stdclass);
|
||||
|
||||
return $instances;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ cid=1
|
||||
- 属性name @默认空间1
|
||||
- 查看获取到的第一条instance的solution
|
||||
- 属性id @1
|
||||
- 属性name @解决方案1
|
||||
- 查看获取到的第二条instance
|
||||
- 属性id @2
|
||||
- 属性name @禅道开源版
|
||||
@@ -32,7 +31,6 @@ cid=1
|
||||
- 属性name @默认空间2
|
||||
- 查看获取到的第二条instance的solution
|
||||
- 属性id @2
|
||||
- 属性name @解决方案2
|
||||
- 查看不存在的instance @0
|
||||
|
||||
*/
|
||||
@@ -43,12 +41,10 @@ $tester->loadModel('instance');
|
||||
$instance = $tester->instance->getByID(1);
|
||||
r($instance) && p('id,name,chart') && e('1,Subversion,subversion'); // 查看获取到的第一条instance
|
||||
r($instance->spaceData) && p('id,name') && e('1,默认空间1'); // 查看获取到的第一条instance的space
|
||||
r($instance->solutionData) && p('id,name') && e('1,解决方案1'); // 查看获取到的第一条instance的solution
|
||||
|
||||
$instance = $tester->instance->getByID(2);
|
||||
r($instance) && p('id,name,chart') && e('2,禅道开源版,zentao'); // 查看获取到的第二条instance
|
||||
r($instance->spaceData) && p('id,name') && e('2,默认空间2'); // 查看获取到的第二条instance的space
|
||||
r($instance->solutionData) && p('id,name') && e('2,解决方案2'); // 查看获取到的第二条instance的solution
|
||||
|
||||
$instance = $tester->instance->getByID(10000);
|
||||
r($instance) && p('') && e('0'); // 查看不存在的instance
|
||||
r($instance) && p('') && e('0'); // 查看不存在的instance
|
||||
|
||||
@@ -32,15 +32,6 @@ cid=1
|
||||
- 查看获取到的第三条instance的space的id和name
|
||||
- 属性id @3
|
||||
- 属性name @默认空间3
|
||||
- 查看获取到的第一条instance的solution的id和name
|
||||
- 属性id @1
|
||||
- 属性name @解决方案1
|
||||
- 查看获取到的第二条instance的solution的id和name
|
||||
- 属性id @2
|
||||
- 属性name @解决方案2
|
||||
- 查看获取到的第三条instance的solution的id和name
|
||||
- 属性id @3
|
||||
- 属性name @解决方案3
|
||||
|
||||
*/
|
||||
|
||||
@@ -57,7 +48,3 @@ r($instance) && p('3:id,name') && e('3,adminer'); // 查看获取到的第三
|
||||
r($instance[1]->spaceData) && p('id,name') && e('1,默认空间1'); // 查看获取到的第一条instance的space的id和name
|
||||
r($instance[2]->spaceData) && p('id,name') && e('2,默认空间2'); // 查看获取到的第二条instance的space的id和name
|
||||
r($instance[3]->spaceData) && p('id,name') && e('3,默认空间3'); // 查看获取到的第三条instance的space的id和name
|
||||
|
||||
r($instance[1]->solutionData) && p('id,name') && e('1,解决方案1'); // 查看获取到的第一条instance的solution的id和name
|
||||
r($instance[2]->solutionData) && p('id,name') && e('2,解决方案2'); // 查看获取到的第二条instance的solution的id和name
|
||||
r($instance[3]->solutionData) && p('id,name') && e('3,解决方案3'); // 查看获取到的第三条instance的solution的id和name
|
||||
@@ -1,65 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
su('admin');
|
||||
|
||||
zenData('instance')->gen(5);
|
||||
zenData('space')->gen(5);
|
||||
zenData('solution')->gen(5);
|
||||
|
||||
/**
|
||||
|
||||
title=instanceModel->instanceOfSolution();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 查看获取到的第一条instance
|
||||
- 属性id @1
|
||||
- 属性name @Subversion
|
||||
- 属性chart @subversion
|
||||
- 查看获取到的第一条instance的space
|
||||
- 属性id @1
|
||||
- 属性name @默认空间1
|
||||
- 查看获取到的第一条instance的solution
|
||||
- 属性id @1
|
||||
- 属性name @解决方案1
|
||||
- 查看获取到的第二条instance
|
||||
- 属性id @2
|
||||
- 属性name @禅道开源版
|
||||
- 属性chart @zentao
|
||||
- 查看获取到的第二条instance的space
|
||||
- 属性id @2
|
||||
- 属性name @默认空间2
|
||||
- 查看获取到的第二条instance的solution
|
||||
- 属性id @2
|
||||
- 属性name @解决方案2
|
||||
- 查看不存在的instance @0
|
||||
- 查看不存在的instance @0
|
||||
|
||||
*/
|
||||
|
||||
global $tester;
|
||||
$tester->loadModel('instance');
|
||||
|
||||
$solution = new stdclass();
|
||||
$solution->id = 1;
|
||||
$instance = $tester->instance->instanceOfSolution($solution, 'subversion');
|
||||
|
||||
r($instance) && p('id,name,chart') && e('1,Subversion,subversion'); // 查看获取到的第一条instance
|
||||
r($instance->spaceData) && p('id,name') && e('1,默认空间1'); // 查看获取到的第一条instance的space
|
||||
r($instance->solutionData) && p('id,name') && e('1,解决方案1'); // 查看获取到的第一条instance的solution
|
||||
|
||||
$solution->id = 2;
|
||||
$instance = $tester->instance->instanceOfSolution($solution, 'zentao');
|
||||
|
||||
r($instance) && p('id,name,chart') && e('2,禅道开源版,zentao'); // 查看获取到的第二条instance
|
||||
r($instance->spaceData) && p('id,name') && e('2,默认空间2'); // 查看获取到的第二条instance的space
|
||||
r($instance->solutionData) && p('id,name') && e('2,解决方案2'); // 查看获取到的第二条instance的solution
|
||||
|
||||
$solution->id = 10000;
|
||||
$instance = $tester->instance->instanceOfSolution($solution, '');
|
||||
r($instance) && p() && e('0'); // 查看不存在的instance
|
||||
|
||||
$solution->id = 3;
|
||||
$instance = $tester->instance->instanceOfSolution($solution, 'qucheng');
|
||||
r($instance) && p() && e('0'); // 查看不存在的instance
|
||||
@@ -1,5 +0,0 @@
|
||||
<?php
|
||||
$config->solution = new stdclass();
|
||||
|
||||
$config->solution->gitlab = new stdclass();
|
||||
$config->solution->gitlab->minCompatibleVersion = '9.0';
|
||||
@@ -1,66 +0,0 @@
|
||||
<?php
|
||||
$lang->solution->market = new stdclass;
|
||||
$lang->solution->market->browse = 'Solution Market';
|
||||
$lang->solution->market->view = 'Solution Detail';
|
||||
|
||||
$lang->solution->name = 'Name';
|
||||
|
||||
$lang->solution->browse = 'Installed';
|
||||
$lang->solution->view = 'Solution Detail';
|
||||
$lang->solution->detail = 'Detail';
|
||||
$lang->solution->progress = 'Progress';
|
||||
$lang->solution->install = 'Install';
|
||||
$lang->solution->background = 'Background';
|
||||
$lang->solution->cancelInstall = 'Cancel';
|
||||
$lang->solution->uninstall = 'Uninstall';
|
||||
$lang->solution->retryInstall = 'Retry';
|
||||
$lang->solution->nextStep = 'Next';
|
||||
$lang->solution->config = 'Config';
|
||||
|
||||
$lang->solution->introduction = 'Introduction';
|
||||
$lang->solution->scenes = 'Scenes';
|
||||
$lang->solution->diagram = 'Diagram';
|
||||
$lang->solution->includedApp = 'Included App';
|
||||
$lang->solution->features = 'Features';
|
||||
$lang->solution->relatedLinks = 'Related Links';
|
||||
$lang->solution->customers = 'Customers';
|
||||
$lang->solution->apps = 'Installed Apps';
|
||||
$lang->solution->externalApps = 'External Apps';
|
||||
$lang->solution->resources = 'Resources';
|
||||
|
||||
$lang->solution->editName = 'Edit Name';
|
||||
|
||||
$lang->solution->chooseApp = 'Choose App';
|
||||
$lang->solution->noInstalledSolution = 'No installed solution';
|
||||
$lang->solution->toInstall = 'To Install';
|
||||
|
||||
$lang->solution->notices = new stdclass;
|
||||
$lang->solution->notices->fail = 'Fail';
|
||||
$lang->solution->notices->success = 'Success';
|
||||
$lang->solution->notices->creatingSolution = 'Creating solution...';
|
||||
$lang->solution->notices->uninstallingSolution = 'Uninstalling solution...';
|
||||
$lang->solution->notices->installingApp = 'Installing: ';
|
||||
$lang->solution->notices->installationSuccess = 'Installation success!';
|
||||
$lang->solution->notices->cancelInstall = 'Are you sure to cancel installation?';
|
||||
$lang->solution->notices->confirmToUninstall = 'Are you sure to uninstall?';
|
||||
$lang->solution->notices->confirmReinstall = 'Are you sure to retry installation?';
|
||||
|
||||
$lang->solution->errors = new stdclass;
|
||||
$lang->solution->errors->error = 'Error';
|
||||
$lang->solution->errors->notFound = 'Not found';
|
||||
$lang->solution->errors->failToInstallApp = 'Fail to install %s';
|
||||
$lang->solution->errors->timeout = 'Timeout';
|
||||
$lang->solution->errors->failToUninstallApp = 'Fail to uninstall %s';
|
||||
$lang->solution->errors->hasInstallationError = 'Has installation error';
|
||||
$lang->solution->errors->notFoundAppByVersion = 'Not found %s version of %s';
|
||||
$lang->solution->errors->notEnoughResource = 'Not enough resource, please increase the configuration or release other resources and try again.';
|
||||
|
||||
$lang->solution->installationErrors = array();
|
||||
$lang->solution->installationErrors['waiting'] = 'Installation not started.';
|
||||
$lang->solution->installationErrors['installing'] = 'Installing.';
|
||||
$lang->solution->installationErrors['installed'] = 'Installed';
|
||||
$lang->solution->installationErrors['uninstalling'] = 'Installation canceled.';
|
||||
$lang->solution->installationErrors['cneError'] = 'Installation failed.';
|
||||
$lang->solution->installationErrors['timeout'] = 'Installation timeout.';
|
||||
$lang->solution->installationErrors['notFoundApp'] = 'Not found app to be installed.';
|
||||
$lang->solution->installationErrors['notEnoughResource'] = 'Not enough resource, please increase the configuration or release other resources and try again.';
|
||||
@@ -1,66 +0,0 @@
|
||||
<?php
|
||||
$lang->solution->market = new stdclass;
|
||||
$lang->solution->market->browse = 'Solution Market';
|
||||
$lang->solution->market->view = 'Solution Detail';
|
||||
|
||||
$lang->solution->name = 'Name';
|
||||
|
||||
$lang->solution->browse = 'Installed';
|
||||
$lang->solution->view = 'Solution Detail';
|
||||
$lang->solution->detail = 'Detail';
|
||||
$lang->solution->progress = 'Progress';
|
||||
$lang->solution->install = 'Install';
|
||||
$lang->solution->background = 'Background';
|
||||
$lang->solution->cancelInstall = 'Cancel';
|
||||
$lang->solution->uninstall = 'Uninstall';
|
||||
$lang->solution->retryInstall = 'Retry';
|
||||
$lang->solution->nextStep = 'Next';
|
||||
$lang->solution->config = 'Config';
|
||||
|
||||
$lang->solution->introduction = 'Introduction';
|
||||
$lang->solution->scenes = 'Scenes';
|
||||
$lang->solution->diagram = 'Diagram';
|
||||
$lang->solution->includedApp = 'Included App';
|
||||
$lang->solution->features = 'Features';
|
||||
$lang->solution->relatedLinks = 'Related Links';
|
||||
$lang->solution->customers = 'Customers';
|
||||
$lang->solution->apps = 'Installed Apps';
|
||||
$lang->solution->externalApps = 'External Apps';
|
||||
$lang->solution->resources = 'Resources';
|
||||
|
||||
$lang->solution->editName = 'Edit Name';
|
||||
|
||||
$lang->solution->chooseApp = 'Choose App';
|
||||
$lang->solution->noInstalledSolution = 'No installed solution';
|
||||
$lang->solution->toInstall = 'To Install';
|
||||
|
||||
$lang->solution->notices = new stdclass;
|
||||
$lang->solution->notices->fail = 'Fail';
|
||||
$lang->solution->notices->success = 'Success';
|
||||
$lang->solution->notices->creatingSolution = 'Creating solution...';
|
||||
$lang->solution->notices->uninstallingSolution = 'Uninstalling solution...';
|
||||
$lang->solution->notices->installingApp = 'Installing: ';
|
||||
$lang->solution->notices->installationSuccess = 'Installation success!';
|
||||
$lang->solution->notices->cancelInstall = 'Are you sure to cancel installation?';
|
||||
$lang->solution->notices->confirmToUninstall = 'Are you sure to uninstall?';
|
||||
$lang->solution->notices->confirmReinstall = 'Are you sure to retry installation?';
|
||||
|
||||
$lang->solution->errors = new stdclass;
|
||||
$lang->solution->errors->error = 'Error';
|
||||
$lang->solution->errors->notFound = 'Not found';
|
||||
$lang->solution->errors->failToInstallApp = 'Fail to install %s';
|
||||
$lang->solution->errors->timeout = 'Timeout';
|
||||
$lang->solution->errors->failToUninstallApp = 'Fail to uninstall %s';
|
||||
$lang->solution->errors->hasInstallationError = 'Has installation error';
|
||||
$lang->solution->errors->notFoundAppByVersion = 'Not found %s version of %s';
|
||||
$lang->solution->errors->notEnoughResource = 'Not enough resource, please increase the configuration or release other resources and try again.';
|
||||
|
||||
$lang->solution->installationErrors = array();
|
||||
$lang->solution->installationErrors['waiting'] = 'Installation not started.';
|
||||
$lang->solution->installationErrors['installing'] = 'Installing.';
|
||||
$lang->solution->installationErrors['installed'] = 'Installed';
|
||||
$lang->solution->installationErrors['uninstalling'] = 'Installation canceled.';
|
||||
$lang->solution->installationErrors['cneError'] = 'Installation failed.';
|
||||
$lang->solution->installationErrors['timeout'] = 'Installation timeout.';
|
||||
$lang->solution->installationErrors['notFoundApp'] = 'Not found app to be installed.';
|
||||
$lang->solution->installationErrors['notEnoughResource'] = 'Not enough resource, please increase the configuration or release other resources and try again.';
|
||||
@@ -1,66 +0,0 @@
|
||||
<?php
|
||||
$lang->solution->market = new stdclass;
|
||||
$lang->solution->market->browse = 'Solution Market';
|
||||
$lang->solution->market->view = 'Solution Detail';
|
||||
|
||||
$lang->solution->name = 'Name';
|
||||
|
||||
$lang->solution->browse = 'Installed';
|
||||
$lang->solution->view = 'Solution Detail';
|
||||
$lang->solution->detail = 'Detail';
|
||||
$lang->solution->progress = 'Progress';
|
||||
$lang->solution->install = 'Install';
|
||||
$lang->solution->background = 'Background';
|
||||
$lang->solution->cancelInstall = 'Cancel';
|
||||
$lang->solution->uninstall = 'Uninstall';
|
||||
$lang->solution->retryInstall = 'Retry';
|
||||
$lang->solution->nextStep = 'Next';
|
||||
$lang->solution->config = 'Config';
|
||||
|
||||
$lang->solution->introduction = 'Introduction';
|
||||
$lang->solution->scenes = 'Scenes';
|
||||
$lang->solution->diagram = 'Diagram';
|
||||
$lang->solution->includedApp = 'Included App';
|
||||
$lang->solution->features = 'Features';
|
||||
$lang->solution->relatedLinks = 'Related Links';
|
||||
$lang->solution->customers = 'Customers';
|
||||
$lang->solution->apps = 'Installed Apps';
|
||||
$lang->solution->externalApps = 'External Apps';
|
||||
$lang->solution->resources = 'Resources';
|
||||
|
||||
$lang->solution->editName = 'Edit Name';
|
||||
|
||||
$lang->solution->chooseApp = 'Choose App';
|
||||
$lang->solution->noInstalledSolution = 'No installed solution';
|
||||
$lang->solution->toInstall = 'To Install';
|
||||
|
||||
$lang->solution->notices = new stdclass;
|
||||
$lang->solution->notices->fail = 'Fail';
|
||||
$lang->solution->notices->success = 'Success';
|
||||
$lang->solution->notices->creatingSolution = 'Creating solution...';
|
||||
$lang->solution->notices->uninstallingSolution = 'Uninstalling solution...';
|
||||
$lang->solution->notices->installingApp = 'Installing: ';
|
||||
$lang->solution->notices->installationSuccess = 'Installation success!';
|
||||
$lang->solution->notices->cancelInstall = 'Are you sure to cancel installation?';
|
||||
$lang->solution->notices->confirmToUninstall = 'Are you sure to uninstall?';
|
||||
$lang->solution->notices->confirmReinstall = 'Are you sure to retry installation?';
|
||||
|
||||
$lang->solution->errors = new stdclass;
|
||||
$lang->solution->errors->error = 'Error';
|
||||
$lang->solution->errors->notFound = 'Not found';
|
||||
$lang->solution->errors->failToInstallApp = 'Fail to install %s';
|
||||
$lang->solution->errors->timeout = 'Timeout';
|
||||
$lang->solution->errors->failToUninstallApp = 'Fail to uninstall %s';
|
||||
$lang->solution->errors->hasInstallationError = 'Has installation error';
|
||||
$lang->solution->errors->notFoundAppByVersion = 'Not found %s version of %s';
|
||||
$lang->solution->errors->notEnoughResource = 'Not enough resource, please increase the configuration or release other resources and try again.';
|
||||
|
||||
$lang->solution->installationErrors = array();
|
||||
$lang->solution->installationErrors['waiting'] = 'Installation not started.';
|
||||
$lang->solution->installationErrors['installing'] = 'Installing.';
|
||||
$lang->solution->installationErrors['installed'] = 'Installed';
|
||||
$lang->solution->installationErrors['uninstalling'] = 'Installation canceled.';
|
||||
$lang->solution->installationErrors['cneError'] = 'Installation failed.';
|
||||
$lang->solution->installationErrors['timeout'] = 'Installation timeout.';
|
||||
$lang->solution->installationErrors['notFoundApp'] = 'Not found app to be installed.';
|
||||
$lang->solution->installationErrors['notEnoughResource'] = 'Not enough resource, please increase the configuration or release other resources and try again.';
|
||||
@@ -1,66 +0,0 @@
|
||||
<?php
|
||||
$lang->solution->market = new stdclass;
|
||||
$lang->solution->market->browse = '解决方案市场';
|
||||
$lang->solution->market->view = '解决方案详情';
|
||||
|
||||
$lang->solution->name = '名称';
|
||||
|
||||
$lang->solution->browse = '已安装';
|
||||
$lang->solution->view = '解决方案详情';
|
||||
$lang->solution->detail = '查看';
|
||||
$lang->solution->progress = '安装进度';
|
||||
$lang->solution->install = '安装';
|
||||
$lang->solution->background = '后台安装';
|
||||
$lang->solution->cancelInstall = '取消安装';
|
||||
$lang->solution->uninstall = '卸载';
|
||||
$lang->solution->retryInstall = '重试';
|
||||
$lang->solution->nextStep = '下一步';
|
||||
$lang->solution->config = '配置';
|
||||
|
||||
$lang->solution->introduction = '基本介绍';
|
||||
$lang->solution->scenes = '适用场景';
|
||||
$lang->solution->diagram = '架构图';
|
||||
$lang->solution->includedApp = '包含应用';
|
||||
$lang->solution->features = '方案亮点';
|
||||
$lang->solution->relatedLinks = '相关链接';
|
||||
$lang->solution->customers = '典型客户';
|
||||
$lang->solution->apps = '安装的应用';
|
||||
$lang->solution->externalApps = '外部应用';
|
||||
$lang->solution->resources = '资源占用';
|
||||
|
||||
$lang->solution->editName = '修改名称';
|
||||
|
||||
$lang->solution->chooseApp = '请选择要安装的应用';
|
||||
$lang->solution->noInstalledSolution = '还没有安装解决方案';
|
||||
$lang->solution->toInstall = '去安装';
|
||||
|
||||
$lang->solution->notices = new stdclass;
|
||||
$lang->solution->notices->fail = '失败';
|
||||
$lang->solution->notices->success = '成功';
|
||||
$lang->solution->notices->creatingSolution = '正在创建解决方案。';
|
||||
$lang->solution->notices->uninstallingSolution = '正在卸载解决方案';
|
||||
$lang->solution->notices->installingApp = '正在安装:';
|
||||
$lang->solution->notices->installationSuccess = '解决方案安装成功!';
|
||||
$lang->solution->notices->cancelInstall = '确定要取消安装吗?';
|
||||
$lang->solution->notices->confirmToUninstall = '确定要卸载吗?';
|
||||
$lang->solution->notices->confirmReinstall = '确定要重试安装吗?';
|
||||
|
||||
$lang->solution->errors = new stdclass;
|
||||
$lang->solution->errors->error = '错误';
|
||||
$lang->solution->errors->notFound = '找不到相关数据';
|
||||
$lang->solution->errors->failToInstallApp = '安装%s应用失败';
|
||||
$lang->solution->errors->timeout = '安装超时';
|
||||
$lang->solution->errors->failToUninstallApp = '卸载%s应用失败';
|
||||
$lang->solution->errors->hasInstallationError = '安装过程中发生错误';
|
||||
$lang->solution->errors->notFoundAppByVersion = '找不到%s版本的%s应用';
|
||||
$lang->solution->errors->notEnoughResource = '资源不足, 请增加配置或释放其它资源后重试。';
|
||||
|
||||
$lang->solution->installationErrors = array();
|
||||
$lang->solution->installationErrors['waiting'] = '安装未开始。';
|
||||
$lang->solution->installationErrors['installing'] = '正在安装中。';
|
||||
$lang->solution->installationErrors['installed'] = '安装已完成。';
|
||||
$lang->solution->installationErrors['uninstalling'] = '安装已取消。';
|
||||
$lang->solution->installationErrors['cneError'] = '安装失败。';
|
||||
$lang->solution->installationErrors['timeout'] = '安装超时。';
|
||||
$lang->solution->installationErrors['notFoundApp'] = '找不到待安装的应用。';
|
||||
$lang->solution->installationErrors['notEnoughResource'] = '资源不足, 请增加配置或释放其它资源后重试。';
|
||||
@@ -1,461 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* The model file of solution module of ZenTaoPMS.
|
||||
*
|
||||
* @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
|
||||
* @license ZPL (http://zpl.pub/page/zplv12.html)
|
||||
* @author Jianhua Wang<wangjianhua@easycorp.ltd>
|
||||
* @package solution
|
||||
* @link https://www.zentao.net
|
||||
*/
|
||||
class solutionModel extends model
|
||||
{
|
||||
/**
|
||||
* 根据ID获取解决方案。
|
||||
* Get solution by id.
|
||||
*
|
||||
* @param int $solutionID
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function getByID(int $solutionID): ?object
|
||||
{
|
||||
$solution = $this->dao->select('*')->from(TABLE_SOLUTION)->where('id')->eq($solutionID)->fetch();
|
||||
if(!$solution) return null;
|
||||
|
||||
$solution->instances = array();
|
||||
$instanceIDList = $this->dao->select('id')->from(TABLE_INSTANCE)->where('solution')->eq($solutionID)->fetchAll('id');
|
||||
if($instanceIDList) $solution->instances = $this->loadModel('instance')->getByIDList(array_keys($instanceIDList));
|
||||
|
||||
return $solution;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据应用市场的解决方案创建本地解决方案。
|
||||
* Create by solution of cloud market.
|
||||
*
|
||||
* @param object $cloudSolution
|
||||
* @param object $components
|
||||
* @access public
|
||||
* @return object|null
|
||||
*/
|
||||
public function create(object $cloudSolution, object $components): object|null
|
||||
{
|
||||
$postedCharts = $this->session->solutionCharts ? $this->session->solutionCharts : fixer::input('post')->get();
|
||||
|
||||
/* Sort selected apps. */
|
||||
$orderedCategories = $components->order;
|
||||
$selectedApps = array();
|
||||
foreach($orderedCategories as $category)
|
||||
{
|
||||
$chart = zget($postedCharts, $category, '');
|
||||
if(empty($chart)) continue;
|
||||
|
||||
$selectedApps[$category] = $this->pickAppFromSchema($components, $category, $chart, $cloudSolution);
|
||||
if(empty($selectedApps[$category])) unset($selectedApps[$category]);
|
||||
}
|
||||
if(empty($selectedApps)) return null;
|
||||
|
||||
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');
|
||||
}
|
||||
|
||||
/* Create solution. */
|
||||
$solution = new stdclass;
|
||||
$solution->name = $cloudSolution->title;
|
||||
$solution->appID = $cloudSolution->id;
|
||||
$solution->appName = $cloudSolution->name;
|
||||
$solution->appVersion = $cloudSolution->app_version;
|
||||
$solution->version = $cloudSolution->version;
|
||||
$solution->chart = $cloudSolution->chart;
|
||||
$solution->cover = $cloudSolution->background_url;
|
||||
$solution->introduction = $cloudSolution->introduction;
|
||||
$solution->desc = $cloudSolution->description;
|
||||
$solution->status = 'waiting';
|
||||
$solution->source = 'cloud';
|
||||
$solution->components = json_encode($selectedApps);
|
||||
$solution->createdBy = $this->app->user->account;
|
||||
$solution->createdAt = helper::now();
|
||||
$solution->channel = $this->app->session->cloudChannel ? $this->app->session->cloudChannel : $this->config->cloud->api->channel;
|
||||
|
||||
$this->dao->insert(TABLE_SOLUTION)->data($solution)->exec();
|
||||
if(dao::isError()) return null;
|
||||
|
||||
return $this->getByID($this->dao->lastInsertID());
|
||||
}
|
||||
|
||||
/**
|
||||
* 按类别和应用从配置信息中获取应用信息。
|
||||
* Pick App from schema info by category and app.
|
||||
*
|
||||
* @param object $schema
|
||||
* @param string $category
|
||||
* @param string $app
|
||||
* @param object $cloudSolution
|
||||
* @access public
|
||||
* @return object|null
|
||||
*/
|
||||
public function pickAppFromSchema(object $schema, string $category, string $app, object $cloudSolution): object|null
|
||||
{
|
||||
$categoryList = helper::arrayColumn($schema->category, null, 'name');
|
||||
$appGroup = zget($categoryList, $category, array());
|
||||
|
||||
foreach($appGroup->choices as $appInSchema)
|
||||
{
|
||||
if($appInSchema->name != $app) continue;
|
||||
|
||||
$appInfo = zget($cloudSolution->apps, $app);
|
||||
$appInfo->version = $appInSchema->version;
|
||||
$appInfo->app_version = $appInSchema->app_version;
|
||||
$appInfo->status = 'waiting';
|
||||
|
||||
return $appInfo;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果实例未安装,则安装实例。
|
||||
* Install instance if instance not installed.
|
||||
*
|
||||
* @param object $solution
|
||||
* @param object $componentApp
|
||||
* @param object $solutionSchema
|
||||
* @param array $allMappings
|
||||
* @access private
|
||||
* @return bool
|
||||
*/
|
||||
private function installInstance(object $solution, object $componentApp, object $solutionSchema, array $allMappings): bool
|
||||
{
|
||||
static $apps, $components, $channel;
|
||||
if(empty($apps)) $apps = helper::arrayColumn(json_decode($solution->components, true), 'chart');
|
||||
if(empty($channel)) $channel = $this->app->session->cloudChannel ? $this->app->session->cloudChannel : $this->config->cloud->api->channel;
|
||||
if(empty($components)) $components = json_decode($solution->components);
|
||||
|
||||
$cloudApp = $this->loadModel('store')->getAppInfo($componentApp->id, false, '', $componentApp->version, $channel);
|
||||
if(!$cloudApp)
|
||||
{
|
||||
$this->saveStatus($solution->id, 'notFoundApp');
|
||||
dao::$errors[] = sprintf($this->lang->solution->errors->notFoundAppByVersion, $componentApp->version, $componentApp->alias);
|
||||
return false;
|
||||
}
|
||||
/* Must install the defineded version in solution schema. */
|
||||
$cloudApp->version = $componentApp->version;
|
||||
$cloudApp->app_version = $componentApp->app_version;
|
||||
|
||||
/* Check enough memory to install app, or not.*/
|
||||
if(!$this->loadModel('instance')->enoughMemory($cloudApp))
|
||||
{
|
||||
$this->saveStatus($solution->id, 'notEnoughResource');
|
||||
dao::$errors[] = $this->lang->solution->errors->notEnoughResource;
|
||||
return false;
|
||||
}
|
||||
|
||||
if($solution->status != 'installing') return false;
|
||||
$settings = $this->mountSettings($solutionSchema, $componentApp->chart, $components, $allMappings, in_array('sonarqube', $apps));
|
||||
$instance = $this->installApp($cloudApp, $settings);
|
||||
|
||||
if(!$instance)
|
||||
{
|
||||
$this->saveStatus($solution->id, 'cneError');
|
||||
dao::$errors[] = sprintf($this->lang->solution->errors->failToInstallApp, $cloudApp->name);
|
||||
return false;
|
||||
}
|
||||
$this->dao->update(TABLE_INSTANCE)->set('solution')->eq($solution->id)->where('id')->eq($instance->id)->exec();
|
||||
|
||||
foreach($components as &$app)
|
||||
{
|
||||
if($app->id == $componentApp->id) $app->status = 'installing';
|
||||
}
|
||||
$this->dao->update(TABLE_SOLUTION)->set('components')->eq(json_encode($components))->where('id')->eq($solution->id)->exec();
|
||||
|
||||
return !dao::isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查启动结果。
|
||||
* Check start result.
|
||||
*
|
||||
* @param object $instance
|
||||
* @param int $solutionID
|
||||
* @param object $solutionSchema
|
||||
* @param string $category
|
||||
* @access private
|
||||
* @return bool
|
||||
*/
|
||||
private function checkSarted(object $instance, int $solutionID, object $solutionSchema, string $category): bool
|
||||
{
|
||||
$instance = $this->waitInstanceStart($instance, $solutionID);
|
||||
if($instance)
|
||||
{
|
||||
$mappingKeys = zget($solutionSchema->mappings, $instance->chart, '');
|
||||
if($mappingKeys)
|
||||
{
|
||||
/* Load settings mapping of installed app for next app. */
|
||||
$tempMappings = $this->cne->getSettingsMapping($instance, $mappingKeys);
|
||||
if($tempMappings) $allMappings[$category] = $tempMappings;
|
||||
}
|
||||
|
||||
$this->instance->saveAuthInfo($instance);
|
||||
return true;
|
||||
}
|
||||
|
||||
$this->saveStatus($solutionID, 'timeout');
|
||||
dao::$errors[] = $this->lang->solution->errors->timeout;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 安装解决方案。
|
||||
* Install solution.
|
||||
*
|
||||
* @param int $solutionID
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function install(int $solutionID): bool
|
||||
{
|
||||
set_time_limit(0);
|
||||
session_write_close();
|
||||
|
||||
$solution = $this->getByID($solutionID);
|
||||
if(!$solution)
|
||||
{
|
||||
dao::$errors[] = $this->lang->solution->errors->notFound;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(in_array($solution->status, array('installing', 'installed', 'uninstalled'))) return false;
|
||||
$this->saveStatus($solutionID, 'installing');
|
||||
$solution->status = 'installing';
|
||||
|
||||
$this->loadModel('cne');
|
||||
$this->loadModel('instance');
|
||||
$this->loadModel('common');
|
||||
$allMappings = array();
|
||||
$solutionSchema = $this->loadModel('store')->solutionConfig('id', $solution->appID);
|
||||
$components = json_decode($solution->components);
|
||||
foreach($components as $category => $componentApp)
|
||||
{
|
||||
$solutionStatus = $this->dao->select('status')->from(TABLE_SOLUTION)->where('id')->eq($solutionID)->fetch();
|
||||
if($solutionStatus->status !='installing')
|
||||
{
|
||||
/* If status is not installing, should abort installation. Becaust installation was canceled or error happened. */
|
||||
dao::$errors[] = $this->lang->solution->errors->hasInstallationError;
|
||||
return false;
|
||||
}
|
||||
|
||||
$instance = $this->instance->instanceOfSolution($solution, $componentApp->chart);
|
||||
if(!$instance && !$this->installInstance($solution, $componentApp, $solutionSchema, $allMappings)) return false;
|
||||
|
||||
$instance = $this->instance->instanceOfSolution($solution, $componentApp->chart);
|
||||
|
||||
/* Wait instanlled app started. */
|
||||
if(!$this->checkSarted($instance, $solutionID, $solutionSchema, $category)) return false;
|
||||
|
||||
$componentApp->status = 'installed';
|
||||
$this->dao->update(TABLE_SOLUTION)->set('components')->eq(json_encode($components))->where('id')->eq($solution->id)->exec();
|
||||
}
|
||||
|
||||
$this->saveStatus($solutionID, 'installed');
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新解决方案的状态。
|
||||
* Update status of solution.
|
||||
*
|
||||
* @param int $solutionID
|
||||
* @param string $status waiting|uninstalling|cneError|timeout|notFoundApp|notEnoughResource
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function saveStatus(int $solutionID, string $status): bool
|
||||
{
|
||||
if(!isset($this->lang->solution->installationErrors[$status])) return false;
|
||||
|
||||
$this->dao->update(TABLE_SOLUTION)
|
||||
->set('status')->eq($status)
|
||||
->set('updatedDate')->eq(helper::now())
|
||||
->where('id')->eq($solutionID)
|
||||
->exec();
|
||||
return !dao::isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取安装应用的配置信息。
|
||||
* Mount settings for installing app.
|
||||
*
|
||||
* @param object $solutionSchema
|
||||
* @param string $chart
|
||||
* @param object $components
|
||||
* @param array $mappings example: ['git' => ['env.GIT_USERNAME' => 'admin', ...], ...]
|
||||
* @param boolean $isInstallSonar
|
||||
* @access private
|
||||
* @return array
|
||||
*/
|
||||
private function mountSettings(object $solutionSchema, string $chart, object $components, array $mappings, bool $isInstallSonar = true): array
|
||||
{
|
||||
$settings = array();
|
||||
|
||||
$appSettings = zget($solutionSchema->settings, $chart, array());
|
||||
$apps = helper::arrayColumn((array)$components, 'chart');
|
||||
foreach($appSettings as $item)
|
||||
{
|
||||
if(!empty($item->when) && !in_array($item->when, $apps)) continue;
|
||||
switch($item->type)
|
||||
{
|
||||
case 'static':
|
||||
if(!$isInstallSonar && $item->key === 'solution.sonarqube.enabled')
|
||||
break;
|
||||
$settings[] = array('key' => $item->key, 'value' => $item->value);
|
||||
break;
|
||||
case 'choose':
|
||||
$appInfo = zget($components, $item->target, '');
|
||||
if($appInfo) $settings[] = array('key' => $item->key, 'value' => $appInfo->chart);
|
||||
break;
|
||||
case 'mappings':
|
||||
$mappingInfo = zget($mappings, $item->target, '');
|
||||
if($mappingInfo) $settings[] = array('key' => $item->key, 'value' => zget($mappingInfo, $item->key, ''));
|
||||
break;
|
||||
case 'auto':
|
||||
if($item->value === 'protocol') $settings[] = array('key' => $item->key, 'value' => strstr(getWebRoot(true), ':', true));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* 安装应用。
|
||||
* Install app.
|
||||
*
|
||||
* @param object $cloudApp
|
||||
* @param array $settings
|
||||
* @access private
|
||||
* @return object|false
|
||||
*/
|
||||
private function installApp(object $cloudApp, array $settings): object|false
|
||||
{
|
||||
/* Fake parameters for installation. */
|
||||
|
||||
$customData = new stdclass;
|
||||
$customData->customName = $cloudApp->alias;
|
||||
$customData->dbType = null;
|
||||
$customData->customDomain = $this->loadModel('instance')->randThirdDomain();
|
||||
|
||||
$dbInfo = new stdclass;
|
||||
$dbList = $this->loadModel('cne')->sharedDBList();
|
||||
if(count($dbList) > 0)
|
||||
{
|
||||
$dbInfo = reset($dbList);
|
||||
|
||||
$customData->dbType = 'sharedDB';
|
||||
$customData->dbService = $dbInfo->name; // Use first shared database.
|
||||
}
|
||||
|
||||
return $this->instance->install($cloudApp, $dbInfo, $customData, null, $settings);
|
||||
}
|
||||
|
||||
/**
|
||||
* 等待应用启动完成。
|
||||
* Wait instance started.
|
||||
*
|
||||
* @param object $instance
|
||||
* @param int $solutionID
|
||||
* @access private
|
||||
* @return object|false
|
||||
*/
|
||||
private function waitInstanceStart(object $instance, int $solutionID): object|false
|
||||
{
|
||||
/* Query status of the installed instance. */
|
||||
$times = 0;
|
||||
$this->loadModel('instance');
|
||||
for($times = 0; $times < 50; $times++)
|
||||
{
|
||||
$solution = $this->getByID($solutionID);
|
||||
if(!$solution || $solution->status != 'installing') return false;
|
||||
|
||||
$this->dao->update(TABLE_SOLUTION)->set('updatedDate')->eq(date("Y-m-d H:i:s"))->where('id')->eq($solutionID)->exec();
|
||||
|
||||
sleep(12);
|
||||
$instance = $this->instance->freshStatus($instance);
|
||||
$this->saveLog(date('Y-m-d H:i:s').' installing ' . $instance->name . ':' . $instance->status . '#' . $instance->solution); // Code for debug.
|
||||
|
||||
if($instance->status == 'running') return $instance;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除解决方案环境。
|
||||
* Uninstall solution and all included instances .
|
||||
*
|
||||
* @param int $solutionID
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function uninstall(int $solutionID): bool
|
||||
{
|
||||
/* Firstly change the status to 'unintalling' for abort installing process. */
|
||||
$this->dao->update(TABLE_SOLUTION)->set('status')->eq('uninstalling')->where('id')->eq($solutionID)->exec();
|
||||
|
||||
$solution = $this->getByID($solutionID);
|
||||
if(empty($solution))
|
||||
{
|
||||
dao::$errors[] = $this->lang->solution->notFound;
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->loadModel('instance');
|
||||
foreach($solution->instances as $instance)
|
||||
{
|
||||
$success = $this->instance->uninstall($instance);
|
||||
if(!$success)
|
||||
{
|
||||
dao::$errors[] = sprintf($this->lang->solution->errors->failToUninstallApp, $instance->name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$this->dao->update(TABLE_SOLUTION)->set('status')->eq('uninstalled')->set('deleted')->eq(1)->where('id')->eq($solutionID)->exec();
|
||||
return !dao::isError();
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存安装日志。
|
||||
* Save message to error log file.
|
||||
*
|
||||
* @param string $message
|
||||
* @access public
|
||||
* @return string
|
||||
*/
|
||||
public function saveLog(string $message): string
|
||||
{
|
||||
$errorFile = $this->app->logRoot . 'php.' . date('Ymd') . '.log.php';
|
||||
if(!is_file($errorFile)) @file_put_contents($errorFile, "<\x3fphp\n die();\n\x3f>\n");
|
||||
|
||||
@file_put_contents($errorFile, $message . "\n", FILE_APPEND);
|
||||
return $errorFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取最后一次安装的方案。
|
||||
* Get last solution.
|
||||
*
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function getLastSolution(): object|false
|
||||
{
|
||||
return $this->dao->select('*')->from(TABLE_SOLUTION)
|
||||
->where('deleted')->eq(0)
|
||||
->orderBy('id_desc')
|
||||
->fetch();
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,37 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
|
||||
title=测试 solutionModel->create();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 没有选择应用 @0
|
||||
- 正确选择了应用属性components @{"git":{"id":58,"name":"gitlab","alias":"GitLab","chart":"gitlab","app_version":"15.3.4","version":"2023.10.901","logo":"https:\/\/img.qucheng.com\/app\/g\/gitlab-icon.svg","status":"waiting"}}
|
||||
- 选择两个应用属性components @{"git":{"id":58,"name":"gitlab","alias":"GitLab","chart":"gitlab","app_version":"15.3.4","version":"2023.10.901","logo":"https:\/\/img.qucheng.com\/app\/g\/gitlab-icon.svg","status":"waiting"},"ci":{"id":59,"name":"jenkins","alias":"Jenkins","chart":"jenkins","app_version":"2.401.3","version":"2023.10.901","logo":"https:\/\/img.qucheng.com\/app\/j\/jenkins-icon.svg","status":"waiting"}}
|
||||
|
||||
*/
|
||||
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
include dirname(__FILE__, 2) . '/lib/solution.unittest.class.php';
|
||||
|
||||
zenData('user')->gen(5);
|
||||
zenData('solution')->loadYaml('solution')->gen(0);
|
||||
zenData('instance')->loadYaml('instance')->gen(0);
|
||||
|
||||
$params = array(
|
||||
'git' => '',
|
||||
'ci' => '',
|
||||
'analysis' => '',
|
||||
'artifact' => ''
|
||||
);
|
||||
|
||||
$solutionModel = new solutionTest();
|
||||
r($solutionModel->createTest($params)) && p() && e('0'); // 没有选择应用
|
||||
|
||||
$params['git'] = 'gitlab';
|
||||
r($solutionModel->createTest($params)) && p('components', '|') && e('{"git":{"id":58,"name":"gitlab","alias":"GitLab","chart":"gitlab","app_version":"15.3.4","version":"2023.10.901","logo":"https:\/\/img.qucheng.com\/app\/g\/gitlab-icon.svg","status":"waiting"}}'); // 正确选择了应用
|
||||
|
||||
$params['ci'] = 'jenkins';
|
||||
r($solutionModel->createTest($params)) && p('components', '|') && e('{"git":{"id":58,"name":"gitlab","alias":"GitLab","chart":"gitlab","app_version":"15.3.4","version":"2023.10.901","logo":"https:\/\/img.qucheng.com\/app\/g\/gitlab-icon.svg","status":"waiting"},"ci":{"id":59,"name":"jenkins","alias":"Jenkins","chart":"jenkins","app_version":"2.401.3","version":"2023.10.901","logo":"https:\/\/img.qucheng.com\/app\/j\/jenkins-icon.svg","status":"waiting"}}'); // 选择两个应用
|
||||
@@ -1,42 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
|
||||
title=测试 solutionModel->getByID();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 解决方案ID为空 @0
|
||||
- 解决方案ID存在
|
||||
- 属性name @禅道 DevOps 解决方案1
|
||||
- 属性status @notEnoughResource
|
||||
- 解决方案ID存在,检查实例数量 @3
|
||||
- 解决方案ID存在
|
||||
- 属性name @禅道 DevOps 解决方案2
|
||||
- 属性status @notEnoughResource
|
||||
- 解决方案ID存在,检查实例数量 @1
|
||||
- 解决方案ID不存在 @0
|
||||
|
||||
*/
|
||||
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
include dirname(__FILE__, 2) . '/lib/solution.unittest.class.php';
|
||||
|
||||
zenData('space')->loadYaml('space')->gen(2);
|
||||
zenData('solution')->loadYaml('solution')->gen(2);
|
||||
zenData('instance')->loadYaml('instance')->gen(4);
|
||||
|
||||
$solutionModel = new solutionTest();
|
||||
|
||||
r($solutionModel->getByIdTest(0)) && p() && e('0'); // 解决方案ID为空
|
||||
|
||||
$solution = $solutionModel->getByIdTest(1);
|
||||
r($solution) && p('name,status') && e('禅道 DevOps 解决方案1,notEnoughResource'); // 解决方案ID存在
|
||||
r(count($solution->instances)) && p() && e('3'); // 解决方案ID存在,检查实例数量
|
||||
|
||||
$solution = $solutionModel->getByIdTest(2);
|
||||
r($solution) && p('name,status') && e('禅道 DevOps 解决方案2,notEnoughResource'); // 解决方案ID存在
|
||||
r(count($solution->instances)) && p() && e('1'); // 解决方案ID存在,检查实例数量
|
||||
|
||||
r($solutionModel->getByIdTest(5)) && p() && e('0'); // 解决方案ID不存在
|
||||
@@ -1,27 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
|
||||
title=测试 solutionModel->getLastSolution();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 获取最后一个解决方案
|
||||
- 属性id @2
|
||||
- 属性name @禅道 DevOps 解决方案2
|
||||
- 没有数据时获取最后一个解决方案 @0
|
||||
|
||||
*/
|
||||
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
include dirname(__FILE__, 2) . '/lib/solution.unittest.class.php';
|
||||
|
||||
zenData('solution')->loadYaml('solution')->gen(2);
|
||||
|
||||
$solutionModel = new solutionTest();
|
||||
|
||||
r($solutionModel->getLastSolutionTest()) && p('id,name') && e('2,禅道 DevOps 解决方案2'); // 获取最后一个解决方案
|
||||
|
||||
zenData('solution')->loadYaml('solution')->gen(0);
|
||||
r($solutionModel->getLastSolutionTest()) && p() && e('0'); // 没有数据时获取最后一个解决方案
|
||||
@@ -1,28 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
|
||||
title=测试 solutionModel->pickAppFromSchema();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 类别和应用不对应 @0
|
||||
- 类别和应用对应
|
||||
- 属性id @58
|
||||
- 属性alias @GitLab
|
||||
- 属性status @waiting
|
||||
|
||||
*/
|
||||
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
include dirname(__FILE__, 2) . '/lib/solution.unittest.class.php';
|
||||
|
||||
zenData('user')->gen(5);
|
||||
zenData('solution')->loadYaml('solution')->gen(0);
|
||||
zenData('instance')->loadYaml('instance')->gen(0);
|
||||
|
||||
$solutionModel = new solutionTest();
|
||||
r($solutionModel->pickAppFromSchemaTest('git', 'gitee')) && p() && e('0'); // 类别和应用不对应
|
||||
|
||||
r($solutionModel->pickAppFromSchemaTest('git', 'gitlab')) && p('id,alias,status') && e('58,GitLab,waiting'); // 类别和应用对应
|
||||
@@ -1,30 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
/**
|
||||
|
||||
title=测试 solutionModel->saveStatus();
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 错误的状态
|
||||
- 属性id @1
|
||||
- 属性status @notEnoughResource
|
||||
- 正确的状态
|
||||
- 属性id @1
|
||||
- 属性status @cneError
|
||||
- 不存在的解决方案 @0
|
||||
|
||||
*/
|
||||
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
include dirname(__FILE__, 2) . '/lib/solution.unittest.class.php';
|
||||
|
||||
zenData('solution')->loadYaml('solution')->gen(1);
|
||||
|
||||
$solutionModel = new solutionTest();
|
||||
|
||||
r($solutionModel->saveStatusTest(1, 'test')) && p('id,status') && e('1,notEnoughResource'); // 错误的状态
|
||||
r($solutionModel->saveStatusTest(1, 'cneError')) && p('id,status') && e('1,cneError'); // 正确的状态
|
||||
|
||||
r($solutionModel->saveStatusTest(2, 'cneError')) && p() && e('0'); // 不存在的解决方案
|
||||
@@ -1,66 +0,0 @@
|
||||
---
|
||||
title: instance
|
||||
author: Yanyi Cao
|
||||
version: "1.0"
|
||||
fields:
|
||||
- field: id
|
||||
range: 1-4
|
||||
- field: space
|
||||
range: '1{2},2{2}'
|
||||
- field: solution
|
||||
range: '1{3},2'
|
||||
- field: name
|
||||
range: '`Jenkins`,`GitLab`,`GitLab`,`Jenkins`'
|
||||
- field: appID
|
||||
range: '`59`,`58`,`58`,`59`'
|
||||
- field: appName
|
||||
range: '`Jenkins`,`GitLab`,`GitLab`,`Jenkins`'
|
||||
- field: appVersion
|
||||
range: '`2.401.3`,`15.3.4`,`15.3.4`,`2.401.3`'
|
||||
- field: chart
|
||||
range: '`jenkins`,`gitlab`,`gitlab`,`jenkins`'
|
||||
- field: logo
|
||||
range: '`//img.qucheng.com/app/j/jenkins-icon.svg`,`//img.qucheng.com/app/g/gitlab-icon.svg`,`//img.qucheng.com/app/g/gitlab-icon.svg`,`//img.qucheng.com/app/j/jenkins-icon.svg`'
|
||||
- field: version
|
||||
range: '`2023.10.901`'
|
||||
- field: desc
|
||||
range: '`Jenkins是国际上流行的免费开源软件项目,是基于Java开发持续集成工具,用于监控持续重复的工作,旨在提供一个开放的易用的软件平台,使软件的持续集成自动化,大大节约人力和时效。`,`GitLab是由GitLab
|
||||
Inc.开发,使用MIT许可证的基于网络的Git仓库管理工具,且具有wiki和issue跟踪功能。使用Git作为代码管理工具,并在此基础上搭建起来的web服务。`,`GitLab是由GitLab
|
||||
Inc.开发,使用MIT许可证的基于网络的Git仓库管理工具,且具有wiki和issue跟踪功能。使用Git作为代码管理工具,并在此基础上搭建起来的web服务。`,`Jenkins是国际上流行的免费开源软件项目,是基于Java开发持续集成工具,用于监控持续重复的工作,旨在提供一个开放的易用的软件平台,使软件的持续集成自动化,大大节约人力和时效。`'
|
||||
- field: introduction
|
||||
range: '`基于Java开发的一款持续集成工具`,`GitLab 一款基于Git的一体化软件开发平台。`,`GitLab 一款基于Git的一体化软件开发平台。`,`基于Java开发的一款持续集成工具`'
|
||||
- field: source
|
||||
range: '`cloud`'
|
||||
- field: channel
|
||||
range: '`stable`'
|
||||
- field: k8name
|
||||
range: '`jenkins-20231019112830`,`gitlab-20231019131424`,`gitlab-20231025104407`,`jenkins-20231025104735`'
|
||||
- field: status
|
||||
range: '`running`,`starting`,,'
|
||||
- field: pinned
|
||||
range: "0"
|
||||
- field: domain
|
||||
range: '`jvud.devops.corp.cc`,`gmip.devops.corp.cc`,`9krd.devops.corp.cc`,`adkm.devops.corp.cc`'
|
||||
- field: smtpSnippetName
|
||||
range: ""
|
||||
- field: ldapSnippetName
|
||||
range: ""
|
||||
- field: ldapSettings
|
||||
range: ""
|
||||
- field: dbSettings
|
||||
range: '`{"ingress":{"enabled":true,"host":"jvud.devops.corp.cc"},"global":{"ingress":{"enabled":true,"host":"jvud.devops.corp.cc"}},"ci":{"enabled":true},"mysql":{"enabled":false,"auth":{"user":"user_52","password":"vmqA3pzlswbB","host":"qucheng-mysql.quickon-system.svc","port":3306,"database":"db_52","dbservice":{"name":"qucheng-mysql","namespace":"quickon-system"}}}}`,`{"ingress":{"enabled":true,"host":"gmip.devops.corp.cc"},"global":{"ingress":{"enabled":true,"host":"gmip.devops.corp.cc"}},"ci":{"enabled":true},"mysql":{"enabled":false,"auth":{"user":"user_53","password":"cjPmBztaTYvy","host":"qucheng-mysql.quickon-system.svc","port":3306,"database":"db_53","dbservice":{"name":"qucheng-mysql","namespace":"quickon-system"}}}}`,`{"ingress":{"enabled":true,"host":"9krd.devops.corp.cc"},"global":{"ingress":{"enabled":true,"host":"9krd.devops.corp.cc"}},"ci":{"enabled":true},"mysql":{"enabled":false,"auth":{"user":"user_54","password":"GTFyIESAUjsP","host":"qucheng-mysql.quickon-system.svc","port":3306,"database":"db_54","dbservice":{"name":"qucheng-mysql","namespace":"quickon-system"}}}}`,`{"ingress":{"enabled":true,"host":"adkm.devops.corp.cc"},"global":{"ingress":{"enabled":true,"host":"adkm.devops.corp.cc"}},"ci":{"enabled":true},"mysql":{"enabled":false,"auth":{"user":"user_55","password":"wvKn8a7JyxcZ","host":"qucheng-mysql.quickon-system.svc","port":3306,"database":"db_55","dbservice":{"name":"qucheng-mysql","namespace":"quickon-system"}}}}`'
|
||||
- field: autoBackup
|
||||
range: "0"
|
||||
- field: backupKeepDays
|
||||
range: '`1`'
|
||||
- field: autoRestore
|
||||
range: "0"
|
||||
- field: env
|
||||
range: ""
|
||||
- field: createdBy
|
||||
range: '`wwccss`'
|
||||
- field: createdAt
|
||||
range: '`2023-10-19 11:28:30`,`2023-10-19 13:14:24`,`2023-10-25 10:44:07`,`2023-10-25 10:47:35`'
|
||||
- field: deleted
|
||||
range: "0"
|
||||
...
|
||||
@@ -1,43 +0,0 @@
|
||||
---
|
||||
title: solution
|
||||
author: Yanyi Cao
|
||||
version: "1.0"
|
||||
fields:
|
||||
- field: id
|
||||
range: 1-2
|
||||
- field: name
|
||||
prefix: '禅道 DevOps 解决方案'
|
||||
range: 1-2
|
||||
- field: appID
|
||||
range: '`2`'
|
||||
- field: appName
|
||||
range: '`devops`'
|
||||
- field: appVersion
|
||||
range: '`1.1.0`'
|
||||
- field: version
|
||||
range: '`2023.10.901`'
|
||||
- field: chart
|
||||
range: '`devops`'
|
||||
- field: cover
|
||||
range: '`https://img.qucheng.com/app/d/devops-bg.png`'
|
||||
- field: desc
|
||||
range: '`禅道 DevOps 解决方案是一套软件全生命周期管理、跟踪、集成、发布解决方案。包含禅道项目管理工具、代码仓库、集成工具等。用户可以跟踪软件项目进度,管理代码的集成与发布。`'
|
||||
- field: introduction
|
||||
range: '`覆盖从立项到发布,端到端的软件开发全流程跟踪。全面集成 Jenkins、Gitlab 等工具。`'
|
||||
- field: source
|
||||
range: '`cloud`'
|
||||
- field: channel
|
||||
range: '`stable`'
|
||||
- field: components
|
||||
range: '`{"git":{"id":58,"name":"gitlab","alias":"GitLab","chart":"gitlab","app_version":"15.3.4","version":"2023.10.901","logo":"https:\/\/img.qucheng.com\/app\/g\/gitlab-icon.svg","status":"installed"},"ci":{"id":59,"name":"jenkins","alias":"Jenkins","chart":"jenkins","app_version":"2.401.3","version":"2023.10.901","logo":"https:\/\/img.qucheng.com\/app\/j\/jenkins-icon.svg","status":"installing"}}`'
|
||||
- field: status
|
||||
range: '`notEnoughResource`'
|
||||
- field: deleted
|
||||
range: "0"
|
||||
- field: createdBy
|
||||
range: '`wwccss`'
|
||||
- field: createdAt
|
||||
range: '`2023-10-16 09:25:07`'
|
||||
- field: updatedDate
|
||||
range: '`2023-12-08 16:10:08`'
|
||||
...
|
||||
@@ -1,20 +0,0 @@
|
||||
---
|
||||
title: space
|
||||
author: Yanyi Cao
|
||||
version: "1.0"
|
||||
fields:
|
||||
- field: id
|
||||
range: 1-2
|
||||
- field: name
|
||||
range: '`默认空间`'
|
||||
- field: k8space
|
||||
range: '`quickon-app`'
|
||||
- field: owner
|
||||
range: '`wwccss`,'
|
||||
- field: default
|
||||
range: '`1`'
|
||||
- field: createdAt
|
||||
range: '`2023-08-29 11:20:29`,`2023-10-16 09:25:11`'
|
||||
- field: deleted
|
||||
range: "0"
|
||||
...
|
||||
@@ -47,14 +47,9 @@ class space extends control
|
||||
$pager = new pager($newRecTotal, $recPerPage, $pageID);
|
||||
$allInstances = array_chunk($allInstances, $pager->recPerPage);
|
||||
|
||||
$solutionID = 0;
|
||||
$solution = $this->loadModel('solution')->getLastSolution();
|
||||
if($solution && $solution->status == 'installing') $solutionID = $solution->id;
|
||||
|
||||
$this->view->title = $this->lang->space->common;
|
||||
$this->view->pager = $pager;
|
||||
$this->view->orderBy = $orderBy;
|
||||
$this->view->solutionID = $solutionID;
|
||||
$this->view->browseType = $browseType;
|
||||
$this->view->instances = (empty($allInstances) or empty($allInstances[$pageID - 1])) ? array() : $allInstances[$pageID - 1];
|
||||
$this->view->users = $this->loadModel('user')->getPairs('noclosed,noletter');
|
||||
|
||||
@@ -126,9 +126,6 @@ class spaceModel extends model
|
||||
|
||||
if($this->config->inQuickon) $instances = $this->loadModel('store')->batchSetLatestVersions($instances);
|
||||
|
||||
$solutionIDList = helper::arrayColumn($instances, 'solution');
|
||||
$solutions = $this->dao->select('*')->from(TABLE_SOLUTION)->where('id')->in($solutionIDList)->fetchAll('id');
|
||||
foreach($instances as $instance) $instance->solutionData = zget($solutions, $instance->solution, new stdclass);
|
||||
return $instances;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,17 +31,6 @@ featureBar
|
||||
$app->loadLang('solution');
|
||||
toolBar
|
||||
(
|
||||
$config->inQuickon && $solutionID && hasPriv('install', 'progress') ? item(set(array
|
||||
(
|
||||
'text' => $lang->solution->progress,
|
||||
'icon' => 'spinner-indicator',
|
||||
'class' => 'ghost',
|
||||
'url' => createLink('install', 'progress', "solutionID=$solutionID&install=true"),
|
||||
'data-size' => array('width' => '900', 'height' => '500'),
|
||||
'data-class-name' => 'install-progress',
|
||||
'data-id' => 'installProgress',
|
||||
'data-toggle' => 'modal'
|
||||
))) : null,
|
||||
$canInstall ? item(set(array
|
||||
(
|
||||
'text' => $lang->space->install,
|
||||
|
||||
@@ -299,53 +299,6 @@ class storeModel extends model
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据参数获取解决方案信息。
|
||||
* Get solution info.
|
||||
*
|
||||
* @param string $type
|
||||
* @param int|string $value
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function getSolution(string $type, string $value): object
|
||||
{
|
||||
$apiParams = array();
|
||||
$apiParams[$type] = $value;
|
||||
|
||||
$apiUrl = $this->config->cloud->api->host;
|
||||
$apiUrl .= '/api/market/solution/info?channel='. $this->config->cloud->api->channel;
|
||||
$result = commonModel::apiGet($apiUrl, $apiParams, $this->config->cloud->api->headers);
|
||||
if(!isset($result->code) || $result->code != 200) return new stdclass();
|
||||
|
||||
$solution = $result->data;
|
||||
$solution->apps = array_combine(helper::arrayColumn($solution->apps, 'chart'), $solution->apps);
|
||||
|
||||
return $solution;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取解决方案的配置信息。
|
||||
* Get solution config.
|
||||
*
|
||||
* @param string $type
|
||||
* @param int|string $value
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function solutionConfig(string $type, int|string $value): object
|
||||
{
|
||||
$apiParams = array();
|
||||
$apiParams[$type] = $value;
|
||||
|
||||
$apiUrl = $this->config->cloud->api->host;
|
||||
$apiUrl .= '/api/market/solution/schema?channel='. $this->config->cloud->api->channel;
|
||||
$result = commonModel::apiGet($apiUrl, $apiParams, $this->config->cloud->api->headers);
|
||||
if(!isset($result->code) || $result->code != 200) return new stdclass();
|
||||
|
||||
return $result->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置应用最新版本。
|
||||
* Set app latest version.
|
||||
|
||||
@@ -11,9 +11,9 @@ class storeTest
|
||||
|
||||
$this->objectModel->config->inQuickon = true;
|
||||
$this->objectModel->config->k8space = 'quickon-system';
|
||||
$this->objectModel->config->CNE->api->host = 'http://10.0.7.210:32380';
|
||||
$this->objectModel->config->CNE->api->token = 'JMz7HCoQ3WHoYbpNyYNpvMfHqde9ugtV';
|
||||
$this->objectModel->config->CNE->app->domain = 'dops.corp.cc';
|
||||
$this->objectModel->config->CNE->api->host = 'http://devops.corp.cc:32380';
|
||||
$this->objectModel->config->CNE->api->token = 'R09p3H5mU1JCg60NGPX94RVbGq31JVkF';
|
||||
$this->objectModel->config->CNE->app->domain = 'devops.corp.cc';
|
||||
|
||||
$this->objectModel->config->cloud->api->host = 'http://api.qucheng.com';
|
||||
$this->objectModel->config->cloud->api->channel = 'stable';
|
||||
@@ -171,36 +171,6 @@ class storeTest
|
||||
return $categories;
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试获取解决方案的配置信息。
|
||||
* Test get solution config.
|
||||
*
|
||||
* @param string $type
|
||||
* @param int|string $value
|
||||
* @access public
|
||||
* @return object
|
||||
*/
|
||||
public function solutionConfigTest(string $type, int|string $value): string
|
||||
{
|
||||
$result = $this->solutionConfig($type, $value);
|
||||
return empty((array)$result) ? 'No data' : 'Success';
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试根据参数获取解决方案信息。
|
||||
* Test get solution info.
|
||||
*
|
||||
* @param string $type
|
||||
* @param string $value
|
||||
* @access public
|
||||
* @return object|string
|
||||
*/
|
||||
public function getSolutionTest(string $type, string $value): object|string
|
||||
{
|
||||
$result = $this->getSolution($type, $value);
|
||||
return empty((array)$result) ? 'No data' : $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试从渠成获取应用动态消息。
|
||||
* Test get app dynamic news from Qucheng offical site.
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
|
||||
title=测试 storeModel->getSolution().
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 测试查询devops解决方案
|
||||
- 属性name @devops
|
||||
- 属性title @禅道 DevOps 解决方案
|
||||
- 测试查询失败 @No data
|
||||
|
||||
*/
|
||||
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
include dirname(__FILE__, 2) . '/lib/store.unittest.class.php';
|
||||
|
||||
zenData('user')->gen(5);
|
||||
su('admin');
|
||||
|
||||
$typeList = array('name', 'id');
|
||||
$valueList = array('devops', '29');
|
||||
|
||||
$store = new storeTest();
|
||||
r($store->getSolutionTest($typeList[0], $valueList[0])) && p('name,title') && e('devops,禅道 DevOps 解决方案'); //测试查询devops解决方案
|
||||
r($store->getSolutionTest($typeList[1], $valueList[1])) && p() && e('No data'); //测试查询失败
|
||||
@@ -1,27 +0,0 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
|
||||
title=测试 storeModel->solutionConfig().
|
||||
timeout=0
|
||||
cid=1
|
||||
|
||||
- 测试查询成功 @Success
|
||||
- 测试查询无数据 @No data
|
||||
|
||||
*/
|
||||
|
||||
include dirname(__FILE__, 5) . '/test/lib/init.php';
|
||||
include dirname(__FILE__, 2) . '/lib/store.unittest.class.php';
|
||||
|
||||
zenData('user')->gen(5);
|
||||
su('admin');
|
||||
|
||||
$typeList = array('name', 'id');
|
||||
$valueList = array('devops', 29);
|
||||
|
||||
$store = new storeTest();
|
||||
r($store->solutionConfigTest($typeList[0], $valueList[0])) && p() && e('Success'); //测试查询成功
|
||||
r($store->solutionConfigTest($typeList[1], $valueList[1])) && p() && e('No data'); //测试查询无数据
|
||||
@@ -1485,6 +1485,8 @@ $config->delete['21_6_beta'][] = 'extension/ipd/project/ext/model/zentaoipd.php'
|
||||
$config->delete['21_6_beta'][] = 'extension/max/project/ext/model/zentaoipd.php';
|
||||
$config->delete['21_6_beta'][] = 'extension/biz/project/ext/model/zentaoipd.php';
|
||||
|
||||
$config->delete['21_7_2'][] = 'module/solution';
|
||||
|
||||
$config->upgrade->openModules = array('action', 'admin', 'ai', 'bi', 'aiapp', 'api', 'automation', 'backup', 'block', 'branch', 'budget', 'bug', 'build', 'cache', 'caselib', 'chart', 'ci', 'client', 'common', 'company', 'compile', 'convert', 'cron', 'custom', 'datatable', 'dataview', 'dept', 'design', 'dev', 'dimension', 'doc', 'durationestimation', 'entry', 'execution', 'extension', 'file', 'git', 'gitlab', 'group', 'holiday', 'im', 'index', 'index.html', 'install', 'issue', 'jenkins', 'job', 'kanban', 'license', 'mail', 'message', 'metric', 'misc', 'mr', 'my', 'personnel', 'pipeline', 'product', 'productplan', 'productset', 'program', 'programplan', 'project', 'projectbuild', 'projectplan', 'projectrelease', 'projectstory', 'pivot', 'qa', 'release', 'repo', 'report', 'risk', 'score', 'screen', 'search', 'setting', 'sonarqube', 'sso', 'stage', 'stakeholder', 'story', 'subject', 'svn', 'task', 'testcase', 'testreport', 'testsuite', 'testtask', 'todo', 'tree', 'tutorial', 'upgrade', 'user', 'webhook', 'weekly', 'workestimation', 'gitea', 'gogs', 'transfer', 'zahost', 'zanode', 'editor', 'charter', 'roadmap', 'account', 'cne', 'host', 'instance', 'ops', 'serverroom', 'space', 'store', 'system', 'solution', 'demand', 'gitfox', 'epic', 'requirement', 'mark');
|
||||
$config->upgrade->unsetModules = array('design', 'program', 'programplan', 'projectbuild', 'projectrelease', 'stage', 'stakeholder', 'product', 'branch', 'productplan', 'release', 'build', 'qa', 'bug', 'testcase', 'testtask', 'testreport', 'testsuite', 'caselib', 'automation', 'repo', 'ci', 'compile', 'jenkins', 'job', 'svn', 'gitlab', 'sonarqube', 'mr', 'git', 'report', 'sqlbuilder', 'feedback', 'faq', 'attend', 'holiday', 'leave', 'makeup', 'overtime', 'lieu', 'ops', 'host', 'serverroom', 'account', 'domain', 'service', 'deploy', 'conference', 'traincourse', 'pssp', 'baseline', 'classify', 'cm', 'cmcl', 'auditcl', 'reviewcl', 'process', 'activity', 'zoutput', 'auditplan', 'nc', 'subject', 'weekly', 'workestimation', 'issue', 'durationestimation', 'risk', 'opportunity', 'trainplan', 'gapanalysis', 'researchplan', 'researchreport', 'meeting', 'meetingroom', 'budget', 'reviewissue', 'reviewsetting', 'review', 'milestone', 'measurement', 'measrecord', 'assetlib', 'setting', 'im', 'client', 'ldap', 'dev', 'api', 'gitea', 'gogs', 'zanode', 'zahost');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user