@uofx/cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +40 -0
- package/README.md +444 -0
- package/THIRD-PARTY-NOTICES.txt +894 -0
- package/dist/application/dtos/index.js +24 -0
- package/dist/application/dtos/request/delete-instance.request.dto.js +3 -0
- package/dist/application/dtos/request/get-config.request.dto.js +3 -0
- package/dist/application/dtos/request/get-credentials.request.dto.js +3 -0
- package/dist/application/dtos/request/index.js +27 -0
- package/dist/application/dtos/request/install-instance.request.dto.js +3 -0
- package/dist/application/dtos/request/list-charts.request.dto.js +3 -0
- package/dist/application/dtos/request/set-config.request.dto.js +16 -0
- package/dist/application/dtos/request/setup-environment.request.dto.js +16 -0
- package/dist/application/dtos/request/show-logs.request.dto.js +19 -0
- package/dist/application/dtos/request/start-instance.request.dto.js +3 -0
- package/dist/application/dtos/request/stop-instance.request.dto.js +3 -0
- package/dist/application/dtos/response/credentials.response.dto.js +3 -0
- package/dist/application/dtos/response/delete-instance.response.dto.js +3 -0
- package/dist/application/dtos/response/index.js +26 -0
- package/dist/application/dtos/response/install-instance.response.dto.js +3 -0
- package/dist/application/dtos/response/instance-list.response.dto.js +3 -0
- package/dist/application/dtos/response/instance-status.response.dto.js +3 -0
- package/dist/application/dtos/response/setup-result.response.dto.js +3 -0
- package/dist/application/dtos/response/show-logs.response.dto.js +3 -0
- package/dist/application/dtos/response/start-instance.response.dto.js +3 -0
- package/dist/application/dtos/response/stop-instance.response.dto.js +3 -0
- package/dist/application/index.js +25 -0
- package/dist/application/interfaces/index.js +24 -0
- package/dist/application/interfaces/use-case.interface.js +3 -0
- package/dist/application/use-cases/config/get-config.use-case.js +66 -0
- package/dist/application/use-cases/config/set-config.use-case.js +49 -0
- package/dist/application/use-cases/credentials/get-credentials.use-case.js +57 -0
- package/dist/application/use-cases/index.js +28 -0
- package/dist/application/use-cases/instance/delete-instance.use-case.js +81 -0
- package/dist/application/use-cases/instance/index.js +23 -0
- package/dist/application/use-cases/instance/install-instance.use-case.js +424 -0
- package/dist/application/use-cases/instance/list-charts.use-case.js +43 -0
- package/dist/application/use-cases/instance/list-instances.use-case.js +62 -0
- package/dist/application/use-cases/instance/start-instance.use-case.js +154 -0
- package/dist/application/use-cases/instance/stop-instance.use-case.js +55 -0
- package/dist/application/use-cases/logs/show-logs.use-case.js +66 -0
- package/dist/application/use-cases/setup/setup-environment.use-case.js +53 -0
- package/dist/cli.js +286 -0
- package/dist/constants/config-defaults.js +23 -0
- package/dist/constants/defaults.js +89 -0
- package/dist/constants/deployment.js +39 -0
- package/dist/constants/environments.js +93 -0
- package/dist/constants/index.js +53 -0
- package/dist/constants/oci-artifacts.js +25 -0
- package/dist/constants/paths.js +92 -0
- package/dist/constants/timeouts.js +60 -0
- package/dist/di/container.js +34 -0
- package/dist/di/index.js +22 -0
- package/dist/di/modules/application.module.js +54 -0
- package/dist/di/modules/infrastructure.module.js +206 -0
- package/dist/di/modules/interceptor.module.js +68 -0
- package/dist/di/modules/presentation.module.js +31 -0
- package/dist/di/tokens.js +149 -0
- package/dist/domain/decorators/sensitive.decorator.js +39 -0
- package/dist/domain/entities/credentials-resolver.entity.js +127 -0
- package/dist/domain/entities/credentials.entity.js +65 -0
- package/dist/domain/entities/delete-instance-validation.entity.js +100 -0
- package/dist/domain/entities/deployment-parameters.entity.js +120 -0
- package/dist/domain/entities/environment-validation.entity.js +125 -0
- package/dist/domain/entities/index.js +29 -0
- package/dist/domain/entities/instance-lifecycle-state.entity.js +100 -0
- package/dist/domain/entities/instance-list-aggregator.entity.js +104 -0
- package/dist/domain/entities/instance-metadata.entity.js +86 -0
- package/dist/domain/entities/instance-status.entity.js +79 -0
- package/dist/domain/entities/instance.entity.js +128 -0
- package/dist/domain/entities/log-filter.entity.js +141 -0
- package/dist/domain/index.js +29 -0
- package/dist/domain/interfaces/safe-loggable.interface.js +3 -0
- package/dist/domain/ports/app-config.port.js +3 -0
- package/dist/domain/ports/base-image.port.js +3 -0
- package/dist/domain/ports/chart-version.port.js +3 -0
- package/dist/domain/ports/correlation-id.port.js +3 -0
- package/dist/domain/ports/credentials.port.js +3 -0
- package/dist/domain/ports/deployment.port.js +3 -0
- package/dist/domain/ports/error-handler.port.js +3 -0
- package/dist/domain/ports/index.js +46 -0
- package/dist/domain/ports/instance-manager.port.js +3 -0
- package/dist/domain/ports/instance-metadata.port.js +8 -0
- package/dist/domain/ports/instance-storage.port.js +3 -0
- package/dist/domain/ports/k8s-deployer.port.js +3 -0
- package/dist/domain/ports/logger.port.js +14 -0
- package/dist/domain/ports/output.port.js +3 -0
- package/dist/domain/ports/runtime-environment.port.js +6 -0
- package/dist/domain/ports/user-interaction.port.js +9 -0
- package/dist/domain/ports/user-settings.port.js +3 -0
- package/dist/domain/types/index.js +22 -0
- package/dist/domain/types/logger.types.js +29 -0
- package/dist/domain/types/validation.types.js +9 -0
- package/dist/domain/value-objects/acr-credentials.value-object.js +92 -0
- package/dist/domain/value-objects/chart-version.value-object.js +124 -0
- package/dist/domain/value-objects/config-log-level.value-object.js +84 -0
- package/dist/domain/value-objects/connection-info.value-object.js +65 -0
- package/dist/domain/value-objects/index.js +25 -0
- package/dist/domain/value-objects/instance-name.value-object.js +91 -0
- package/dist/domain/value-objects/jwt-key.value-object.js +97 -0
- package/dist/domain/value-objects/mssql-password.value-object.js +140 -0
- package/dist/domain/value-objects/rsa-key-pair.value-object.js +181 -0
- package/dist/index.js +6 -0
- package/dist/infrastructure/config/app-config.interface.js +3 -0
- package/dist/infrastructure/config/app-config.service.js +280 -0
- package/dist/infrastructure/config/config-validator.js +31 -0
- package/dist/infrastructure/config/crypto.service.js +125 -0
- package/dist/infrastructure/deployment/deployment.adapter.js +118 -0
- package/dist/infrastructure/deployment/interfaces/acr-credential-manager.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/app-manager.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/helm-registry.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/infra-manager.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/k8s-job-runner.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/mssql-database-init.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/mssql-helm-deployment.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/mssql-storage.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/mssql-user-manager.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/oci-artifact.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/secret-manager.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/service-manager.interface.js +3 -0
- package/dist/infrastructure/deployment/interfaces/version-compatibility.interface.js +3 -0
- package/dist/infrastructure/deployment/services/acr-credential-manager.service.js +144 -0
- package/dist/infrastructure/deployment/services/app-manager.service.js +193 -0
- package/dist/infrastructure/deployment/services/base-helm-deployment.service.js +163 -0
- package/dist/infrastructure/deployment/services/helm-registry.service.js +126 -0
- package/dist/infrastructure/deployment/services/infra-manager.service.js +130 -0
- package/dist/infrastructure/deployment/services/k8s-job-runner.service.js +194 -0
- package/dist/infrastructure/deployment/services/mssql-database-init.service.js +139 -0
- package/dist/infrastructure/deployment/services/mssql-helm-deployment.service.js +100 -0
- package/dist/infrastructure/deployment/services/mssql-storage.service.js +54 -0
- package/dist/infrastructure/deployment/services/mssql-user-manager.service.js +66 -0
- package/dist/infrastructure/deployment/services/oci-artifact.service.js +289 -0
- package/dist/infrastructure/deployment/services/secret-manager.service.js +179 -0
- package/dist/infrastructure/deployment/services/service-manager.service.js +82 -0
- package/dist/infrastructure/deployment/services/version-compatibility.service.js +291 -0
- package/dist/infrastructure/environment/interfaces/hardware-info.interface.js +3 -0
- package/dist/infrastructure/environment/interfaces/network-checker.interface.js +3 -0
- package/dist/infrastructure/environment/services/hardware-info.service.js +135 -0
- package/dist/infrastructure/environment/services/network-checker.service.js +142 -0
- package/dist/infrastructure/environment/windows-environment.adapter.js +162 -0
- package/dist/infrastructure/errors/app-error.js +73 -0
- package/dist/infrastructure/errors/error-handler.interface.js +3 -0
- package/dist/infrastructure/errors/error-handler.js +218 -0
- package/dist/infrastructure/errors/exit-codes.js +27 -0
- package/dist/infrastructure/errors/index.js +25 -0
- package/dist/infrastructure/execution/builders/base-command.builder.js +122 -0
- package/dist/infrastructure/execution/builders/host-command.builder.js +58 -0
- package/dist/infrastructure/execution/builders/windows-host-command.builder.js +50 -0
- package/dist/infrastructure/execution/builders/wsl-command.builder.js +29 -0
- package/dist/infrastructure/execution/command-builder.js +252 -0
- package/dist/infrastructure/execution/command-executor.service.js +230 -0
- package/dist/infrastructure/execution/environments/wsl-execution.environment.js +70 -0
- package/dist/infrastructure/execution/execution-environment.factory.js +53 -0
- package/dist/infrastructure/execution/index.js +25 -0
- package/dist/infrastructure/execution/interfaces/command-builder.interface.js +3 -0
- package/dist/infrastructure/execution/interfaces/command-executor.interface.js +3 -0
- package/dist/infrastructure/execution/interfaces/execution-environment-factory.interface.js +3 -0
- package/dist/infrastructure/execution/interfaces/execution-environment.interface.js +7 -0
- package/dist/infrastructure/execution/interfaces/host-command-builder.interface.js +3 -0
- package/dist/infrastructure/execution/interfaces/index.js +23 -0
- package/dist/infrastructure/execution/interfaces/script-executor.interface.js +3 -0
- package/dist/infrastructure/execution/script-executor.service.js +171 -0
- package/dist/infrastructure/http/http-client.service.js +176 -0
- package/dist/infrastructure/http/index.js +18 -0
- package/dist/infrastructure/http/interfaces/http-client.interface.js +3 -0
- package/dist/infrastructure/interceptors/index.js +8 -0
- package/dist/infrastructure/interceptors/interceptor.factory.js +44 -0
- package/dist/infrastructure/interceptors/interceptor.interface.js +3 -0
- package/dist/infrastructure/interceptors/logging.interceptor.js +171 -0
- package/dist/infrastructure/logger/correlation-id.adapter.js +68 -0
- package/dist/infrastructure/logger/index.js +23 -0
- package/dist/infrastructure/logger/interfaces/index.js +22 -0
- package/dist/infrastructure/logger/interfaces/log-reader.repository.interface.js +7 -0
- package/dist/infrastructure/logger/interfaces/log-writer.repository.interface.js +7 -0
- package/dist/infrastructure/logger/logger.adapter.js +274 -0
- package/dist/infrastructure/logger/services/file-log-reader.repository.js +148 -0
- package/dist/infrastructure/logger/services/file-log-writer.repository.js +307 -0
- package/dist/infrastructure/logger/services/index.js +22 -0
- package/dist/infrastructure/persistence/index.js +25 -0
- package/dist/infrastructure/persistence/instance-metadata.adapter.js +100 -0
- package/dist/infrastructure/persistence/instance-storage.adapter.js +64 -0
- package/dist/infrastructure/persistence/interfaces/config.repository.interface.js +3 -0
- package/dist/infrastructure/persistence/interfaces/index.js +22 -0
- package/dist/infrastructure/persistence/interfaces/instance.repository.interface.js +3 -0
- package/dist/infrastructure/persistence/services/file-system-config.repository.js +168 -0
- package/dist/infrastructure/persistence/services/file-system-instance.repository.js +170 -0
- package/dist/infrastructure/persistence/services/index.js +22 -0
- package/dist/infrastructure/persistence/user-settings.adapter.js +55 -0
- package/dist/infrastructure/platform-detector.js +71 -0
- package/dist/infrastructure/platforms/windows/interfaces/microk8s.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/rootfs-manager.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/windows-features.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/windows-info.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/wsl-config.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/wsl-info.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/wsl-instance-inspection.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/wsl-instance-lifecycle.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/wsl-instance-naming.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/wsl-manager.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/wsl-resources.interface.js +8 -0
- package/dist/infrastructure/platforms/windows/interfaces/wsl-updater.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/interfaces/wslconfig-parser.interface.js +3 -0
- package/dist/infrastructure/platforms/windows/parsers/wsl-version.parser.js +133 -0
- package/dist/infrastructure/platforms/windows/services/microk8s.service.js +168 -0
- package/dist/infrastructure/platforms/windows/services/rootfs-manager.service.js +336 -0
- package/dist/infrastructure/platforms/windows/services/windows-features.service.js +191 -0
- package/dist/infrastructure/platforms/windows/services/windows-info.service.js +138 -0
- package/dist/infrastructure/platforms/windows/services/wsl-config.service.js +171 -0
- package/dist/infrastructure/platforms/windows/services/wsl-info.service.js +226 -0
- package/dist/infrastructure/platforms/windows/services/wsl-instance-inspection.service.js +325 -0
- package/dist/infrastructure/platforms/windows/services/wsl-instance-lifecycle.service.js +442 -0
- package/dist/infrastructure/platforms/windows/services/wsl-instance-naming.service.js +93 -0
- package/dist/infrastructure/platforms/windows/services/wsl-updater.service.js +273 -0
- package/dist/infrastructure/platforms/windows/services/wslconfig-parser.service.js +222 -0
- package/dist/infrastructure/platforms/windows/wsl-base-image.adapter.js +41 -0
- package/dist/infrastructure/platforms/windows/wsl-instance-manager.adapter.js +150 -0
- package/dist/infrastructure/utils/error-formatter.util.js +29 -0
- package/dist/infrastructure/utils/file-operations.util.js +201 -0
- package/dist/infrastructure/utils/input-validator.util.js +152 -0
- package/dist/infrastructure/utils/retry.util.js +98 -0
- package/dist/presentation/controllers/config.controller.js +146 -0
- package/dist/presentation/controllers/credentials.controller.js +105 -0
- package/dist/presentation/controllers/index.js +25 -0
- package/dist/presentation/controllers/instance.controller.js +363 -0
- package/dist/presentation/controllers/logs.controller.js +103 -0
- package/dist/presentation/controllers/setup.controller.js +175 -0
- package/dist/presentation/interfaces/cli-options.interface.js +8 -0
- package/dist/presentation/prompts/acr-credentials.prompt.js +76 -0
- package/dist/presentation/prompts/index.js +21 -0
- package/dist/presentation/ui/cli-progress.service.js +193 -0
- package/dist/presentation/ui/constants/output-symbols.js +42 -0
- package/dist/presentation/ui/index.js +27 -0
- package/dist/presentation/ui/interaction.service.js +276 -0
- package/dist/presentation/ui/interfaces/cli-progress.interface.js +9 -0
- package/dist/presentation/ui/interfaces/output-formatter.interface.js +23 -0
- package/dist/presentation/ui/log-level.enum.js +66 -0
- package/dist/presentation/ui/output-builder.service.js +378 -0
- package/dist/presentation/ui/output-formatter.service.js +393 -0
- package/package.json +65 -0
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.InstallInstanceUseCase = void 0;
|
|
16
|
+
const tsyringe_1 = require("tsyringe");
|
|
17
|
+
const value_objects_1 = require("../../../domain/value-objects");
|
|
18
|
+
const app_error_1 = require("../../../infrastructure/errors/app-error");
|
|
19
|
+
const exit_codes_1 = require("../../../infrastructure/errors/exit-codes");
|
|
20
|
+
const entities_1 = require("../../../domain/entities");
|
|
21
|
+
const error_formatter_util_1 = require("../../../infrastructure/utils/error-formatter.util");
|
|
22
|
+
const tokens_1 = require("../../../di/tokens");
|
|
23
|
+
const runtime_environment_port_1 = require("../../../domain/ports/runtime-environment.port");
|
|
24
|
+
const timeouts_1 = require("../../../constants/timeouts");
|
|
25
|
+
/**
|
|
26
|
+
* 安裝實例 Use Case
|
|
27
|
+
*
|
|
28
|
+
* 協調整個 UOFX 開發環境的安裝流程
|
|
29
|
+
* 特點:完全無 UI 依賴,透過 Progress 介面回調通知進度
|
|
30
|
+
*/
|
|
31
|
+
let InstallInstanceUseCase = class InstallInstanceUseCase {
|
|
32
|
+
constructor(instanceManager, instanceStorage, deploymentPort, baseImagePort, appConfigPort, errorHandler, runtimeEnvironment, userInteraction, httpClient) {
|
|
33
|
+
this.instanceManager = instanceManager;
|
|
34
|
+
this.instanceStorage = instanceStorage;
|
|
35
|
+
this.deploymentPort = deploymentPort;
|
|
36
|
+
this.baseImagePort = baseImagePort;
|
|
37
|
+
this.appConfigPort = appConfigPort;
|
|
38
|
+
this.errorHandler = errorHandler;
|
|
39
|
+
this.runtimeEnvironment = runtimeEnvironment;
|
|
40
|
+
this.userInteraction = userInteraction;
|
|
41
|
+
this.httpClient = httpClient;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* 執行安裝流程
|
|
45
|
+
* @param request - 安裝請求
|
|
46
|
+
* @param output - 輸出介面(可選)
|
|
47
|
+
* @returns 安裝結果
|
|
48
|
+
*/
|
|
49
|
+
async execute(request, output) {
|
|
50
|
+
output?.info('Installing UOFX development environment...').newline().flush();
|
|
51
|
+
// [1/14] 檢查 WSL 是否已安裝
|
|
52
|
+
await this.checkWslInstalled(output);
|
|
53
|
+
output?.newline().flush();
|
|
54
|
+
// [2/14] 檢查記憶體
|
|
55
|
+
await this.checkMemoryAvailability(output);
|
|
56
|
+
output?.newline().flush();
|
|
57
|
+
// [3/14] 解析 Chart 版本
|
|
58
|
+
const instanceName = value_objects_1.InstanceName.create(request.name);
|
|
59
|
+
const chartVersion = await this.resolveChartVersion(request.chartVersion, output);
|
|
60
|
+
output?.newline().flush();
|
|
61
|
+
// [4/14] 檢查是否有其他實例正在運行
|
|
62
|
+
await this.ensureNoRunningInstances(output);
|
|
63
|
+
output?.newline().flush();
|
|
64
|
+
// 檢查實例是否已存在
|
|
65
|
+
const exists = await this.instanceManager.exists(instanceName);
|
|
66
|
+
if (exists) {
|
|
67
|
+
throw new Error(`Instance "${request.name}" already exists`);
|
|
68
|
+
}
|
|
69
|
+
// [5/14] 準備憑證
|
|
70
|
+
const acrCredentials = await this.getAcrCredentials(request.pullSecretPath, output);
|
|
71
|
+
output?.newline().flush();
|
|
72
|
+
// [6/14] 準備部署參數
|
|
73
|
+
const deploymentParams = this.prepareDeploymentParameters(instanceName, acrCredentials, output);
|
|
74
|
+
// [7/14] 下載 Rootfs
|
|
75
|
+
output?.section('[7/14] Checking Ubuntu rootfs').flush();
|
|
76
|
+
output?.item('arrow', 'Checking rootfs image...').flush();
|
|
77
|
+
const rootfsPath = await this.baseImagePort.getOrDownload();
|
|
78
|
+
output?.success(`Rootfs ready: ${rootfsPath}`).newline().flush();
|
|
79
|
+
// [8/14] 建立實例
|
|
80
|
+
output?.section('[8/14] Creating instance').flush();
|
|
81
|
+
const installPath = this.appConfigPort.getInstallPath(instanceName.toString());
|
|
82
|
+
const config = {
|
|
83
|
+
rootfsPath,
|
|
84
|
+
installPath,
|
|
85
|
+
chartVersion: chartVersion.toString()
|
|
86
|
+
};
|
|
87
|
+
await this.instanceManager.create(instanceName, config, output);
|
|
88
|
+
output?.success('Instance created').flush();
|
|
89
|
+
// 註冊中斷清理 handler(傳入 output 用於輸出清理訊息)
|
|
90
|
+
this.errorHandler.registerCleanupHandler(async () => {
|
|
91
|
+
await this.cleanupInstance(instanceName, output);
|
|
92
|
+
}, output);
|
|
93
|
+
output?.newline().flush();
|
|
94
|
+
// 6. 儲存 metadata
|
|
95
|
+
const cliVersion = this.appConfigPort.getCliVersion();
|
|
96
|
+
const metadata = entities_1.InstanceMetadata.create(instanceName, cliVersion, 'Ubuntu 22.04', chartVersion);
|
|
97
|
+
await this.instanceStorage.saveInstance(metadata);
|
|
98
|
+
// [9/14] 取得環境版本並初始化系統
|
|
99
|
+
output?.section('[9/14] System initialization').flush();
|
|
100
|
+
const environmentVersion = await this.deploymentPort.getEnvironmentVersion(chartVersion.toString());
|
|
101
|
+
await this.initializeSystem(instanceName, deploymentParams, environmentVersion, output);
|
|
102
|
+
output?.newline().flush();
|
|
103
|
+
// 8. 部署 K8s 資源 (步驟 4-8)
|
|
104
|
+
await this.deployK8sResources(instanceName, deploymentParams, chartVersion, output);
|
|
105
|
+
// 成功完成 - 清除清理 handler
|
|
106
|
+
this.errorHandler.clearCleanupHandler();
|
|
107
|
+
// 取得連線資訊
|
|
108
|
+
const instanceIp = await this.instanceManager.getInstanceIP(instanceName);
|
|
109
|
+
const connectionInfo = value_objects_1.ConnectionInfo.create(instanceIp);
|
|
110
|
+
return {
|
|
111
|
+
instanceName: request.name,
|
|
112
|
+
fullInstanceName: instanceName.fullName,
|
|
113
|
+
chartVersion: chartVersion.toString(),
|
|
114
|
+
installedAt: new Date().toISOString(),
|
|
115
|
+
connectionInfo: connectionInfo.toDto(),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* 解析 Chart 版本
|
|
120
|
+
* @param versionInput - 使用者輸入的版本
|
|
121
|
+
* @param output - 輸出介面
|
|
122
|
+
* @returns Chart 版本物件
|
|
123
|
+
*/
|
|
124
|
+
async resolveChartVersion(versionInput, output) {
|
|
125
|
+
output?.section('[3/14] Resolving chart version').flush();
|
|
126
|
+
if (versionInput) {
|
|
127
|
+
// 使用者提供版本,直接驗證
|
|
128
|
+
output?.item('arrow', 'Validating specified version...').flush();
|
|
129
|
+
const version = value_objects_1.ChartVersion.create(versionInput);
|
|
130
|
+
const isValid = await this.deploymentPort.validateChartVersion('uofx', version);
|
|
131
|
+
if (!isValid) {
|
|
132
|
+
throw new Error(`Chart version "${versionInput}" does not exist`);
|
|
133
|
+
}
|
|
134
|
+
output?.success(`Using version: ${version.toString()}`).flush();
|
|
135
|
+
return version;
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
// 未提供版本,取得最新相容版本
|
|
139
|
+
output?.item('arrow', 'Resolving latest compatible version...').flush();
|
|
140
|
+
const latestVersion = await this.deploymentPort.getLatestCompatibleVersion('uofx');
|
|
141
|
+
output?.success(`Using version: ${latestVersion.toString()}`).flush();
|
|
142
|
+
return latestVersion;
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* 取得 ACR 憑證
|
|
147
|
+
* @param pullSecretPath - Pull secret 檔案路徑(可選)
|
|
148
|
+
* @param output - 輸出介面
|
|
149
|
+
* @returns ACR 憑證
|
|
150
|
+
*/
|
|
151
|
+
async getAcrCredentials(pullSecretPath, output) {
|
|
152
|
+
output?.section('[5/14] Checking ACR credentials').flush();
|
|
153
|
+
output?.item('arrow', 'Loading credentials...').flush();
|
|
154
|
+
// 載入可用的憑證來源
|
|
155
|
+
const fileCredentials = pullSecretPath
|
|
156
|
+
? this.appConfigPort.loadAcrCredentialsFromFile(pullSecretPath)
|
|
157
|
+
: null;
|
|
158
|
+
const configCredentials = this.appConfigPort.getAcrCredentials();
|
|
159
|
+
// 使用 CredentialsResolver 決定優先級
|
|
160
|
+
const resolver = entities_1.CredentialsResolver.create(fileCredentials, configCredentials, pullSecretPath);
|
|
161
|
+
// 解析憑證(會依優先級選擇)
|
|
162
|
+
const credentials = resolver.resolveOrThrow();
|
|
163
|
+
// 顯示憑證來源
|
|
164
|
+
if (resolver.source === 'file') {
|
|
165
|
+
output
|
|
166
|
+
?.item('bullet', `Reading from: ${pullSecretPath}`)
|
|
167
|
+
.success('Credentials loaded from file')
|
|
168
|
+
.flush();
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
output?.success('Using credentials from config').flush();
|
|
172
|
+
}
|
|
173
|
+
output?.item('bullet', `ACR: ${credentials.name}`).flush();
|
|
174
|
+
return credentials;
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* 準備部署參數
|
|
178
|
+
* @param instanceName - 實例名稱
|
|
179
|
+
* @param acrCredentials - ACR 憑證
|
|
180
|
+
* @param output - 輸出介面
|
|
181
|
+
* @returns 部署參數
|
|
182
|
+
*/
|
|
183
|
+
prepareDeploymentParameters(instanceName, acrCredentials, output) {
|
|
184
|
+
output?.section('[6/14] Preparing deployment parameters').flush();
|
|
185
|
+
output?.item('arrow', 'Generating security credentials...').flush();
|
|
186
|
+
const params = entities_1.DeploymentParameters.createWithGeneratedCredentials(instanceName, acrCredentials);
|
|
187
|
+
output?.success('Deployment parameters ready').newline().flush();
|
|
188
|
+
return params;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* 部署 Kubernetes 資源
|
|
192
|
+
* @param instanceName - 實例名稱
|
|
193
|
+
* @param params - 部署參數
|
|
194
|
+
* @param chartVersion - Chart 版本
|
|
195
|
+
* @param output - 輸出介面
|
|
196
|
+
*/
|
|
197
|
+
async deployK8sResources(instanceName, params, chartVersion, output) {
|
|
198
|
+
const fullName = instanceName.fullName;
|
|
199
|
+
const version = chartVersion.toString();
|
|
200
|
+
// [10/14] 建立全域設定 Secret
|
|
201
|
+
output?.section('[10/14] Configuring Kubernetes secrets').flush();
|
|
202
|
+
output?.item('arrow', 'Creating global config secret...').flush();
|
|
203
|
+
await this.deploymentPort.createGlobalConfigSecret(fullName, params);
|
|
204
|
+
output?.success('Secrets configured').newline().flush();
|
|
205
|
+
// [11/14] 部署 MSSQL
|
|
206
|
+
output?.section('[11/14] Deploying MSSQL').flush();
|
|
207
|
+
await this.deploymentPort.deployMssql(fullName, params, version, output);
|
|
208
|
+
output?.success('MSSQL deployed').newline().flush();
|
|
209
|
+
// [12/14] 部署基礎設施服務
|
|
210
|
+
output?.section('[12/14] Deploying Infrastructure Services').flush();
|
|
211
|
+
await this.deploymentPort.deployInfra(fullName, params, version, output);
|
|
212
|
+
output?.success('Infrastructure deployed').newline().flush();
|
|
213
|
+
// [13/14] 部署 Service Definition
|
|
214
|
+
output?.section('[13/14] Deploying Service Definition').flush();
|
|
215
|
+
await this.deploymentPort.deployService(fullName, params, version, output);
|
|
216
|
+
output?.success('Service deployed').newline().flush();
|
|
217
|
+
// [14/14] 部署 UofX App
|
|
218
|
+
output?.section('[14/14] Deploying UofX App').flush();
|
|
219
|
+
await this.deploymentPort.deployApp(fullName, params, version, output);
|
|
220
|
+
// 初始化 D-Bus session(防止 WSL 自動停止)
|
|
221
|
+
output?.item('arrow', 'Initializing D-Bus session...').flush();
|
|
222
|
+
await this.instanceManager.initDBusSession(instanceName, output);
|
|
223
|
+
// 等待所有 pods 就緒
|
|
224
|
+
output?.item('arrow', 'Waiting for all pods to be ready...').flush();
|
|
225
|
+
const podsReady = await this.instanceManager.waitForPodsReady(instanceName);
|
|
226
|
+
if (podsReady) {
|
|
227
|
+
output?.success('All pods are ready').flush();
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
output?.warning('Some pods may not be ready yet').flush();
|
|
231
|
+
}
|
|
232
|
+
// 執行後台健康檢查
|
|
233
|
+
await this.checkAdminHealthWithRetry(instanceName, output);
|
|
234
|
+
output?.success('App deployed').newline().flush();
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* 初始化系統
|
|
238
|
+
* @param instanceName - 實例名稱
|
|
239
|
+
* @param params - 部署參數(包含 ACR 憑證)
|
|
240
|
+
* @param environmentVersion - ubuntu-environment 版本
|
|
241
|
+
* @param output - 輸出介面
|
|
242
|
+
*/
|
|
243
|
+
async initializeSystem(instanceName, params, environmentVersion, output) {
|
|
244
|
+
output?.item('arrow', 'Executing environment setup script...').flush();
|
|
245
|
+
output?.item('bullet', `Using ubuntu-environment v${environmentVersion}`).flush();
|
|
246
|
+
try {
|
|
247
|
+
await this.instanceManager.initialize(instanceName, params, environmentVersion, output);
|
|
248
|
+
output?.success('System initialized').flush();
|
|
249
|
+
}
|
|
250
|
+
catch (error) {
|
|
251
|
+
output?.warning('Environment script execution completed with warnings').flush();
|
|
252
|
+
throw error;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* 確保沒有其他實例正在運行
|
|
257
|
+
* 安裝新實例前必須停止所有現有實例
|
|
258
|
+
* @param output - 輸出介面
|
|
259
|
+
* @throws AppError 若有運行中的實例
|
|
260
|
+
*/
|
|
261
|
+
async ensureNoRunningInstances(output) {
|
|
262
|
+
output?.section('[4/14] Checking for running instances').flush();
|
|
263
|
+
output?.item('arrow', 'Scanning running instances...').flush();
|
|
264
|
+
const runningInstances = await this.instanceManager.listRunningInstances();
|
|
265
|
+
if (runningInstances.length > 0) {
|
|
266
|
+
// 將全名轉換為顯示名稱(移除 uofx- 前綴)
|
|
267
|
+
const displayNames = runningInstances.map(name => name.replace('uofx-', ''));
|
|
268
|
+
const instanceList = displayNames
|
|
269
|
+
.map(name => ` - ${name}`)
|
|
270
|
+
.join('\n');
|
|
271
|
+
const stopCommand = displayNames.length === 1
|
|
272
|
+
? `uofx env stop --name ${displayNames[0]}`
|
|
273
|
+
: 'uofx env stop --name <instance-name>';
|
|
274
|
+
throw new app_error_1.AppError(`Cannot install: ${runningInstances.length} instance(s) currently running:\n${instanceList}`, {
|
|
275
|
+
exitCode: exit_codes_1.EXIT_CODES.BUSINESS_ERROR,
|
|
276
|
+
solution: `Stop all running instances before installing a new one.\nRun: ${stopCommand}`,
|
|
277
|
+
context: { runningInstances }
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
output?.success('No running instances detected').flush();
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* 清理未完成安裝的實體
|
|
284
|
+
* 用於安裝中斷時的清理
|
|
285
|
+
* @param instanceName - 實例名稱
|
|
286
|
+
* @param output - 輸出介面
|
|
287
|
+
*/
|
|
288
|
+
async cleanupInstance(instanceName, output) {
|
|
289
|
+
output?.item('arrow', `Removing incomplete instance: ${instanceName.toString()}`).flush();
|
|
290
|
+
try {
|
|
291
|
+
// 嘗試停止實體(如果正在運行)
|
|
292
|
+
const status = await this.instanceManager.getStatus(instanceName);
|
|
293
|
+
if (status.isRunning) {
|
|
294
|
+
output?.indent().item('arrow', 'Stopping instance...').outdent().flush();
|
|
295
|
+
await this.instanceManager.stop(instanceName, true);
|
|
296
|
+
output?.indent().success('Instance stopped').outdent().flush();
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
catch (error) {
|
|
300
|
+
output?.indent().warning(`Failed to stop instance: ${(0, error_formatter_util_1.formatErrorMessage)(error)}`).outdent().flush();
|
|
301
|
+
}
|
|
302
|
+
try {
|
|
303
|
+
// 刪除實體
|
|
304
|
+
output?.indent().item('arrow', 'Deleting instance...').outdent().flush();
|
|
305
|
+
await this.instanceManager.delete(instanceName);
|
|
306
|
+
output?.indent().success('Instance deleted').outdent().flush();
|
|
307
|
+
}
|
|
308
|
+
catch (error) {
|
|
309
|
+
output?.indent().warning(`Failed to delete instance: ${(0, error_formatter_util_1.formatErrorMessage)(error)}`).outdent().flush();
|
|
310
|
+
}
|
|
311
|
+
try {
|
|
312
|
+
// 刪除 metadata
|
|
313
|
+
output?.indent().item('arrow', 'Deleting metadata...').outdent().flush();
|
|
314
|
+
await this.instanceStorage.deleteInstance(instanceName);
|
|
315
|
+
output?.indent().success('Metadata deleted').outdent().flush();
|
|
316
|
+
}
|
|
317
|
+
catch (error) {
|
|
318
|
+
output?.indent().warning(`Failed to delete metadata: ${(0, error_formatter_util_1.formatErrorMessage)(error)}`).outdent().flush();
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* 檢查 WSL 是否已安裝
|
|
323
|
+
* @param output - 輸出介面
|
|
324
|
+
* @throws AppError 若 WSL 未安裝
|
|
325
|
+
*/
|
|
326
|
+
async checkWslInstalled(output) {
|
|
327
|
+
output?.section('[1/14] Checking WSL installation').flush();
|
|
328
|
+
output?.item('arrow', 'Verifying runtime environment...').flush();
|
|
329
|
+
const runtimeInfo = await this.runtimeEnvironment.getRuntimeInfo();
|
|
330
|
+
if (!runtimeInfo.isInstalled) {
|
|
331
|
+
throw new app_error_1.AppError(`${runtimeInfo.type} is not installed on this system`, {
|
|
332
|
+
exitCode: exit_codes_1.EXIT_CODES.ENVIRONMENT_ERROR,
|
|
333
|
+
solution: 'Please install WSL first. Run: uofx env setup',
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
output?.success(`${runtimeInfo.type} is installed (${runtimeInfo.version})`).flush();
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* 檢查記憶體可用性
|
|
340
|
+
* 綜合考量系統剩餘記憶體、WSL 限制、WSL 目前使用量
|
|
341
|
+
* @param output - 輸出介面
|
|
342
|
+
*/
|
|
343
|
+
async checkMemoryAvailability(output) {
|
|
344
|
+
output?.section('[2/14] Checking remaining memory').flush();
|
|
345
|
+
const memoryInfo = await this.runtimeEnvironment.getMemoryAvailability();
|
|
346
|
+
// 顯示詳細資訊
|
|
347
|
+
for (const detail of memoryInfo.details) {
|
|
348
|
+
const suffix = detail.suffix ? ` (${detail.suffix})` : '';
|
|
349
|
+
output?.item('bullet', `${detail.label}: ${detail.valueGB.toFixed(2)} GB${suffix}`).flush();
|
|
350
|
+
}
|
|
351
|
+
if (memoryInfo.availableGB < runtime_environment_port_1.UOFX_REQUIRED_MEMORY_GB) {
|
|
352
|
+
output?.newline().flush();
|
|
353
|
+
output?.warning(`Available memory (${memoryInfo.availableGB.toFixed(2)} GB) is below recommended ${runtime_environment_port_1.UOFX_REQUIRED_MEMORY_GB} GB`).flush();
|
|
354
|
+
output?.info('Insufficient memory may cause:').flush();
|
|
355
|
+
output?.item('bullet', 'Kubernetes pods failing to start').flush();
|
|
356
|
+
output?.item('bullet', 'Services becoming unresponsive or crashing').flush();
|
|
357
|
+
output?.newline().flush();
|
|
358
|
+
const shouldContinue = await this.userInteraction.confirm('Do you want to continue installation anyway?', false);
|
|
359
|
+
if (!shouldContinue) {
|
|
360
|
+
throw new app_error_1.AppError('Installation cancelled due to insufficient memory', {
|
|
361
|
+
exitCode: exit_codes_1.EXIT_CODES.BUSINESS_ERROR,
|
|
362
|
+
solution: 'Close other applications or increase memory available for the runtime environment'
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
else {
|
|
367
|
+
output?.success('Memory check passed').flush();
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* 執行後台健康檢查(含重試機制)
|
|
372
|
+
* 超時後顯示警告但不中斷安裝
|
|
373
|
+
* @param instanceName - 實例名稱
|
|
374
|
+
* @param output - 輸出介面
|
|
375
|
+
*/
|
|
376
|
+
async checkAdminHealthWithRetry(instanceName, output) {
|
|
377
|
+
output?.item('arrow', 'Checking admin interface health...').flush();
|
|
378
|
+
// 取得實例 IP 與 Admin URL
|
|
379
|
+
const ip = await this.instanceManager.getInstanceIP(instanceName);
|
|
380
|
+
if (!ip) {
|
|
381
|
+
output?.warning('Could not determine instance IP for health check').flush();
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
const connectionInfo = value_objects_1.ConnectionInfo.create(ip);
|
|
385
|
+
if (!connectionInfo.adminUrl) {
|
|
386
|
+
output?.warning('Could not determine admin URL for health check').flush();
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
const adminUrl = connectionInfo.adminUrl;
|
|
390
|
+
const startTime = Date.now();
|
|
391
|
+
const timeout = timeouts_1.TIMEOUTS.ADMIN_HEALTH_CHECK_TIMEOUT;
|
|
392
|
+
const retryInterval = timeouts_1.TIMEOUTS.HEALTH_CHECK_RETRY_INTERVAL;
|
|
393
|
+
while (Date.now() - startTime < timeout) {
|
|
394
|
+
const isHealthy = await this.httpClient.checkHealth(adminUrl);
|
|
395
|
+
if (isHealthy) {
|
|
396
|
+
output?.success(`Admin interface is healthy: ${adminUrl}`).flush();
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
// 等待後重試
|
|
400
|
+
await new Promise(resolve => setTimeout(resolve, retryInterval));
|
|
401
|
+
}
|
|
402
|
+
// 超時 - 顯示警告但不拋出錯誤
|
|
403
|
+
output
|
|
404
|
+
?.warning(`Admin interface health check timed out after ${timeout / 60000} minutes. ` +
|
|
405
|
+
`The interface may not be fully ready yet.`)
|
|
406
|
+
.flush();
|
|
407
|
+
output?.info(`You can manually check: ${adminUrl}`).flush();
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
exports.InstallInstanceUseCase = InstallInstanceUseCase;
|
|
411
|
+
exports.InstallInstanceUseCase = InstallInstanceUseCase = __decorate([
|
|
412
|
+
(0, tsyringe_1.injectable)(),
|
|
413
|
+
__param(0, (0, tsyringe_1.inject)(tokens_1.TOKENS.IInstanceManagerPort)),
|
|
414
|
+
__param(1, (0, tsyringe_1.inject)(tokens_1.TOKENS.IInstanceStoragePort)),
|
|
415
|
+
__param(2, (0, tsyringe_1.inject)(tokens_1.TOKENS.IDeploymentPort)),
|
|
416
|
+
__param(3, (0, tsyringe_1.inject)(tokens_1.TOKENS.IBaseImagePort)),
|
|
417
|
+
__param(4, (0, tsyringe_1.inject)(tokens_1.TOKENS.IAppConfigPort)),
|
|
418
|
+
__param(5, (0, tsyringe_1.inject)(tokens_1.TOKENS.IErrorHandlerPort)),
|
|
419
|
+
__param(6, (0, tsyringe_1.inject)(tokens_1.TOKENS.IRuntimeEnvironmentPort)),
|
|
420
|
+
__param(7, (0, tsyringe_1.inject)(tokens_1.TOKENS.IUserInteractionPort)),
|
|
421
|
+
__param(8, (0, tsyringe_1.inject)(tokens_1.TOKENS.Internal.IHttpClient)),
|
|
422
|
+
__metadata("design:paramtypes", [Object, Object, Object, Object, Object, Object, Object, Object, Object])
|
|
423
|
+
], InstallInstanceUseCase);
|
|
424
|
+
//# sourceMappingURL=install-instance.use-case.js.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.ListChartsUseCase = void 0;
|
|
16
|
+
const tsyringe_1 = require("tsyringe");
|
|
17
|
+
const tokens_1 = require("../../../di/tokens");
|
|
18
|
+
/**
|
|
19
|
+
* 列出可用 Chart 版本 Use Case
|
|
20
|
+
*
|
|
21
|
+
* 從 Helm Registry 取得可用的 UOFX Chart 版本列表
|
|
22
|
+
*/
|
|
23
|
+
let ListChartsUseCase = class ListChartsUseCase {
|
|
24
|
+
constructor(deploymentPort) {
|
|
25
|
+
this.deploymentPort = deploymentPort;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* 執行列出 Chart 版本
|
|
29
|
+
* @param request - 列出請求
|
|
30
|
+
* @returns Chart 版本陣列
|
|
31
|
+
*/
|
|
32
|
+
async execute(request) {
|
|
33
|
+
const { chartName = 'uofx' } = request;
|
|
34
|
+
return await this.deploymentPort.listChartVersions(chartName);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
exports.ListChartsUseCase = ListChartsUseCase;
|
|
38
|
+
exports.ListChartsUseCase = ListChartsUseCase = __decorate([
|
|
39
|
+
(0, tsyringe_1.injectable)(),
|
|
40
|
+
__param(0, (0, tsyringe_1.inject)(tokens_1.TOKENS.IDeploymentPort)),
|
|
41
|
+
__metadata("design:paramtypes", [Object])
|
|
42
|
+
], ListChartsUseCase);
|
|
43
|
+
//# sourceMappingURL=list-charts.use-case.js.map
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.ListInstancesUseCase = void 0;
|
|
16
|
+
const tsyringe_1 = require("tsyringe");
|
|
17
|
+
const tokens_1 = require("../../../di/tokens");
|
|
18
|
+
const instance_list_aggregator_entity_1 = require("../../../domain/entities/instance-list-aggregator.entity");
|
|
19
|
+
const instance_name_value_object_1 = require("../../../domain/value-objects/instance-name.value-object");
|
|
20
|
+
/**
|
|
21
|
+
* 列出實例 Use Case
|
|
22
|
+
*/
|
|
23
|
+
let ListInstancesUseCase = class ListInstancesUseCase {
|
|
24
|
+
constructor(instanceManager, instanceStorage) {
|
|
25
|
+
this.instanceManager = instanceManager;
|
|
26
|
+
this.instanceStorage = instanceStorage;
|
|
27
|
+
}
|
|
28
|
+
async execute() {
|
|
29
|
+
// 取得所有 UOFX 實例
|
|
30
|
+
const instanceInfos = await this.instanceManager.listUofx();
|
|
31
|
+
// 取得所有 metadata
|
|
32
|
+
const metadataList = await this.instanceStorage.listInstances();
|
|
33
|
+
// 取得運行中實例的 IP
|
|
34
|
+
const ipMap = new Map();
|
|
35
|
+
for (const info of instanceInfos) {
|
|
36
|
+
if (info.state === 'Running') {
|
|
37
|
+
const instanceName = instance_name_value_object_1.InstanceName.createFromFullName(info.name);
|
|
38
|
+
const ip = await this.instanceManager.getInstanceIP(instanceName);
|
|
39
|
+
ipMap.set(info.name, ip);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
ipMap.set(info.name, null);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
// 使用 Entity 聚合資訊並計算統計
|
|
46
|
+
const { instances, statistics } = instance_list_aggregator_entity_1.InstanceListAggregator.aggregateWithStatistics(instanceInfos, metadataList, ipMap);
|
|
47
|
+
return {
|
|
48
|
+
instances,
|
|
49
|
+
total: statistics.total,
|
|
50
|
+
runningCount: statistics.runningCount,
|
|
51
|
+
stoppedCount: statistics.stoppedCount,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
exports.ListInstancesUseCase = ListInstancesUseCase;
|
|
56
|
+
exports.ListInstancesUseCase = ListInstancesUseCase = __decorate([
|
|
57
|
+
(0, tsyringe_1.injectable)(),
|
|
58
|
+
__param(0, (0, tsyringe_1.inject)(tokens_1.TOKENS.IInstanceManagerPort)),
|
|
59
|
+
__param(1, (0, tsyringe_1.inject)(tokens_1.TOKENS.IInstanceStoragePort)),
|
|
60
|
+
__metadata("design:paramtypes", [Object, Object])
|
|
61
|
+
], ListInstancesUseCase);
|
|
62
|
+
//# sourceMappingURL=list-instances.use-case.js.map
|