diff --git a/config/zentaopms.php b/config/zentaopms.php index 14a968d96c..f7ef902c2a 100644 --- a/config/zentaopms.php +++ b/config/zentaopms.php @@ -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; diff --git a/db/update21.7.1.sql b/db/update21.7.1.sql index c4549815a7..78df85b2df 100644 --- a/db/update21.7.1.sql +++ b/db/update21.7.1.sql @@ -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`; diff --git a/db/zentao.sql b/db/zentao.sql index f55d20d8ee..23896cc89f 100755 --- a/db/zentao.sql +++ b/db/zentao.sql @@ -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, diff --git a/module/build/test/model/getexecutionbuildsbysearch.php b/module/build/test/model/getexecutionbuildsbysearch.php index aee5dd9305..35edf78912 100755 --- a/module/build/test/model/getexecutionbuildsbysearch.php +++ b/module/build/test/model/getexecutionbuildsbysearch.php @@ -12,12 +12,12 @@ cid=1 - 正常执行查询 - 第19条的execution属性 @101 - 第19条的name属性 @版本19 -- 执行id为0查询统计 @18 +- 执行id为0查询统计 @20 - 正常执行查询统计 @3 - 查询条件查询 - 第17条的execution属性 @125 - 第17条的name属性 @版本17 -- 查询条件查询统计 @18 +- 查询条件查询统计 @20 */ @@ -38,7 +38,7 @@ $build = new buildTest(); r($build->getExecutionBuildsBySearchTest($count[0], $executionIDList[0], $queryIDList[0])) && p('20:execution,name') && e('106,版本20'); // 执行id为0查询 r($build->getExecutionBuildsBySearchTest($count[0], $executionIDList[1], $queryIDList[0])) && p('19:execution,name') && e('101,版本19'); // 正常执行查询 -r($build->getExecutionBuildsBySearchTest($count[1], $executionIDList[0], $queryIDList[0])) && p() && e('18'); // 执行id为0查询统计 +r($build->getExecutionBuildsBySearchTest($count[1], $executionIDList[0], $queryIDList[0])) && p() && e('20'); // 执行id为0查询统计 r($build->getExecutionBuildsBySearchTest($count[1], $executionIDList[1], $queryIDList[0])) && p() && e('3'); // 正常执行查询统计 r($build->getExecutionBuildsBySearchTest($count[0], $executionIDList[0], $queryIDList[1])) && p('17:execution,name') && e('125,版本17'); // 查询条件查询 -r($build->getExecutionBuildsBySearchTest($count[1], $executionIDList[0], $queryIDList[1])) && p() && e('18'); // 查询条件查询统计 +r($build->getExecutionBuildsBySearchTest($count[1], $executionIDList[0], $queryIDList[1])) && p() && e('20'); // 查询条件查询统计 diff --git a/module/install/control.php b/module/install/control.php index 6e57471a05..71fabf15bc 100644 --- a/module/install/control.php +++ b/module/install/control.php @@ -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. diff --git a/module/instance/model.php b/module/instance/model.php index 6ca619756a..19f3034501 100644 --- a/module/instance/model.php +++ b/module/instance/model.php @@ -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; } diff --git a/module/instance/test/model/getbyid.php b/module/instance/test/model/getbyid.php index 2dad75a099..3b62d65cc3 100755 --- a/module/instance/test/model/getbyid.php +++ b/module/instance/test/model/getbyid.php @@ -5,7 +5,6 @@ su('admin'); zenData('instance')->gen(5); zenData('space')->gen(5); -zenData('solution')->gen(5); /** @@ -22,7 +21,6 @@ cid=1 - 属性name @默认空间1 - 查看获取到的第一条instance的solution - 属性id @1 - - 属性name @解决方案1 - 查看获取到的第二条instance - 属性id @2 - 属性name @禅道开源版 @@ -32,7 +30,6 @@ cid=1 - 属性name @默认空间2 - 查看获取到的第二条instance的solution - 属性id @2 - - 属性name @解决方案2 - 查看不存在的instance @0 */ @@ -43,12 +40,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 \ No newline at end of file +r($instance) && p('') && e('0'); // 查看不存在的instance diff --git a/module/instance/test/model/getbyidlist.php b/module/instance/test/model/getbyidlist.php index c9e243f1b5..8d18ff5605 100755 --- a/module/instance/test/model/getbyidlist.php +++ b/module/instance/test/model/getbyidlist.php @@ -5,7 +5,6 @@ su('admin'); zenData('instance')->gen(5); zenData('space')->gen(5); -zenData('solution')->gen(5); /** @@ -32,15 +31,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 +47,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 \ No newline at end of file diff --git a/module/instance/test/model/getlist.php b/module/instance/test/model/getlist.php index 3820f4d960..01af1f5728 100755 --- a/module/instance/test/model/getlist.php +++ b/module/instance/test/model/getlist.php @@ -15,6 +15,7 @@ cid=1 - 通过搜索条件查看获取到的所有instance的数量 @1 - 通过状态查看获取到的所有instance的数量 @5 - 通过状态查看获取到的所有instance的数量 @0 +- 通过状态查看获取到的所有instance的数量 @0 */ @@ -32,3 +33,6 @@ r(count($instance)) && p('') && e('5'); // 通过状态查看获取到的所有i $instance = $tester->instance->getList(null, '', '', 'wait'); r(count($instance)) && p('') && e('0'); // 通过状态查看获取到的所有instance的数量 + +$instance = $tester->instance->getList(null, '', '', 'stop'); +r(count($instance)) && p('') && e('0'); // 通过状态查看获取到的所有instance的数量 diff --git a/module/instance/test/model/instanceofsolution.php b/module/instance/test/model/instanceofsolution.php deleted file mode 100755 index 5c386dde9e..0000000000 --- a/module/instance/test/model/instanceofsolution.php +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env php -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 \ No newline at end of file diff --git a/module/release/test/lib/release.unittest.class.php b/module/release/test/lib/release.unittest.class.php index 87dfce8533..47c833f076 100644 --- a/module/release/test/lib/release.unittest.class.php +++ b/module/release/test/lib/release.unittest.class.php @@ -229,12 +229,12 @@ class releaseTest */ public function changeStatusTest(int $releaseID, string $status) { - $oldRelease = $this->objectModel->getByID($releaseID); + $oldRelease = $this->objectModel->fetchByID($releaseID); $this->objectModel->changeStatus($releaseID, $status); if(dao::isError()) return dao::getError(); - $release = $this->objectModel->getByID($releaseID); + $release = $this->objectModel->fetchByID($releaseID); return common::createChanges($oldRelease, $release); } diff --git a/module/solution/config.php b/module/solution/config.php deleted file mode 100644 index 8e88853748..0000000000 --- a/module/solution/config.php +++ /dev/null @@ -1,5 +0,0 @@ -solution = new stdclass(); - -$config->solution->gitlab = new stdclass(); -$config->solution->gitlab->minCompatibleVersion = '9.0'; diff --git a/module/solution/lang/de.php b/module/solution/lang/de.php deleted file mode 100644 index aae35c6870..0000000000 --- a/module/solution/lang/de.php +++ /dev/null @@ -1,66 +0,0 @@ -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.'; diff --git a/module/solution/lang/en.php b/module/solution/lang/en.php deleted file mode 100644 index aae35c6870..0000000000 --- a/module/solution/lang/en.php +++ /dev/null @@ -1,66 +0,0 @@ -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.'; diff --git a/module/solution/lang/fr.php b/module/solution/lang/fr.php deleted file mode 100644 index aae35c6870..0000000000 --- a/module/solution/lang/fr.php +++ /dev/null @@ -1,66 +0,0 @@ -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.'; diff --git a/module/solution/lang/zh-cn.php b/module/solution/lang/zh-cn.php deleted file mode 100644 index fe14578a85..0000000000 --- a/module/solution/lang/zh-cn.php +++ /dev/null @@ -1,66 +0,0 @@ -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'] = '资源不足, 请增加配置或释放其它资源后重试。'; diff --git a/module/solution/model.php b/module/solution/model.php deleted file mode 100644 index 4e7a69aa4d..0000000000 --- a/module/solution/model.php +++ /dev/null @@ -1,461 +0,0 @@ - - * @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(); - } -} diff --git a/module/solution/test/lib/solution.unittest.class.php b/module/solution/test/lib/solution.unittest.class.php deleted file mode 100644 index cc93bcd2b7..0000000000 --- a/module/solution/test/lib/solution.unittest.class.php +++ /dev/null @@ -1,118 +0,0 @@ - - * @package solution - * @link https://www.zentao.net - */ -class solutionTest -{ - private $objectModel; - public function __construct() - { - su('admin'); - - global $tester, $app; - $this->objectModel = $tester->loadModel('solution'); - - $app->session->cloudChannel = 'stable'; - } - - /** - * Test getByID method. - * - * @param int $solutionID - * @access public - * @return object|null - */ - public function getByIdTest(int $solutionID): object|null - { - return $this->objectModel->getByID($solutionID); - } - - /** - * Test getLastSolution method. - * - * @access public - * @return object|false - */ - public function getLastSolutionTest(): object|false - { - return $this->objectModel->getLastSolution(); - } - - /** - * Test saveStatus method. - * - * @param int $solutionID - * @param string $status - * @access public - * @return object|null - */ - public function saveStatusTest(int $solutionID, string $status): object|null - { - $this->objectModel->saveStatus($solutionID, $status); - if(dao::isError()) return dao::getError(); - - return $this->objectModel->getByID($solutionID); - } - - /** - * Init solution create data for api. - * - * @access private - * @return array - */ - private function initCreateData(): array - { - static $solution, $config; - - if(empty($solution)) - { - $solution = json_decode('{"id":2,"name":"devops","title":"禅道 DevOps 解决方案","introduction":"覆盖从立项到发布,端到端的软件开发全流程跟踪。全面集成 Jenkins、Gitlab 等工具。","background_url":"https://img.qucheng.com/app/d/devops-bg.png","chart":"devops","app_version":"1.1.0","version":"2023.10.901","apps":[{"id":29,"name":"zentao","alias":"禅道开源版","chart":"zentao","app_version":"18.3","version":"2023.4.701","logo":"https://img.qucheng.com/app/z/zentao-icon.svg"},{"id":54,"name":"zentao-biz","alias":"禅道企业版","chart":"zentao-biz","app_version":"8.3","version":"2023.4.701","logo":"https://img.qucheng.com/app/z/zentao-icon.svg"},{"id":51,"name":"zentao-max","alias":"禅道旗舰版","chart":"zentao-max","app_version":"4.3","version":"2023.4.701","logo":"https://img.qucheng.com/app/z/zentao-icon.svg"},{"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"},{"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"},{"id":60,"name":"sonarqube","alias":"SonarQube","chart":"sonarqube","app_version":"9.9.0","version":"2023.10.901","logo":"https://img.qucheng.com/app/s/sonarqube-icon.svg"},{"id":118,"name":"nexus3","alias":"Nexus3","chart":"nexus3","app_version":"3.42.0","version":"2023.10.901","logo":"https://img.qucheng.com/app/n/nexus_icon.png"}],"description":"禅道 DevOps 解决方案是一套软件全生命周期管理、跟踪、集成、发布解决方案。包含禅道项目管理工具、代码仓库、集成工具等。用户可以跟踪软件项目进度,管理代码的集成与发布。","arch_design_url":"https://img.qucheng.com/app/d/devops-arch.svg","scenes":[{"name":"项目管理","description":"软件项目的全生命周期管理"},{"name":"BUG管理","description":"BUG记录与跟踪"},{"name":"文档管理","description":"团队文档共享协同,高效办公"}],"features":[{"name":"自动集成","description":"选择的 Git、CI 应用与禅道自动对接,无需手动配置"},{"name":"代码评审","description":"代码合并前触发评审,可根据代码行、代码段提交 Bug"},{"name":"测试管理","description":"集成 ZTF 自动化测试工具,支持禅道测试用例导入和导出"},{"name":"可定制流水线","description":"根据需要定制流水线步骤,如单元测试、UI测试、镜像安全检查等"}],"customers":[{"name":"禅道","description":"https://img.qucheng.com/app/z/zentao-icon.svg","home":"https://www.zentao.net"}],"links":[{"name":"禅道使用手册","url":"https://www.zentao.net/book/zentaopms/38.html"}]}'); - $solution->apps = array_combine(helper::arrayColumn($solution->apps, 'chart'), $solution->apps); - } - - if(empty($config)) $config = json_decode('{"category":[{"alias":"项目管理","choices":[{"app_version":"18.3","name":"zentao","version":"2023.4.701"},{"app_version":"8.3","name":"zentao-biz","version":"2023.4.701"},{"app_version":"4.3","name":"zentao-max","version":"2023.4.701"}],"external":false,"name":"pms","required":true},{"alias":"源代码管理","choices":[{"app_version":"15.3.4","external":true,"name":"gitlab","version":"2023.10.901"}],"external":false,"name":"git","required":true},{"alias":"流水线引擎","choices":[{"app_version":"2.401.3","external":false,"name":"jenkins","version":"2023.10.901"}],"name":"ci","required":true},{"alias":"代码扫描","choices":[{"app_version":"9.9.0","external":true,"name":"sonarqube","version":"2023.10.901"}],"name":"analysis","required":false},{"alias":"制品库","choices":[{"app_version":"3.42.0","external":false,"name":"nexus3","version":"2023.10.901"}],"name":"artifact","required":false}],"forms":{"gitea":[{"alias":"主机","keys":["env.GIT_DOMAIN","solution.git.host"],"name":"host","type":"string"},{"alias":"用户名","keys":["solution.git.username"],"name":"username","type":"string"},{"alias":"密码","help":{"link":"https://www.qucheng.com/book/Installation-manual/57.html","text":"jenkins需要此帐号密码来拉取代码执行构建"},"keys":["solution.git.password"],"name":"password","type":"string"},{"alias":"Token","help":{"link":"https://www.qucheng.com/book/Installation-manual/53.html","text":"禅道和jenkins需要此token调用gitea接口"},"keys":["solution.git.token","env.GIT_TOKEN"],"name":"token","type":"string"}],"gitlab":[{"alias":"主机","keys":["env.GIT_DOMAIN","solution.git.host"],"name":"host","type":"string"},{"alias":"用户名","keys":["solution.git.username"],"name":"username","type":"string"},{"alias":"密码","help":{"link":"https://www.qucheng.com/book/Installation-manual/56.html","text":"jenkins需要此帐号密码来拉取代码执行构建"},"keys":["solution.git.password"],"name":"password","type":"string"},{"alias":"Token","help":{"link":"https://www.qucheng.com/book/Installation-manual/52.html","text":"禅道和jenkins需要此token调用gitea接口"},"keys":["solution.git.token","env.GIT_TOKEN"],"name":"token","type":"string"}],"sonarqube":[{"alias":"主机","keys":["solution.sonarqube.host","env.SCAN_URL"],"name":"host","type":"string"},{"alias":"用户名","keys":["solution.sonarqube.username","env.SCAN_USERNAME"],"name":"username","type":"string"},{"alias":"密码","help":{"link":"https://www.qucheng.com/book/Installation-manual/54.html","text":"禅道需要此帐号密码来调用sonarqube相关接口"},"keys":["solution.sonarqube.password","env.SCAN_PASSWORD"],"name":"password","type":"string"},{"alias":"Token","help":{"link":"https://www.qucheng.com/book/Installation-manual/54.html","text":"禅道和jenkins需要此token调用gitea接口"},"keys":["solution.sonarqube.token"],"name":"token","type":"string"}]},"mappings":{"gitea":[{"key":"env.GIT_DOMAIN","path":"ingress.host","type":"helm"},{"key":"env.GIT_USERNAME","path":"auth.username","type":"helm"},{"key":"env.GIT_PASSWORD","path":"default_admin_password","type":"secret"},{"key":"solution.git.host","path":"ingress.host","type":"helm"},{"key":"solution.git.username","path":"z_username","type":"secret"},{"key":"solution.git.password","path":"z_password","type":"secret"},{"key":"solution.git.token","path":"api_token","type":"secret"}],"gitlab":[{"key":"env.GIT_DOMAIN","path":"ingress.host","type":"helm"},{"key":"env.GIT_USERNAME","path":"auth.username","type":"helm"},{"key":"env.GIT_PASSWORD","path":"auth.password","type":"helm"},{"key":"solution.git.host","path":"ingress.host","type":"helm"},{"key":"solution.git.username","path":"z_username","type":"secret"},{"key":"solution.git.password","path":"z_password","type":"secret"},{"key":"solution.git.token","path":"api_token","type":"secret"}],"gogs":[{"key":"env.GIT_DOMAIN","path":"ingress.host","type":"helm"},{"key":"env.GIT_USERNAME","path":"auth.username","type":"helm"},{"key":"env.GIT_PASSWORD","path":"default_admin_password","type":"secret"}],"jenkins":[{"key":"env.CI_URL","path":"ingress.host","type":"helm"},{"key":"env.CI_USERNAME","path":"auth.username","type":"helm"},{"key":"env.CI_PASSWORD","path":"jenkins_password","type":"secret"}],"sonarqube":[{"key":"solution.sonarqube.host","path":"ingress.host","type":"helm"},{"key":"solution.sonarqube.token","path":"api_token","type":"secret"},{"key":"env.SCAN_URL","path":"ingress.host","type":"helm"},{"key":"env.SCAN_USERNAME","path":"auth.username","type":"helm"},{"key":"env.SCAN_PASSWORD","path":"auth.password","type":"helm"}]},"order":["git","analysis","artifact","ci","pms"],"settings":{"gitea":[{"key":"ci.enabled","type":"static","value":"true"}],"gitlab":[{"key":"ci.enabled","type":"static","value":"true"}],"jenkins":[{"key":"initContainers.plugins.enabled","type":"static","value":"true"},{"key":"solution.enabled","type":"static","value":"true"},{"key":"solution.git.protocol","type":"auto","value":"protocol"},{"key":"solution.git.type","target":"git","type":"choose"},{"key":"solution.git.group","type":"static","value":"demo"},{"key":"solution.git.host","target":"git","type":"mappings"},{"key":"solution.git.username","target":"git","type":"mappings"},{"key":"solution.git.password","target":"git","type":"mappings"},{"key":"solution.git.token","target":"git","type":"mappings"},{"key":"solution.sonarqube.enabled","type":"static","value":"true","when":"sonarqube"},{"key":"solution.sonarqube.protocol","type":"auto","value":"protocol","when":"sonarqube"},{"key":"solution.sonarqube.host","target":"analysis","type":"mappings","when":"sonarqube"},{"key":"solution.sonarqube.token","target":"analysis","type":"mappings","when":"sonarqube"}],"sonarqube":[{"key":"ci.enabled","type":"static","value":"true"}],"zentao":[{"key":"env.LINK_GIT","type":"static","value":"true"},{"key":"env.GIT_TYPE","target":"git","type":"choose"},{"key":"env.GIT_INSTANCE_NAME","type":"static","value":"QuickOn"},{"key":"env.GIT_USERNAME","target":"git","type":"mappings"},{"key":"env.GIT_PASSWORD","target":"git","type":"mappings"},{"key":"env.GIT_TOKEN","target":"git","type":"mappings"},{"key":"env.GIT_DOMAIN","target":"git","type":"mappings"},{"key":"env.LINK_CI","type":"static","value":"true"},{"key":"env.CI_TYPE","target":"ci","type":"choose"},{"key":"env.CI_USERNAME","target":"ci","type":"mappings"},{"key":"env.CI_PASSWORD","target":"ci","type":"mappings"},{"key":"env.CI_URL","target":"ci","type":"mappings"},{"key":"env.LINK_SCAN","type":"static","value":"true"},{"key":"env.SCAN_TYPE","target":"analysis","type":"choose"},{"key":"env.SCAN_URL","target":"analysis","type":"mappings"},{"key":"env.SCAN_USERNAME","target":"analysis","type":"mappings"},{"key":"env.SCAN_PASSWORD","target":"analysis","type":"mappings"}],"zentao-biz":[{"key":"env.LINK_GIT","type":"static","value":"true"},{"key":"env.GIT_TYPE","target":"git","type":"choose"},{"key":"env.GIT_INSTANCE_NAME","type":"static","value":"QuickOn"},{"key":"env.GIT_USERNAME","target":"git","type":"mappings"},{"key":"env.GIT_PASSWORD","target":"git","type":"mappings"},{"key":"env.GIT_TOKEN","target":"git","type":"mappings"},{"key":"env.GIT_DOMAIN","target":"git","type":"mappings"},{"key":"env.LINK_CI","type":"static","value":"true"},{"key":"env.CI_TYPE","target":"ci","type":"choose"},{"key":"env.CI_USERNAME","target":"ci","type":"mappings"},{"key":"env.CI_PASSWORD","target":"ci","type":"mappings"},{"key":"env.CI_URL","target":"ci","type":"mappings"},{"key":"env.LINK_SCAN","type":"static","value":"true"},{"key":"env.SCAN_TYPE","target":"analysis","type":"choose"},{"key":"env.SCAN_URL","target":"analysis","type":"mappings"},{"key":"env.SCAN_USERNAME","target":"analysis","type":"mappings"},{"key":"env.SCAN_PASSWORD","target":"analysis","type":"mappings"}],"zentao-max":[{"key":"env.LINK_GIT","type":"static","value":"true"},{"key":"env.GIT_TYPE","target":"git","type":"choose"},{"key":"env.GIT_INSTANCE_NAME","type":"static","value":"QuickOn"},{"key":"env.GIT_USERNAME","target":"git","type":"mappings"},{"key":"env.GIT_PASSWORD","target":"git","type":"mappings"},{"key":"env.GIT_TOKEN","target":"git","type":"mappings"},{"key":"env.GIT_DOMAIN","target":"git","type":"mappings"},{"key":"env.LINK_CI","type":"static","value":"true"},{"key":"env.CI_TYPE","target":"ci","type":"choose"},{"key":"env.CI_USERNAME","target":"ci","type":"mappings"},{"key":"env.CI_PASSWORD","target":"ci","type":"mappings"},{"key":"env.CI_URL","target":"ci","type":"mappings"},{"key":"env.LINK_SCAN","type":"static","value":"true"},{"key":"env.SCAN_TYPE","target":"analysis","type":"choose"},{"key":"env.SCAN_URL","target":"analysis","type":"mappings"},{"key":"env.SCAN_USERNAME","target":"analysis","type":"mappings"},{"key":"env.SCAN_PASSWORD","target":"analysis","type":"mappings"}]}}'); - return array($solution, $config); - } - - /** - * Test create method. - * - * @param array $postData - * @access public - * @return object|null - */ - public function createTest(array $postData): object|null - { - global $app; - $app->user = new stdclass(); - foreach($postData as $key => $value) $app->post->set($key, $value); - - list($cloudSolution, $components) = $this->initCreateData(); - $solution = $this->objectModel->create($cloudSolution, $components); - - foreach($postData as $key => $value) $app->post->set($key, ''); - return $solution; - } - - /** - * Test pickAppFromSchema method. - * - * @param string $category - * @param string $application - * @access public - * @return object|null - */ - public function pickAppFromSchemaTest(string $category, string $application): object|null - { - list($cloudSolution, $components) = $this->initCreateData(); - return $this->objectModel->pickAppFromSchema($components, $category, $application, $cloudSolution); - } -} diff --git a/module/solution/test/model/create.php b/module/solution/test/model/create.php deleted file mode 100755 index 964449136f..0000000000 --- a/module/solution/test/model/create.php +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env php -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"}}'); // 选择两个应用 \ No newline at end of file diff --git a/module/solution/test/model/getbyid.php b/module/solution/test/model/getbyid.php deleted file mode 100755 index 68c2c5364e..0000000000 --- a/module/solution/test/model/getbyid.php +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/env php -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不存在 \ No newline at end of file diff --git a/module/solution/test/model/getlastsolution.php b/module/solution/test/model/getlastsolution.php deleted file mode 100755 index 7da45d0a71..0000000000 --- a/module/solution/test/model/getlastsolution.php +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env php -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'); // 没有数据时获取最后一个解决方案 \ No newline at end of file diff --git a/module/solution/test/model/pickappfromschema.php b/module/solution/test/model/pickappfromschema.php deleted file mode 100755 index 6793ad404e..0000000000 --- a/module/solution/test/model/pickappfromschema.php +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env php -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'); // 类别和应用对应 \ No newline at end of file diff --git a/module/solution/test/model/savestatus.php b/module/solution/test/model/savestatus.php deleted file mode 100755 index bb67969f17..0000000000 --- a/module/solution/test/model/savestatus.php +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env php -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'); // 不存在的解决方案 \ No newline at end of file diff --git a/module/solution/test/yaml/instance.yaml b/module/solution/test/yaml/instance.yaml deleted file mode 100644 index 6df6ba9328..0000000000 --- a/module/solution/test/yaml/instance.yaml +++ /dev/null @@ -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" -... diff --git a/module/solution/test/yaml/solution.yaml b/module/solution/test/yaml/solution.yaml deleted file mode 100644 index 6d397c4d0c..0000000000 --- a/module/solution/test/yaml/solution.yaml +++ /dev/null @@ -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`' -... diff --git a/module/solution/test/yaml/space.yaml b/module/solution/test/yaml/space.yaml deleted file mode 100644 index 534a8c4700..0000000000 --- a/module/solution/test/yaml/space.yaml +++ /dev/null @@ -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" -... diff --git a/module/space/control.php b/module/space/control.php index 36a446e588..1e362157f8 100644 --- a/module/space/control.php +++ b/module/space/control.php @@ -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'); diff --git a/module/space/model.php b/module/space/model.php index 55158bbfd6..8655d7d818 100644 --- a/module/space/model.php +++ b/module/space/model.php @@ -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; } diff --git a/module/space/ui/browse.html.php b/module/space/ui/browse.html.php index 04a4a1155b..dab669702b 100644 --- a/module/space/ui/browse.html.php +++ b/module/space/ui/browse.html.php @@ -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, diff --git a/module/store/model.php b/module/store/model.php index 44f008b3c8..329554e348 100644 --- a/module/store/model.php +++ b/module/store/model.php @@ -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. diff --git a/module/store/test/lib/store.unittest.class.php b/module/store/test/lib/store.unittest.class.php index f59467ec81..a655aa0d58 100755 --- a/module/store/test/lib/store.unittest.class.php +++ b/module/store/test/lib/store.unittest.class.php @@ -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. diff --git a/module/store/test/model/appdynamic.php b/module/store/test/model/appdynamic.php index 852598f3f0..ac5c7a175d 100755 --- a/module/store/test/model/appdynamic.php +++ b/module/store/test/model/appdynamic.php @@ -10,6 +10,9 @@ cid=1 - 测试获取应用动态第一页信息 @Success - 测试每页展示5条动态 @5 +- 测试每页最多展示10条动态 @7 +- 测试每页最多展示15条动态 @7 +- 测试每页最多展示0条动态 @7 */ @@ -20,8 +23,11 @@ zenData('user')->gen(5); su('admin'); $pageIdList = array(1, 2); -$pageList = array(20, 5); +$pageList = array(20, 5, 10, 15, 30); $store = new storeTest(); r($store->appDynamicTest(29, $pageIdList[0], $pageList[0])) && p() && e('Success'); //测试获取应用动态第一页信息 -r($store->appDynamicTest(29, $pageIdList[0], $pageList[1])) && p() && e('5'); //测试每页展示5条动态 \ No newline at end of file +r($store->appDynamicTest(29, $pageIdList[0], $pageList[1])) && p() && e('5'); //测试每页展示5条动态 +r($store->appDynamicTest(29, $pageIdList[0], $pageList[2])) && p() && e('7'); //测试每页最多展示10条动态 +r($store->appDynamicTest(29, $pageIdList[0], $pageList[3])) && p() && e('7'); //测试每页最多展示15条动态 +r($store->appDynamicTest(29, $pageIdList[0], 0)) && p() && e('7'); //测试每页最多展示0条动态 diff --git a/module/store/test/model/getsolution.php b/module/store/test/model/getsolution.php deleted file mode 100755 index c64357e09f..0000000000 --- a/module/store/test/model/getsolution.php +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env php -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'); //测试查询失败 \ No newline at end of file diff --git a/module/store/test/model/solutionconfig.php b/module/store/test/model/solutionconfig.php deleted file mode 100755 index 578ced70cf..0000000000 --- a/module/store/test/model/solutionconfig.php +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env php -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'); //测试查询无数据 \ No newline at end of file diff --git a/module/upgrade/config.php b/module/upgrade/config.php index 966a502cea..b76d86f78b 100644 --- a/module/upgrade/config.php +++ b/module/upgrade/config.php @@ -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'); diff --git a/test/lib/coverage.php b/test/lib/coverage.php index e1e37e6169..ae3420b802 100644 --- a/test/lib/coverage.php +++ b/test/lib/coverage.php @@ -591,6 +591,8 @@ EOT; if(!$tracesFiles) return false ; $tracesList = array(); + $tracesList['ztfPath'] = ''; + $tracesList['time'] = ''; foreach($tracesFiles as $file) { $tracesInfo = json_decode(file_get_contents($file), true); @@ -615,7 +617,7 @@ EOT; } $tracesList['time'] = $tracesInfo['time']; - $tracesList['ztfPath'] = $tracesInfo['ztfPath']; + if(!empty($tracesInfo['ztfPath'])) $tracesList['ztfPath'] = $tracesInfo['ztfPath']; } if($key == '') return $tracesList;