underpost 2.8.885 → 2.81.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/.env.production +3 -0
- package/.github/workflows/ghpkg.ci.yml +1 -1
- package/.github/workflows/npmpkg.ci.yml +1 -1
- package/.github/workflows/publish.ci.yml +5 -5
- package/.github/workflows/pwa-microservices-template-page.cd.yml +1 -1
- package/.github/workflows/pwa-microservices-template-test.ci.yml +1 -1
- package/.vscode/zed.keymap.json +17 -0
- package/.vscode/zed.settings.json +20 -0
- package/CHANGELOG.md +145 -1
- package/Dockerfile +20 -3
- package/README.md +6 -6
- package/bin/build.js +18 -9
- package/bin/deploy.js +130 -195
- package/bin/zed.js +20 -0
- package/cli.md +13 -7
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +50 -50
- package/manifests/deployment/dd-test-development/proxy.yaml +4 -4
- package/manifests/lxd/underpost-setup.sh +5 -5
- package/package.json +3 -4
- package/{manifests/maas → scripts}/ssh-cluster-info.sh +1 -1
- package/scripts/ssl.sh +164 -0
- package/src/cli/baremetal.js +8 -8
- package/src/cli/cloud-init.js +1 -1
- package/src/cli/cluster.js +15 -4
- package/src/cli/cron.js +1 -1
- package/src/cli/db.js +2 -1
- package/src/cli/deploy.js +65 -14
- package/src/cli/fs.js +2 -2
- package/src/cli/image.js +19 -2
- package/src/cli/index.js +11 -4
- package/src/cli/monitor.js +34 -1
- package/src/cli/repository.js +42 -1
- package/src/cli/run.js +396 -86
- package/src/cli/script.js +32 -0
- package/src/cli/secrets.js +34 -0
- package/src/cli/test.js +42 -1
- package/src/client/components/core/Css.js +0 -8
- package/src/client/components/core/windowGetDimensions.js +229 -162
- package/src/index.js +2 -2
- package/src/mailer/MailerProvider.js +1 -0
- package/src/runtime/express/Dockerfile +41 -0
- package/src/runtime/express/Express.js +12 -4
- package/src/runtime/lampp/Dockerfile +1 -1
- package/src/server/backup.js +20 -0
- package/src/server/client-build-live.js +12 -10
- package/src/server/client-build.js +136 -91
- package/src/server/client-dev-server.js +16 -2
- package/src/server/client-icons.js +19 -0
- package/src/server/conf.js +495 -69
- package/src/server/dns.js +169 -46
- package/src/server/downloader.js +65 -24
- package/src/server/object-layer.js +260 -162
- package/src/server/peer.js +2 -8
- package/src/server/proxy.js +93 -76
- package/src/server/runtime.js +15 -16
- package/src/server/ssr.js +4 -4
- package/src/server/tls.js +251 -0
- package/src/server/valkey.js +11 -10
- package/src/ws/IoInterface.js +2 -1
- package/src/ws/IoServer.js +2 -1
- package/src/ws/core/core.ws.connection.js +1 -1
- package/src/ws/core/core.ws.emit.js +1 -1
- package/src/ws/core/core.ws.server.js +1 -1
- package/manifests/maas/lxd-preseed.yaml +0 -32
- package/src/server/ssl.js +0 -108
- /package/{manifests/maas → scripts}/device-scan.sh +0 -0
- /package/{manifests/maas → scripts}/gpu-diag.sh +0 -0
- /package/{manifests/maas → scripts}/maas-setup.sh +0 -0
- /package/{manifests/maas → scripts}/nat-iptables.sh +0 -0
- /package/{manifests/maas → scripts}/nvim.sh +0 -0
- /package/{manifests/maas → scripts}/snap-clean.sh +0 -0
package/src/cli/run.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @description The main entry point for the Underpost CLI applications.
|
|
3
|
+
* @module src/cli/run.js
|
|
4
|
+
* @namespace UnderpostRun
|
|
5
|
+
*/
|
|
6
|
+
|
|
1
7
|
import { daemonProcess, getTerminalPid, openTerminal, pbcopy, shellCd, shellExec } from '../server/process.js';
|
|
2
|
-
import
|
|
3
|
-
import { getNpmRootPath } from '../server/conf.js';
|
|
8
|
+
import { getNpmRootPath, isDeployRunnerContext } from '../server/conf.js';
|
|
4
9
|
import { actionInitLog, loggerFactory } from '../server/logger.js';
|
|
5
10
|
import UnderpostTest from './test.js';
|
|
6
11
|
import fs from 'fs-extra';
|
|
@@ -12,7 +17,33 @@ import os from 'os';
|
|
|
12
17
|
|
|
13
18
|
const logger = loggerFactory(import.meta);
|
|
14
19
|
|
|
20
|
+
/**
|
|
21
|
+
* @class UnderpostRun
|
|
22
|
+
* @description Manages the execution of various CLI commands and operations.
|
|
23
|
+
* This class provides a set of static methods to perform different tasks
|
|
24
|
+
* such as running tests, deploying applications, managing environment variables,
|
|
25
|
+
* and more. It also includes a default option configuration and a collection of
|
|
26
|
+
* runners for executing specific commands.
|
|
27
|
+
* @memberof UnderpostRun
|
|
28
|
+
*/
|
|
15
29
|
class UnderpostRun {
|
|
30
|
+
/**
|
|
31
|
+
* @static
|
|
32
|
+
* @description Default options for the UnderpostRun class.
|
|
33
|
+
* @type {Object}
|
|
34
|
+
* @property {boolean} dev - Whether to run in development mode.
|
|
35
|
+
* @property {string} podName - The name of the pod to run.
|
|
36
|
+
* @property {string} volumeHostPath - The host path for the volume.
|
|
37
|
+
* @property {string} volumeMountPath - The mount path for the volume.
|
|
38
|
+
* @property {string} imageName - The name of the image to run.
|
|
39
|
+
* @property {string} containerName - The name of the container to run.
|
|
40
|
+
* @property {string} namespace - The namespace to run in.
|
|
41
|
+
* @property {boolean} build - Whether to build the image.
|
|
42
|
+
* @property {number} replicas - The number of replicas to run.
|
|
43
|
+
* @property {boolean} k3s - Whether to run in k3s mode.
|
|
44
|
+
* @property {boolean} kubeadm - Whether to run in kubeadm mode.
|
|
45
|
+
* @memberof UnderpostRun
|
|
46
|
+
*/
|
|
16
47
|
static DEFAULT_OPTION = {
|
|
17
48
|
dev: false,
|
|
18
49
|
podName: '',
|
|
@@ -26,7 +57,20 @@ class UnderpostRun {
|
|
|
26
57
|
k3s: false,
|
|
27
58
|
kubeadm: false,
|
|
28
59
|
};
|
|
60
|
+
/**
|
|
61
|
+
* @static
|
|
62
|
+
* @description Collection of runners for executing specific commands.
|
|
63
|
+
* @type {Object}
|
|
64
|
+
* @memberof UnderpostRun
|
|
65
|
+
*/
|
|
29
66
|
static RUNNERS = {
|
|
67
|
+
/**
|
|
68
|
+
* @method spark-template
|
|
69
|
+
* @description Creates a new Spark template project using `sbt new` in `/home/dd/spark-template`, initializes a Git repository, and runs `replace_params.sh` and `build.sh`.
|
|
70
|
+
* @param {string} path - The input value, identifier, or path for the operation.
|
|
71
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
72
|
+
* @memberof UnderpostRun
|
|
73
|
+
*/
|
|
30
74
|
'spark-template': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
31
75
|
const dir = '/home/dd/spark-template';
|
|
32
76
|
shellExec(`sudo rm -rf ${dir}`);
|
|
@@ -47,12 +91,33 @@ class UnderpostRun {
|
|
|
47
91
|
|
|
48
92
|
shellCd('/home/dd/engine');
|
|
49
93
|
},
|
|
94
|
+
/**
|
|
95
|
+
* @method rmi
|
|
96
|
+
* @description Forces the removal of all local Podman images (`podman rmi $(podman images -qa) --force`).
|
|
97
|
+
* @param {string} path - The input value, identifier, or path for the operation.
|
|
98
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
99
|
+
* @memberof UnderpostRun
|
|
100
|
+
*/
|
|
50
101
|
rmi: (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
51
102
|
shellExec(`podman rmi $(podman images -qa) --force`);
|
|
52
103
|
},
|
|
104
|
+
/**
|
|
105
|
+
* @method kill
|
|
106
|
+
* @description Kills the process running on the specified port by finding its PID using `lsof -t -i:${path}`.
|
|
107
|
+
* @param {string} path - The input value, identifier, or path for the operation (used as the port number).
|
|
108
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
109
|
+
* @memberof UnderpostRun
|
|
110
|
+
*/
|
|
53
111
|
kill: (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
54
112
|
shellExec(`sudo kill -9 $(lsof -t -i:${path})`);
|
|
55
113
|
},
|
|
114
|
+
/**
|
|
115
|
+
* @method secret
|
|
116
|
+
* @description Creates an Underpost secret named 'underpost' from a file, defaulting to `/home/dd/engine/engine-private/conf/dd-cron/.env.production` if no path is provided.
|
|
117
|
+
* @param {string} path - The input value, identifier, or path for the operation (used as the optional path to the secret file).
|
|
118
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
119
|
+
* @memberof UnderpostRun
|
|
120
|
+
*/
|
|
56
121
|
secret: (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
57
122
|
shellExec(
|
|
58
123
|
`underpost secret underpost --create-from-file ${
|
|
@@ -60,31 +125,62 @@ class UnderpostRun {
|
|
|
60
125
|
}`,
|
|
61
126
|
);
|
|
62
127
|
},
|
|
128
|
+
/**
|
|
129
|
+
* @method underpost-config
|
|
130
|
+
* @description Calls `UnderpostDeploy.API.configMap` to create a Kubernetes ConfigMap, defaulting to the 'production' environment.
|
|
131
|
+
* @param {string} path - The input value, identifier, or path for the operation (used as the optional configuration name/environment).
|
|
132
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
133
|
+
* @memberof UnderpostRun
|
|
134
|
+
*/
|
|
63
135
|
'underpost-config': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
64
136
|
UnderpostDeploy.API.configMap(path ?? 'production');
|
|
65
137
|
},
|
|
138
|
+
/**
|
|
139
|
+
* @method gpu-env
|
|
140
|
+
* @description Sets up a dedicated GPU development environment cluster, resetting and then setting up the cluster with `--dedicated-gpu` and monitoring the pods.
|
|
141
|
+
* @param {string} path - The input value, identifier, or path for the operation.
|
|
142
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
143
|
+
* @memberof UnderpostRun
|
|
144
|
+
*/
|
|
66
145
|
'gpu-env': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
67
146
|
shellExec(
|
|
68
147
|
`node bin cluster --dev --reset && node bin cluster --dev --dedicated-gpu --kubeadm && kubectl get pods --all-namespaces -o wide -w`,
|
|
69
148
|
);
|
|
70
149
|
},
|
|
150
|
+
/**
|
|
151
|
+
* @method tf-gpu-test
|
|
152
|
+
* @description Deletes existing `tf-gpu-test-script` ConfigMap and `tf-gpu-test-pod`, and applies the test manifest from `manifests/deployment/tensorflow/tf-gpu-test.yaml`.
|
|
153
|
+
* @param {string} path - The input value, identifier, or path for the operation.
|
|
154
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
155
|
+
* @memberof UnderpostRun
|
|
156
|
+
*/
|
|
71
157
|
'tf-gpu-test': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
72
158
|
const { underpostRoot } = options;
|
|
73
159
|
shellExec(`kubectl delete configmap tf-gpu-test-script`);
|
|
74
160
|
shellExec(`kubectl delete pod tf-gpu-test-pod`);
|
|
75
161
|
shellExec(`kubectl apply -f ${underpostRoot}/manifests/deployment/tensorflow/tf-gpu-test.yaml`);
|
|
76
162
|
},
|
|
163
|
+
/**
|
|
164
|
+
* @method dev-cluster
|
|
165
|
+
* @description Resets and deploys a full development cluster including MongoDB, Valkey, exposes services, and updates `/etc/hosts` for local access.
|
|
166
|
+
* @param {string} path - The input value, identifier, or path for the operation.
|
|
167
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
168
|
+
* @memberof UnderpostRun
|
|
169
|
+
*/
|
|
77
170
|
'dev-cluster': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
78
171
|
const baseCommand = options.dev ? 'node bin' : 'underpost';
|
|
79
|
-
shellExec(`${baseCommand} cluster${options.dev ? ' --dev' : ''} --reset`);
|
|
80
|
-
shellExec(`${baseCommand} cluster${options.dev ? ' --dev' : ''}`);
|
|
81
172
|
const mongoHosts = ['mongodb-0.mongodb-service'];
|
|
82
|
-
|
|
83
|
-
`${baseCommand} cluster${options.dev ? ' --dev' : ''} --
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
173
|
+
if (path !== 'expose') {
|
|
174
|
+
shellExec(`${baseCommand} cluster${options.dev ? ' --dev' : ''} --reset`);
|
|
175
|
+
shellExec(`${baseCommand} cluster${options.dev ? ' --dev' : ''}`);
|
|
176
|
+
|
|
177
|
+
shellExec(
|
|
178
|
+
`${baseCommand} cluster${options.dev ? ' --dev' : ''} --mongodb --mongo-db-host ${mongoHosts.join(
|
|
179
|
+
',',
|
|
180
|
+
)} --pull-image`,
|
|
181
|
+
);
|
|
182
|
+
shellExec(`${baseCommand} cluster${options.dev ? ' --dev' : ''} --valkey --pull-image`);
|
|
183
|
+
}
|
|
88
184
|
shellExec(`${baseCommand} deploy --expose mongo`, { async: true });
|
|
89
185
|
shellExec(`${baseCommand} deploy --expose valkey`, { async: true });
|
|
90
186
|
{
|
|
@@ -92,23 +188,91 @@ class UnderpostRun {
|
|
|
92
188
|
logger.info(hostListenResult.renderHosts);
|
|
93
189
|
}
|
|
94
190
|
},
|
|
191
|
+
/**
|
|
192
|
+
* @method ssh-cluster-info
|
|
193
|
+
* @description Executes the `ssh-cluster-info.sh` script to display cluster connection information.
|
|
194
|
+
* @param {string} path - The input value, identifier, or path for the operation.
|
|
195
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
196
|
+
* @memberof UnderpostRun
|
|
197
|
+
*/
|
|
95
198
|
'ssh-cluster-info': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
96
199
|
const { underpostRoot } = options;
|
|
97
|
-
shellExec(`chmod +x ${underpostRoot}/
|
|
98
|
-
shellExec(`${underpostRoot}/
|
|
200
|
+
shellExec(`chmod +x ${underpostRoot}/scripts/ssh-cluster-info.sh`);
|
|
201
|
+
shellExec(`${underpostRoot}/scripts/ssh-cluster-info.sh`);
|
|
99
202
|
},
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* @method dev-hosts-expose
|
|
206
|
+
* @description Deploys a specified service in development mode with `/etc/hosts` modification for local access.
|
|
207
|
+
* @param {string} path - The input value, identifier, or path for the operation (used as the deployment ID to deploy).
|
|
208
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
209
|
+
* @memberof UnderpostRun
|
|
210
|
+
*/
|
|
211
|
+
'dev-hosts-expose': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
212
|
+
shellExec(
|
|
213
|
+
`node bin deploy ${path} development --disable-update-deployment --disable-update-proxy --kubeadm --etc-hosts`,
|
|
214
|
+
);
|
|
215
|
+
},
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* @method dev-hosts-restore
|
|
219
|
+
* @description Restores the `/etc/hosts` file to its original state after modifications made during development deployments.
|
|
220
|
+
* @param {string} path - The input value, identifier, or path for the operation.
|
|
221
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
222
|
+
* @memberof UnderpostRun
|
|
223
|
+
*/
|
|
224
|
+
'dev-hosts-restore': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
225
|
+
shellExec(`node bin deploy --restore-hosts`);
|
|
226
|
+
},
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* @method cyberia-ide
|
|
230
|
+
* @description Starts the development environment (IDE) for both `cyberia-server` and `cyberia-client` repositories.
|
|
231
|
+
* @param {string} path - The input value, identifier, or path for the operation.
|
|
232
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
233
|
+
* @memberof UnderpostRun
|
|
234
|
+
*/
|
|
100
235
|
'cyberia-ide': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
101
236
|
const baseCommand = options.dev ? 'node bin' : 'underpost';
|
|
102
237
|
shellExec(`${baseCommand} run ide /home/dd/cyberia-server`);
|
|
103
238
|
shellExec(`${baseCommand} run ide /home/dd/cyberia-client`);
|
|
104
239
|
},
|
|
240
|
+
/**
|
|
241
|
+
* @method engine-ide
|
|
242
|
+
* @description Starts the development environment (IDE) for the `engine` and `engine-private` repositories.
|
|
243
|
+
* @param {string} path - The input value, identifier, or path for the operation.
|
|
244
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
245
|
+
* @memberof UnderpostRun
|
|
246
|
+
*/
|
|
105
247
|
'engine-ide': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
106
248
|
const baseCommand = options.dev ? 'node bin' : 'underpost';
|
|
107
249
|
shellExec(`${baseCommand} run ide /home/dd/engine`);
|
|
108
250
|
shellExec(`${baseCommand} run ide /home/dd/engine/engine-private`);
|
|
109
251
|
},
|
|
252
|
+
/**
|
|
253
|
+
* @method cluster-build
|
|
254
|
+
* @description Build configuration for cluster deployment.
|
|
255
|
+
* @param {string} path - The input value, identifier, or path for the operation.
|
|
256
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
257
|
+
* @memberof UnderpostRun
|
|
258
|
+
*/
|
|
259
|
+
'cluster-build': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
260
|
+
shellExec(`node bin run clean`);
|
|
261
|
+
shellExec(`node bin run --dev sync-replica template-deploy`);
|
|
262
|
+
shellExec(`node bin run sync-replica template-deploy`);
|
|
263
|
+
shellExec(`node bin env clean`);
|
|
264
|
+
shellExec(`git add . && underpost cmt . build cluster-build`);
|
|
265
|
+
shellExec(`cd engine-private && git add . && underpost cmt . build cluster-build`);
|
|
266
|
+
},
|
|
267
|
+
/**
|
|
268
|
+
* @method template-deploy
|
|
269
|
+
* @description Cleans up, pushes `engine-private` and `engine` repositories with a commit tag `ci package-pwa-microservices-template`.
|
|
270
|
+
* @param {string} path - The input value, identifier, or path for the operation.
|
|
271
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
272
|
+
* @memberof UnderpostRun
|
|
273
|
+
*/
|
|
110
274
|
'template-deploy': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
111
|
-
const baseCommand = options.dev
|
|
275
|
+
const baseCommand = options.dev ? 'node bin' : 'underpost';
|
|
112
276
|
shellExec(`${baseCommand} run clean`);
|
|
113
277
|
shellExec(`${baseCommand} push ./engine-private ${process.env.GITHUB_USERNAME}/engine-private`);
|
|
114
278
|
shellCd('/home/dd/engine');
|
|
@@ -116,16 +280,37 @@ class UnderpostRun {
|
|
|
116
280
|
shellExec(`${baseCommand} cmt . --empty ci package-pwa-microservices-template`);
|
|
117
281
|
shellExec(`${baseCommand} push . ${process.env.GITHUB_USERNAME}/engine`);
|
|
118
282
|
},
|
|
283
|
+
/**
|
|
284
|
+
* @method clean
|
|
285
|
+
* @description Changes directory to the provided path (defaulting to `/home/dd/engine`) and runs `node bin/deploy clean-core-repo`.
|
|
286
|
+
* @param {string} path - The input value, identifier, or path for the operation (used as the optional directory path).
|
|
287
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
288
|
+
* @memberof UnderpostRun
|
|
289
|
+
*/
|
|
119
290
|
clean: (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
120
291
|
shellCd(path ?? `/home/dd/engine`);
|
|
121
292
|
shellExec(`node bin/deploy clean-core-repo`);
|
|
122
293
|
},
|
|
294
|
+
/**
|
|
295
|
+
* @method pull
|
|
296
|
+
* @description Cleans the core repository and pulls the latest content for `engine` and `engine-private` repositories from the remote.
|
|
297
|
+
* @param {string} path - The input value, identifier, or path for the operation.
|
|
298
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
299
|
+
* @memberof UnderpostRun
|
|
300
|
+
*/
|
|
123
301
|
pull: (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
124
302
|
shellCd(`/home/dd/engine`);
|
|
125
303
|
shellExec(`node bin/deploy clean-core-repo`);
|
|
126
304
|
shellExec(`underpost pull . ${process.env.GITHUB_USERNAME}/engine`);
|
|
127
305
|
shellExec(`underpost pull ./engine-private ${process.env.GITHUB_USERNAME}/engine-private`);
|
|
128
306
|
},
|
|
307
|
+
/**
|
|
308
|
+
* @method release-deploy
|
|
309
|
+
* @description Executes deployment (`underpost run deploy`) for all deployment IDs listed in `./engine-private/deploy/dd.router`.
|
|
310
|
+
* @param {string} path - The input value, identifier, or path for the operation.
|
|
311
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
312
|
+
* @memberof UnderpostRun
|
|
313
|
+
*/
|
|
129
314
|
'release-deploy': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
130
315
|
actionInitLog();
|
|
131
316
|
shellExec(`underpost --version`);
|
|
@@ -135,51 +320,98 @@ class UnderpostRun {
|
|
|
135
320
|
shellExec(`underpost run deploy ${deployId}`, { async: true });
|
|
136
321
|
}
|
|
137
322
|
},
|
|
323
|
+
/**
|
|
324
|
+
* @method ssh-deploy
|
|
325
|
+
* @description Performs a Git reset, commits with a message `cd ssh-${path}`, and pushes the `engine` repository, likely triggering an SSH-based CD pipeline.
|
|
326
|
+
* @param {string} path - The input value, identifier, or path for the operation (used as the deployment identifier for the commit message).
|
|
327
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
328
|
+
* @memberof UnderpostRun
|
|
329
|
+
*/
|
|
138
330
|
'ssh-deploy': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
139
331
|
actionInitLog();
|
|
140
|
-
const baseCommand = options.dev
|
|
332
|
+
const baseCommand = options.dev ? 'node bin' : 'underpost';
|
|
141
333
|
shellCd('/home/dd/engine');
|
|
142
334
|
shellExec(`git reset`);
|
|
143
335
|
shellExec(`${baseCommand} cmt . --empty cd ssh-${path}`);
|
|
144
336
|
shellExec(`${baseCommand} push . ${process.env.GITHUB_USERNAME}/engine`);
|
|
145
337
|
},
|
|
338
|
+
/**
|
|
339
|
+
* @method ide
|
|
340
|
+
* @description Opens a Visual Studio Code (VS Code) session for the specified path using `node ${underpostRoot}/bin/zed ${path}`.
|
|
341
|
+
* @param {string} path - The input value, identifier, or path for the operation (used as the path to the directory to open in the IDE).
|
|
342
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
343
|
+
* @memberof UnderpostRun
|
|
344
|
+
*/
|
|
146
345
|
ide: (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
147
346
|
const { underpostRoot } = options;
|
|
148
|
-
shellExec(`node ${underpostRoot}/bin/
|
|
149
|
-
},
|
|
150
|
-
'dev-client': (_path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
151
|
-
let [deployId, hostpath, subConf, lite] = _path.split(',');
|
|
152
|
-
let [host, path] = hostpath.split('/');
|
|
153
|
-
if (!path) path = '/';
|
|
154
|
-
shellExec(`npm run dev-client ${deployId} ${host} ${path} ${subConf} static${lite === 'l' ? ' l' : ''}`);
|
|
347
|
+
shellExec(`node ${underpostRoot}/bin/zed ${path}`);
|
|
155
348
|
},
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
349
|
+
/**
|
|
350
|
+
* @method sync
|
|
351
|
+
* @description Cleans up, and then runs a deployment synchronization command (`underpost deploy --kubeadm --build-manifest --sync...`) using parameters parsed from `path` (deployId, replicas, versions, image, node).
|
|
352
|
+
* @param {string} path - The input value, identifier, or path for the operation (used as a comma-separated string containing deploy parameters).
|
|
353
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
354
|
+
* @memberof UnderpostRun
|
|
355
|
+
*/
|
|
356
|
+
sync: async (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
357
|
+
// Dev usage: node bin run --dev --build sync dd-default
|
|
161
358
|
const env = options.dev ? 'development' : 'production';
|
|
162
|
-
const baseCommand = options.dev
|
|
163
|
-
|
|
164
|
-
|
|
359
|
+
const baseCommand = options.dev ? 'node bin' : 'underpost';
|
|
360
|
+
const defaultPath = [
|
|
361
|
+
'dd-default',
|
|
362
|
+
1,
|
|
363
|
+
``,
|
|
364
|
+
``,
|
|
365
|
+
options.dev || !isDeployRunnerContext(path, options) ? 'kind-control-plane' : os.hostname(),
|
|
366
|
+
];
|
|
165
367
|
let [deployId, replicas, versions, image, node] = path ? path.split(',') : defaultPath;
|
|
166
|
-
deployId = deployId
|
|
167
|
-
replicas = replicas
|
|
168
|
-
versions = versions
|
|
169
|
-
image = image
|
|
170
|
-
node = node
|
|
368
|
+
deployId = deployId ? deployId : defaultPath[0];
|
|
369
|
+
replicas = replicas ? replicas : defaultPath[1];
|
|
370
|
+
versions = versions ? versions.replaceAll('+', ',') : defaultPath[2];
|
|
371
|
+
image = image ? image : defaultPath[3];
|
|
372
|
+
node = node ? node : defaultPath[4];
|
|
373
|
+
|
|
374
|
+
if (isDeployRunnerContext(path, options)) {
|
|
375
|
+
const { validVersion } = UnderpostRepository.API.privateConfUpdate(deployId);
|
|
376
|
+
if (!validVersion) throw new Error('Version mismatch');
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
const currentTraffic = isDeployRunnerContext(path, options)
|
|
380
|
+
? UnderpostDeploy.API.getCurrentTraffic(deployId)
|
|
381
|
+
: '';
|
|
382
|
+
let targetTraffic = currentTraffic ? (currentTraffic === 'blue' ? 'green' : 'blue') : '';
|
|
383
|
+
if (targetTraffic) versions = targetTraffic;
|
|
384
|
+
|
|
171
385
|
shellExec(
|
|
172
386
|
`${baseCommand} deploy --kubeadm --build-manifest --sync --info-router --replicas ${
|
|
173
387
|
replicas ?? 1
|
|
174
|
-
} --node ${node}${image ? ` --image ${image}` : ''}${
|
|
175
|
-
versions ? ` --versions ${versions.replaceAll('+', ',')}` : ''
|
|
176
|
-
} dd ${env}`,
|
|
388
|
+
} --node ${node}${image ? ` --image ${image}` : ''}${versions ? ` --versions ${versions}` : ''} dd ${env}`,
|
|
177
389
|
);
|
|
178
|
-
|
|
390
|
+
|
|
391
|
+
if (isDeployRunnerContext(path, options)) {
|
|
392
|
+
shellExec(`${baseCommand} deploy --kubeadm --disable-update-proxy ${deployId} ${env} --versions ${versions}`);
|
|
393
|
+
if (!targetTraffic) targetTraffic = UnderpostDeploy.API.getCurrentTraffic(deployId);
|
|
394
|
+
await UnderpostDeploy.API.monitorReadyRunner(deployId, env, targetTraffic);
|
|
395
|
+
UnderpostDeploy.API.switchTraffic(deployId, env, targetTraffic);
|
|
396
|
+
} else logger.info('current traffic', UnderpostDeploy.API.getCurrentTraffic(deployId));
|
|
179
397
|
},
|
|
398
|
+
/**
|
|
399
|
+
* @method ls-deployments
|
|
400
|
+
* @description Retrieves and logs a table of Kubernetes deployments using `UnderpostDeploy.API.get`.
|
|
401
|
+
* @param {string} path - The input value, identifier, or path for the operation (used as an optional deployment name filter).
|
|
402
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
403
|
+
* @memberof UnderpostRun
|
|
404
|
+
*/
|
|
180
405
|
'ls-deployments': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
181
406
|
console.table(await UnderpostDeploy.API.get(path, 'deployments'));
|
|
182
407
|
},
|
|
408
|
+
/**
|
|
409
|
+
* @method monitor
|
|
410
|
+
* @description Monitors a specific pod (identified by `path`) for the existence of a file (`/await`), and performs conditional actions (like file copying and opening Firefox) when the file is removed.
|
|
411
|
+
* @param {string} path - The input value, identifier, or path for the operation (used as the name of the pod to monitor).
|
|
412
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
413
|
+
* @memberof UnderpostRun
|
|
414
|
+
*/
|
|
183
415
|
monitor: (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
184
416
|
const pid = getTerminalPid();
|
|
185
417
|
logger.info('monitor pid', pid);
|
|
@@ -253,6 +485,13 @@ class UnderpostRun {
|
|
|
253
485
|
};
|
|
254
486
|
_monitor();
|
|
255
487
|
},
|
|
488
|
+
/**
|
|
489
|
+
* @method db-client
|
|
490
|
+
* @description Deploys and exposes the Adminer database client application (using `adminer:4.7.6-standalone` image) on the cluster.
|
|
491
|
+
* @param {string} path - The input value, identifier, or path for the operation.
|
|
492
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
493
|
+
* @memberof UnderpostRun
|
|
494
|
+
*/
|
|
256
495
|
'db-client': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
257
496
|
const { underpostRoot } = options;
|
|
258
497
|
|
|
@@ -274,6 +513,13 @@ class UnderpostRun {
|
|
|
274
513
|
shellExec(`underpost deploy --expose adminer`);
|
|
275
514
|
}
|
|
276
515
|
},
|
|
516
|
+
/**
|
|
517
|
+
* @method promote
|
|
518
|
+
* @description Switches traffic between blue/green deployments for a specified deployment ID(s) (uses `dd.router` for 'dd', or a specific ID).
|
|
519
|
+
* @param {string} path - The input value, identifier, or path for the operation (used as a comma-separated string: `deployId,env,replicas`).
|
|
520
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
521
|
+
* @memberof UnderpostRun
|
|
522
|
+
*/
|
|
277
523
|
promote: async (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
278
524
|
let [inputDeployId, inputEnv, inputReplicas] = path.split(',');
|
|
279
525
|
if (!inputEnv) inputEnv = 'production';
|
|
@@ -290,7 +536,13 @@ class UnderpostRun {
|
|
|
290
536
|
UnderpostDeploy.API.switchTraffic(inputDeployId, inputEnv, targetTraffic, inputReplicas);
|
|
291
537
|
}
|
|
292
538
|
},
|
|
293
|
-
|
|
539
|
+
/**
|
|
540
|
+
* @method metrics
|
|
541
|
+
* @description Deploys Prometheus and Grafana for metrics monitoring, targeting the hosts defined in the deployment configuration files.
|
|
542
|
+
* @param {string} path - The input value, identifier, or path for the operation.
|
|
543
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
544
|
+
* @memberof UnderpostRun
|
|
545
|
+
*/
|
|
294
546
|
metrics: async (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
295
547
|
const deployList = fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8').split(',');
|
|
296
548
|
let hosts = [];
|
|
@@ -301,78 +553,119 @@ class UnderpostRun {
|
|
|
301
553
|
shellExec(`node bin cluster --prom ${hosts.join(',')}`);
|
|
302
554
|
shellExec(`node bin cluster --grafana`);
|
|
303
555
|
},
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
556
|
+
/**
|
|
557
|
+
* @method cluster
|
|
558
|
+
* @description Deploys a full production/development ready Kubernetes cluster environment including MongoDB, MariaDB, Valkey, Contour (Ingress), and Cert-Manager, and deploys all services.
|
|
559
|
+
* @param {string} path - The input value, identifier, or path for the operation.
|
|
560
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
561
|
+
* @memberof UnderpostRun
|
|
562
|
+
*/
|
|
563
|
+
cluster: async (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
|
|
564
|
+
const env = options.dev ? 'development' : 'production';
|
|
565
|
+
const baseCommand = options.dev ? 'node bin' : 'underpost';
|
|
566
|
+
const baseClusterCommand = options.dev ? ' --dev' : '';
|
|
308
567
|
shellCd(`/home/dd/engine`);
|
|
309
|
-
shellExec(
|
|
310
|
-
await timer(5000);
|
|
311
|
-
shellExec(`underpost cluster --kubeadm`);
|
|
568
|
+
shellExec(`${baseCommand} cluster${baseClusterCommand} --reset`);
|
|
312
569
|
await timer(5000);
|
|
313
|
-
shellExec(
|
|
570
|
+
shellExec(`${baseCommand} cluster${baseClusterCommand} --kubeadm`);
|
|
314
571
|
await timer(5000);
|
|
315
|
-
|
|
572
|
+
let [runtimeImage, deployList] = path.split(',')
|
|
573
|
+
? path.split(',')
|
|
574
|
+
: ['lampp', fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8').replaceAll(',', '+')];
|
|
575
|
+
shellExec(
|
|
576
|
+
`${baseCommand} dockerfile-pull-base-images${baseClusterCommand}${
|
|
577
|
+
runtimeImage ? ` --path /home/dd/engine/src/runtime/${runtimeImage}` : ''
|
|
578
|
+
} --kubeadm-load`,
|
|
579
|
+
);
|
|
580
|
+
if (!deployList) {
|
|
581
|
+
deployList = [];
|
|
582
|
+
logger.warn('No deploy list provided');
|
|
583
|
+
} else deployList = deployList.split('+');
|
|
316
584
|
await timer(5000);
|
|
317
|
-
shellExec(
|
|
585
|
+
shellExec(`${baseCommand} cluster${baseClusterCommand} --kubeadm --pull-image --mongodb`);
|
|
586
|
+
if (runtimeImage === 'lampp') {
|
|
587
|
+
await timer(5000);
|
|
588
|
+
shellExec(`${baseCommand} cluster${baseClusterCommand} --kubeadm --pull-image --mariadb`);
|
|
589
|
+
}
|
|
318
590
|
await timer(5000);
|
|
319
591
|
for (const deployId of deployList) {
|
|
320
|
-
shellExec(
|
|
592
|
+
shellExec(`${baseCommand} db ${deployId} --import --git`);
|
|
321
593
|
}
|
|
322
594
|
await timer(5000);
|
|
323
|
-
shellExec(
|
|
595
|
+
shellExec(`${baseCommand} cluster${baseClusterCommand} --kubeadm --pull-image --valkey`);
|
|
324
596
|
await timer(5000);
|
|
325
|
-
shellExec(
|
|
326
|
-
|
|
327
|
-
|
|
597
|
+
shellExec(`${baseCommand} cluster${baseClusterCommand} --kubeadm --contour`);
|
|
598
|
+
if (env === 'production') {
|
|
599
|
+
await timer(5000);
|
|
600
|
+
shellExec(`${baseCommand} cluster${baseClusterCommand} --kubeadm --cert-manager`);
|
|
601
|
+
}
|
|
328
602
|
for (const deployId of deployList) {
|
|
329
|
-
shellExec(
|
|
603
|
+
shellExec(
|
|
604
|
+
`${baseCommand} deploy ${deployId} ${env} --kubeadm${env === 'production' ? ' --cert' : ''}${
|
|
605
|
+
env === 'development' ? ' --etc-hosts' : ''
|
|
606
|
+
}`,
|
|
607
|
+
);
|
|
330
608
|
}
|
|
331
609
|
},
|
|
610
|
+
/**
|
|
611
|
+
* @method deploy
|
|
612
|
+
* @description Deploys a specified service (identified by `path`) using blue/green strategy, monitors its status, and switches traffic upon readiness.
|
|
613
|
+
* @param {string} path - The input value, identifier, or path for the operation (used as the deployment ID to deploy).
|
|
614
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
615
|
+
* @memberof UnderpostRun
|
|
616
|
+
*/
|
|
332
617
|
deploy: async (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
333
618
|
const deployId = path;
|
|
334
|
-
const { validVersion
|
|
619
|
+
const { validVersion } = UnderpostRepository.API.privateConfUpdate(deployId);
|
|
335
620
|
if (!validVersion) throw new Error('Version mismatch');
|
|
336
621
|
const currentTraffic = UnderpostDeploy.API.getCurrentTraffic(deployId);
|
|
337
622
|
const targetTraffic = currentTraffic === 'blue' ? 'green' : 'blue';
|
|
338
623
|
const env = 'production';
|
|
339
624
|
const ignorePods = UnderpostDeploy.API.get(`${deployId}-${env}-${targetTraffic}`).map((p) => p.NAME);
|
|
340
625
|
|
|
341
|
-
|
|
342
|
-
// deployId, replicas, versions, image, node
|
|
343
|
-
shellExec(
|
|
344
|
-
`node bin run sync ${deployId},${options.replicas ?? 1},${targetTraffic},${
|
|
345
|
-
options.imageName ?? `localhost/rockylinux9-underpost:${deployVersion}`
|
|
346
|
-
},${os.hostname()}`,
|
|
347
|
-
);
|
|
348
|
-
} else shellExec(`sudo kubectl rollout restart deployment/${deployId}-${env}-${targetTraffic}`);
|
|
349
|
-
|
|
350
|
-
let checkStatusIteration = 0;
|
|
351
|
-
const checkStatusIterationMsDelay = 1000;
|
|
352
|
-
const iteratorTag = `[${deployId}-${env}-${targetTraffic}]`;
|
|
353
|
-
logger.info('Deployment init', { deployId, env, targetTraffic, checkStatusIterationMsDelay });
|
|
354
|
-
const minReadyOk = 3;
|
|
355
|
-
let readyOk = 0;
|
|
356
|
-
|
|
357
|
-
while (readyOk < minReadyOk) {
|
|
358
|
-
const ready = UnderpostDeploy.API.checkDeploymentReadyStatus(deployId, env, targetTraffic, ignorePods).ready;
|
|
359
|
-
if (ready === true) {
|
|
360
|
-
readyOk++;
|
|
361
|
-
logger.info(`${iteratorTag} | Deployment ready. Verification number: ${readyOk}`);
|
|
362
|
-
}
|
|
363
|
-
await timer(checkStatusIterationMsDelay);
|
|
364
|
-
checkStatusIteration++;
|
|
365
|
-
logger.info(
|
|
366
|
-
`${iteratorTag} | Deployment in progress... | Delay number check iterations: ${checkStatusIteration}`,
|
|
367
|
-
);
|
|
368
|
-
}
|
|
626
|
+
shellExec(`sudo kubectl rollout restart deployment/${deployId}-${env}-${targetTraffic}`);
|
|
369
627
|
|
|
370
|
-
|
|
628
|
+
await UnderpostDeploy.API.monitorReadyRunner(deployId, env, targetTraffic, ignorePods);
|
|
371
629
|
|
|
372
630
|
UnderpostDeploy.API.switchTraffic(deployId, env, targetTraffic);
|
|
631
|
+
},
|
|
373
632
|
|
|
374
|
-
|
|
633
|
+
/**
|
|
634
|
+
* @method sync-replica
|
|
635
|
+
* @description Syncs a replica for the dd.router
|
|
636
|
+
* @param {string} path - The input value, identifier, or path for the operation.
|
|
637
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
638
|
+
* @memberof UnderpostRun
|
|
639
|
+
*/
|
|
640
|
+
'sync-replica': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
641
|
+
const env = options.dev ? 'development' : 'production';
|
|
642
|
+
const baseCommand = options.dev ? 'node bin' : 'underpost';
|
|
643
|
+
|
|
644
|
+
for (let deployId of fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8').split(',')) {
|
|
645
|
+
deployId = deployId.trim();
|
|
646
|
+
const _path = '/single-replica';
|
|
647
|
+
const confServer = JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'));
|
|
648
|
+
shellExec(`${baseCommand} env ${deployId} ${env}`);
|
|
649
|
+
for (const host of Object.keys(confServer)) {
|
|
650
|
+
if (!(_path in confServer[host])) continue;
|
|
651
|
+
shellExec(`node bin/deploy build-single-replica ${deployId} ${host} ${_path}`);
|
|
652
|
+
shellExec(`node bin/deploy build-full-client ${deployId}`);
|
|
653
|
+
const node = options.dev || !isDeployRunnerContext(path, options) ? 'kind-control-plane' : os.hostname();
|
|
654
|
+
// deployId, replicas, versions, image, node
|
|
655
|
+
let defaultPath = [deployId, 1, ``, ``, node];
|
|
656
|
+
shellExec(`${baseCommand} run${options.dev === true ? ' --dev' : ''} --build sync ${defaultPath}`);
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
if (isDeployRunnerContext(path, options)) shellExec(`${baseCommand} run promote ${path} production`);
|
|
375
660
|
},
|
|
661
|
+
|
|
662
|
+
/**
|
|
663
|
+
* @method tf-vae-test
|
|
664
|
+
* @description Creates and runs a job pod (`tf-vae-test`) that installs TensorFlow dependencies, clones the TensorFlow docs, and runs the CVAE tutorial script, with a terminal monitor attached.
|
|
665
|
+
* @param {string} path - The input value, identifier, or path for the operation.
|
|
666
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
667
|
+
* @memberof UnderpostRun
|
|
668
|
+
*/
|
|
376
669
|
'tf-vae-test': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
377
670
|
const { underpostRoot } = options;
|
|
378
671
|
const podName = 'tf-vae-test';
|
|
@@ -406,6 +699,13 @@ class UnderpostRun {
|
|
|
406
699
|
],
|
|
407
700
|
});
|
|
408
701
|
},
|
|
702
|
+
/**
|
|
703
|
+
* @method deploy-job
|
|
704
|
+
* @description Creates and applies a custom Kubernetes Pod manifest (Job) for running arbitrary commands inside a container image (defaulting to a TensorFlow/NVIDIA image).
|
|
705
|
+
* @param {string} path - The input value, identifier, or path for the operation (used as the optional script path or job argument).
|
|
706
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
707
|
+
* @memberof UnderpostRun
|
|
708
|
+
*/
|
|
409
709
|
'deploy-job': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
410
710
|
const podName = options.podName || 'deploy-job';
|
|
411
711
|
const volumeName = `${podName}-volume`;
|
|
@@ -485,7 +785,17 @@ EOF`;
|
|
|
485
785
|
}
|
|
486
786
|
},
|
|
487
787
|
};
|
|
788
|
+
|
|
488
789
|
static API = {
|
|
790
|
+
/**
|
|
791
|
+
* @method callback
|
|
792
|
+
* @description Initiates the execution of a specified CLI command (runner) with the given input value (`path`) and processed options.
|
|
793
|
+
* @param {string} runner - The name of the runner to execute.
|
|
794
|
+
* @param {string} path - The input value, identifier, or path for the operation.
|
|
795
|
+
* @param {Object} options - The default underpost runner options for customizing workflow
|
|
796
|
+
* @memberof UnderpostRun
|
|
797
|
+
* @returns {Promise<any>} The result of the callback execution.
|
|
798
|
+
*/
|
|
489
799
|
async callback(runner, path, options = UnderpostRun.DEFAULT_OPTION) {
|
|
490
800
|
const npmRoot = getNpmRootPath();
|
|
491
801
|
const underpostRoot = options?.dev === true ? '.' : `${npmRoot}/underpost`;
|