@underpostnet/underpost 2.98.3 → 2.99.1

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.
Files changed (42) hide show
  1. package/.env.development +1 -0
  2. package/.env.production +1 -0
  3. package/.env.test +1 -0
  4. package/README.md +2 -3
  5. package/bin/deploy.js +1 -1
  6. package/cli.md +113 -110
  7. package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
  8. package/manifests/deployment/dd-test-development/deployment.yaml +4 -4
  9. package/package.json +1 -2
  10. package/src/api/user/user.router.js +7 -40
  11. package/src/cli/baremetal.js +67 -71
  12. package/src/cli/cloud-init.js +11 -12
  13. package/src/cli/cluster.js +22 -24
  14. package/src/cli/db.js +43 -50
  15. package/src/cli/deploy.js +163 -61
  16. package/src/cli/env.js +20 -5
  17. package/src/cli/fs.js +19 -21
  18. package/src/cli/index.js +38 -32
  19. package/src/cli/lxd.js +5 -5
  20. package/src/cli/monitor.js +83 -88
  21. package/src/cli/repository.js +7 -6
  22. package/src/cli/run.js +498 -288
  23. package/src/cli/secrets.js +3 -3
  24. package/src/cli/ssh.js +80 -32
  25. package/src/cli/static.js +1 -1
  26. package/src/cli/test.js +6 -7
  27. package/src/index.js +49 -32
  28. package/src/runtime/express/Express.js +7 -6
  29. package/src/server/auth.js +6 -1
  30. package/src/server/backup.js +11 -1
  31. package/src/server/conf.js +4 -4
  32. package/src/{cli → server}/cron.js +56 -29
  33. package/src/server/dns.js +39 -31
  34. package/src/server/peer.js +2 -2
  35. package/src/server/process.js +2 -2
  36. package/src/server/proxy.js +8 -7
  37. package/src/server/runtime.js +4 -7
  38. package/src/server/start.js +28 -15
  39. package/src/ws/IoServer.js +2 -3
  40. package/scripts/ssh-cluster-info.sh +0 -15
  41. package/src/cli/script.js +0 -85
  42. package/src/monitor.js +0 -34
package/src/cli/run.js CHANGED
@@ -4,30 +4,138 @@
4
4
  * @namespace UnderpostRun
5
5
  */
6
6
 
7
- import { daemonProcess, getTerminalPid, openTerminal, pbcopy, shellCd, shellExec } from '../server/process.js';
7
+ import { daemonProcess, getTerminalPid, openTerminal, shellCd, shellExec } from '../server/process.js';
8
8
  import {
9
9
  awaitDeployMonitor,
10
10
  buildKindPorts,
11
11
  Config,
12
12
  getNpmRootPath,
13
- getUnderpostRootPath,
14
13
  isDeployRunnerContext,
15
14
  writeEnv,
16
15
  } from '../server/conf.js';
17
16
  import { actionInitLog, loggerFactory } from '../server/logger.js';
18
- import UnderpostTest from './test.js';
17
+
19
18
  import fs from 'fs-extra';
20
19
  import { range, setPad, timer } from '../client/components/core/CommonJs.js';
21
- import UnderpostDeploy from './deploy.js';
22
- import UnderpostDB from './db.js';
23
- import UnderpostRootEnv from './env.js';
24
- import UnderpostRepository from './repository.js';
20
+
25
21
  import os from 'os';
26
- import Underpost, { UnderpostSSH } from '../index.js';
22
+ import Underpost from '../index.js';
27
23
  import dotenv from 'dotenv';
28
24
 
29
25
  const logger = loggerFactory(import.meta);
30
26
 
27
+ /**
28
+ * @constant DEFAULT_OPTION
29
+ * @description Default options for the UnderpostRun class.
30
+ * @type {Object}
31
+ * @property {boolean} dev - Whether to run in development mode.
32
+ * @property {string} podName - The name of the pod to run.
33
+ * @property {string} nodeName - The name of the node to run.
34
+ * @property {number} port - Custom port to use.
35
+ * @property {boolean} etcHosts - Whether to modify /etc/hosts.
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 {string} timeoutResponse - The response timeout duration.
42
+ * @property {string} timeoutIdle - The idle timeout duration.
43
+ * @property {string} retryCount - The number of retries.
44
+ * @property {string} retryPerTryTimeout - The timeout duration per retry.
45
+ * @property {boolean} build - Whether to build the image.
46
+ * @property {number} replicas - The number of replicas to run.
47
+ * @property {boolean} force - Whether to force the operation.
48
+ * @property {boolean} reset - Whether to reset the operation.
49
+ * @property {boolean} tls - Whether to use TLS.
50
+ * @property {string} cmd - The command to run in the container.
51
+ * @property {string} tty - The TTY option for the container.
52
+ * @property {string} stdin - The stdin option for the container.
53
+ * @property {string} restartPolicy - The restart policy for the container.
54
+ * @property {string} runtimeClassName - The runtime class name for the container.
55
+ * @property {string} imagePullPolicy - The image pull policy for the container.
56
+ * @property {string} apiVersion - The API version for the container.
57
+ * @property {string} claimName - The claim name for the volume.
58
+ * @property {string} kindType - The kind of resource to create.
59
+ * @property {boolean} terminal - Whether to open a terminal.
60
+ * @property {number} devProxyPortOffset - The port offset for the development proxy.
61
+ * @property {boolean} hostNetwork - Whether to use host networking.
62
+ * @property {string} requestsMemory - The memory request for the container.
63
+ * @property {string} requestsCpu - The CPU request for the container.
64
+ * @property {string} limitsMemory - The memory limit for the container.
65
+ * @property {string} limitsCpu - The CPU limit for the container.
66
+ * @property {string} resourceTemplateId - The resource template ID.
67
+ * @property {boolean} expose - Whether to expose the service.
68
+ * @property {boolean} etcHosts - Whether to modify /etc/hosts.
69
+ * @property {string} confServerPath - The configuration server path.
70
+ * @property {string} underpostRoot - The root path of the Underpost installation.
71
+ * @property {string} cronJobs - The cron jobs to run.
72
+ * @property {string} timezone - The timezone to set.
73
+ * @property {boolean} kubeadm - Whether to run in kubeadm mode.
74
+ * @property {boolean} kind - Whether to run in kind mode.
75
+ * @property {boolean} k3s - Whether to run in k3s mode.
76
+ * @property {string} logType - The type of log to generate.
77
+ * @property {string} hosts - The hosts to use.
78
+ * @property {string} deployId - The deployment ID.
79
+ * @property {string} instanceId - The instance ID.
80
+ * @property {string} user - The user to run as.
81
+ * @property {string} pid - The process ID.
82
+ * @property {boolean} disablePrivateConfUpdate - Whether to disable private configuration updates.
83
+ * @memberof UnderpostRun
84
+ */
85
+ const DEFAULT_OPTION = {
86
+ dev: false,
87
+ podName: '',
88
+ nodeName: '',
89
+ port: 0,
90
+ volumeHostPath: '',
91
+ volumeMountPath: '',
92
+ imageName: '',
93
+ containerName: '',
94
+ namespace: 'default',
95
+ timeoutResponse: '',
96
+ timeoutIdle: '',
97
+ retryCount: '',
98
+ retryPerTryTimeout: '',
99
+ build: false,
100
+ replicas: 1,
101
+ force: false,
102
+ reset: false,
103
+ tls: false,
104
+ cmd: '',
105
+ tty: '',
106
+ stdin: '',
107
+ restartPolicy: '',
108
+ runtimeClassName: '',
109
+ imagePullPolicy: '',
110
+ apiVersion: '',
111
+ claimName: '',
112
+ kindType: '',
113
+ terminal: false,
114
+ devProxyPortOffset: 0,
115
+ hostNetwork: false,
116
+ requestsMemory: '',
117
+ requestsCpu: '',
118
+ limitsMemory: '',
119
+ limitsCpu: '',
120
+ resourceTemplateId: '',
121
+ expose: false,
122
+ etcHosts: false,
123
+ confServerPath: '',
124
+ underpostRoot: '',
125
+ cronJobs: '',
126
+ timezone: '',
127
+ kubeadm: false,
128
+ kind: false,
129
+ k3s: false,
130
+ logType: '',
131
+ hosts: '',
132
+ deployId: '',
133
+ instanceId: '',
134
+ user: '',
135
+ pid: '',
136
+ disablePrivateConfUpdate: false,
137
+ };
138
+
31
139
  /**
32
140
  * @class UnderpostRun
33
141
  * @description Manages the execution of various CLI commands and operations.
@@ -38,107 +146,6 @@ const logger = loggerFactory(import.meta);
38
146
  * @memberof UnderpostRun
39
147
  */
40
148
  class UnderpostRun {
41
- /**
42
- * @static
43
- * @description Default options for the UnderpostRun class.
44
- * @type {Object}
45
- * @property {boolean} dev - Whether to run in development mode.
46
- * @property {string} podName - The name of the pod to run.
47
- * @property {string} nodeName - The name of the node to run.
48
- * @property {number} port - Custom port to use.
49
- * @property {boolean} etcHosts - Whether to modify /etc/hosts.
50
- * @property {string} volumeHostPath - The host path for the volume.
51
- * @property {string} volumeMountPath - The mount path for the volume.
52
- * @property {string} imageName - The name of the image to run.
53
- * @property {string} containerName - The name of the container to run.
54
- * @property {string} namespace - The namespace to run in.
55
- * @property {boolean} build - Whether to build the image.
56
- * @property {number} replicas - The number of replicas to run.
57
- * @property {boolean} force - Whether to force the operation.
58
- * @property {boolean} reset - Whether to reset the operation.
59
- * @property {boolean} tls - Whether to use TLS.
60
- * @property {string} cmd - The command to run in the container.
61
- * @property {string} tty - The TTY option for the container.
62
- * @property {string} stdin - The stdin option for the container.
63
- * @property {string} restartPolicy - The restart policy for the container.
64
- * @property {string} runtimeClassName - The runtime class name for the container.
65
- * @property {string} imagePullPolicy - The image pull policy for the container.
66
- * @property {string} apiVersion - The API version for the container.
67
- * @property {string} claimName - The claim name for the volume.
68
- * @property {string} kindType - The kind of resource to create.
69
- * @property {boolean} terminal - Whether to open a terminal.
70
- * @property {number} devProxyPortOffset - The port offset for the development proxy.
71
- * @property {boolean} hostNetwork - Whether to use host networking.
72
- * @property {string} requestsMemory - The memory request for the container.
73
- * @property {string} requestsCpu - The CPU request for the container.
74
- * @property {string} limitsMemory - The memory limit for the container.
75
- * @property {string} limitsCpu - The CPU limit for the container.
76
- * @property {string} resourceTemplateId - The resource template ID.
77
- * @property {boolean} expose - Whether to expose the service.
78
- * @property {boolean} etcHosts - Whether to modify /etc/hosts.
79
- * @property {string} confServerPath - The configuration server path.
80
- * @property {string} underpostRoot - The root path of the Underpost installation.
81
- * @property {string} cronJobs - The cron jobs to run.
82
- * @property {string} timezone - The timezone to set.
83
- * @property {boolean} kubeadm - Whether to run in kubeadm mode.
84
- * @property {boolean} kind - Whether to run in kind mode.
85
- * @property {boolean} k3s - Whether to run in k3s mode.
86
- * @property {string} logType - The type of log to generate.
87
- * @property {string} hosts - The hosts to use.
88
- * @property {string} deployId - The deployment ID.
89
- * @property {string} instanceId - The instance ID.
90
- * @property {string} user - The user to run as.
91
- * @property {string} pid - The process ID.
92
- * @memberof UnderpostRun
93
- */
94
- static DEFAULT_OPTION = {
95
- dev: false,
96
- podName: '',
97
- nodeName: '',
98
- port: 0,
99
- volumeHostPath: '',
100
- volumeMountPath: '',
101
- imageName: '',
102
- containerName: '',
103
- namespace: 'default',
104
- build: false,
105
- replicas: 1,
106
- force: false,
107
- reset: false,
108
- tls: false,
109
- cmd: '',
110
- tty: '',
111
- stdin: '',
112
- restartPolicy: '',
113
- runtimeClassName: '',
114
- imagePullPolicy: '',
115
- apiVersion: '',
116
- claimName: '',
117
- kindType: '',
118
- terminal: false,
119
- devProxyPortOffset: 0,
120
- hostNetwork: false,
121
- requestsMemory: '',
122
- requestsCpu: '',
123
- limitsMemory: '',
124
- limitsCpu: '',
125
- resourceTemplateId: '',
126
- expose: false,
127
- etcHosts: false,
128
- confServerPath: '',
129
- underpostRoot: '',
130
- cronJobs: '',
131
- timezone: '',
132
- kubeadm: false,
133
- kind: false,
134
- k3s: false,
135
- logType: '',
136
- hosts: '',
137
- deployId: '',
138
- instanceId: '',
139
- user: '',
140
- pid: '',
141
- };
142
149
  /**
143
150
  * @static
144
151
  * @description Collection of runners for executing specific commands.
@@ -153,7 +160,7 @@ class UnderpostRun {
153
160
  * @param {Object} options - The default underpost runner options for customizing workflow
154
161
  * @memberof UnderpostRun
155
162
  */
156
- 'dev-cluster': (path, options = UnderpostRun.DEFAULT_OPTION) => {
163
+ 'dev-cluster': (path, options = DEFAULT_OPTION) => {
157
164
  const baseCommand = options.dev ? 'node bin' : 'underpost';
158
165
  const mongoHosts = ['mongodb-0.mongodb-service'];
159
166
  if (!options.expose) {
@@ -172,7 +179,7 @@ class UnderpostRun {
172
179
  // Detect MongoDB primary pod using centralized method
173
180
  let primaryMongoHost = 'mongodb-0.mongodb-service';
174
181
  try {
175
- const primaryPodName = UnderpostDB.API.getMongoPrimaryPodName({
182
+ const primaryPodName = Underpost.db.getMongoPrimaryPodName({
176
183
  namespace: options.namespace,
177
184
  podName: 'mongodb-0',
178
185
  });
@@ -189,7 +196,7 @@ class UnderpostRun {
189
196
  });
190
197
  }
191
198
 
192
- const hostListenResult = UnderpostDeploy.API.etcHostFactory([primaryMongoHost]);
199
+ const hostListenResult = Underpost.deploy.etcHostFactory([primaryMongoHost]);
193
200
  logger.info(hostListenResult.renderHosts);
194
201
  }
195
202
  },
@@ -201,7 +208,7 @@ class UnderpostRun {
201
208
  * @param {Object} options - The default underpost runner options for customizing workflow
202
209
  * @memberof UnderpostRun
203
210
  */
204
- metadata: async (path, options = UnderpostRun.DEFAULT_OPTION) => {
211
+ metadata: async (path, options = DEFAULT_OPTION) => {
205
212
  const ports = '6379,27017';
206
213
  shellExec(`node bin run kill '${ports}'`);
207
214
  shellExec(`node bin run dev-cluster --dev --expose --namespace ${options.namespace}`, { async: true });
@@ -219,7 +226,7 @@ class UnderpostRun {
219
226
  * @param {Object} options - The default underpost runner options for customizing workflow
220
227
  * @memberof UnderpostRun
221
228
  */
222
- 'svc-ls': (path, options = UnderpostRun.DEFAULT_OPTION) => {
229
+ 'svc-ls': (path, options = DEFAULT_OPTION) => {
223
230
  const log = shellExec(`systemctl list-units --type=service${path ? ` | grep ${path}` : ''}`, {
224
231
  silent: true,
225
232
  stdout: true,
@@ -239,7 +246,7 @@ class UnderpostRun {
239
246
  * @param {Object} options - The default underpost runner options for customizing workflow
240
247
  * @memberof UnderpostRun
241
248
  */
242
- 'svc-rm': (path, options = UnderpostRun.DEFAULT_OPTION) => {
249
+ 'svc-rm': (path, options = DEFAULT_OPTION) => {
243
250
  shellExec(`sudo systemctl stop ${path}`);
244
251
  shellExec(`sudo systemctl disable --now ${path}`);
245
252
  shellExec(`sudo dnf remove -y ${path}*`);
@@ -248,17 +255,25 @@ class UnderpostRun {
248
255
  },
249
256
 
250
257
  /**
251
- * @method ssh-cluster-info
252
- * @description Executes the `ssh-cluster-info.sh` script to display cluster connection information.
258
+ * @method ssh-deploy-info
259
+ * @description Retrieves deployment status and pod information from a remote server via SSH.
253
260
  * @param {string} path - The input value, identifier, or path for the operation.
254
261
  * @param {Object} options - The default underpost runner options for customizing workflow
255
262
  * @memberof UnderpostRun
256
263
  */
257
- 'ssh-cluster-info': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
258
- const { underpostRoot } = options;
259
- if (options.deployId && options.user) await UnderpostSSH.API.setDefautlSshCredentials(options);
260
- shellExec(`chmod +x ${underpostRoot}/scripts/ssh-cluster-info.sh`);
261
- shellExec(`${underpostRoot}/scripts/ssh-cluster-info.sh`);
264
+ 'ssh-deploy-info': async (path = '', options = DEFAULT_OPTION) => {
265
+ const env = options.dev ? 'development' : 'production';
266
+ await Underpost.ssh.sshRemoteRunner(
267
+ `node bin deploy ${path ? path : 'dd'} ${env} --status && kubectl get pods -A`,
268
+ {
269
+ deployId: options.deployId,
270
+ user: options.user,
271
+ dev: options.dev,
272
+ remote: true,
273
+ useSudo: true,
274
+ cd: '/home/dd/engine',
275
+ },
276
+ );
262
277
  },
263
278
 
264
279
  /**
@@ -268,7 +283,7 @@ class UnderpostRun {
268
283
  * @param {Object} options - The default underpost runner options for customizing workflow
269
284
  * @memberof UnderpostRun
270
285
  */
271
- 'dev-hosts-expose': (path, options = UnderpostRun.DEFAULT_OPTION) => {
286
+ 'dev-hosts-expose': (path, options = DEFAULT_OPTION) => {
272
287
  shellExec(
273
288
  `node bin deploy ${path} development --disable-update-deployment --disable-update-proxy --kubeadm --etc-hosts`,
274
289
  );
@@ -281,7 +296,7 @@ class UnderpostRun {
281
296
  * @param {Object} options - The default underpost runner options for customizing workflow
282
297
  * @memberof UnderpostRun
283
298
  */
284
- 'dev-hosts-restore': (path, options = UnderpostRun.DEFAULT_OPTION) => {
299
+ 'dev-hosts-restore': (path, options = DEFAULT_OPTION) => {
285
300
  shellExec(`node bin deploy --restore-hosts`);
286
301
  },
287
302
 
@@ -292,7 +307,7 @@ class UnderpostRun {
292
307
  * @param {Object} options - The default underpost runner options for customizing workflow
293
308
  * @memberof UnderpostRun
294
309
  */
295
- 'cluster-build': (path, options = UnderpostRun.DEFAULT_OPTION) => {
310
+ 'cluster-build': (path, options = DEFAULT_OPTION) => {
296
311
  const nodeOptions = options.nodeName ? ` --node-name ${options.nodeName}` : '';
297
312
  shellExec(`node bin run clean`);
298
313
  shellExec(`node bin run --dev sync-replica template-deploy${nodeOptions}`);
@@ -312,16 +327,20 @@ class UnderpostRun {
312
327
  * @param {Object} options - The default underpost runner options for customizing workflow
313
328
  * @memberof UnderpostRun
314
329
  */
315
- 'template-deploy': (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
330
+ 'template-deploy': (path = '', options = DEFAULT_OPTION) => {
316
331
  const baseCommand = options.dev ? 'node bin' : 'underpost';
317
332
  shellExec(`${baseCommand} run clean`);
318
333
  shellExec(
319
- `${baseCommand} push ./engine-private ${options.force ? '-f ' : ''}${process.env.GITHUB_USERNAME}/engine-private`,
334
+ `${baseCommand} push ./engine-private ${options.force ? '-f ' : ''}${
335
+ process.env.GITHUB_USERNAME
336
+ }/engine-private`,
320
337
  );
321
338
  shellCd('/home/dd/engine');
322
339
  shellExec(`git reset`);
323
340
  shellExec(
324
- `${baseCommand} cmt . --empty ci package-pwa-microservices-template${path.startsWith('sync') ? `-${path}` : ''}`,
341
+ `${baseCommand} cmt . --empty ci package-pwa-microservices-template${
342
+ path.startsWith('sync') ? `-${path}` : ''
343
+ }`,
325
344
  );
326
345
  shellExec(`${baseCommand} push . ${options.force ? '-f ' : ''}${process.env.GITHUB_USERNAME}/engine`);
327
346
  },
@@ -333,10 +352,12 @@ class UnderpostRun {
333
352
  * @param {Object} options - The default underpost runner options for customizing workflow
334
353
  * @memberof UnderpostRun
335
354
  */
336
- 'template-deploy-image': (path, options = UnderpostRun.DEFAULT_OPTION) => {
355
+ 'template-deploy-image': (path, options = DEFAULT_OPTION) => {
337
356
  // const baseCommand = options.dev ? 'node bin' : 'underpost';
338
357
  shellExec(
339
- `cd /home/dd/engine && git reset && underpost cmt . --empty ci docker-image 'underpost-engine:${Underpost.version}' && underpost push . ${options.force ? '-f ' : ''}${process.env.GITHUB_USERNAME}/engine`,
358
+ `cd /home/dd/engine && git reset && underpost cmt . --empty ci docker-image 'underpost-engine:${
359
+ Underpost.version
360
+ }' && underpost push . ${options.force ? '-f ' : ''}${process.env.GITHUB_USERNAME}/engine`,
340
361
  );
341
362
  },
342
363
  /**
@@ -346,7 +367,7 @@ class UnderpostRun {
346
367
  * @param {Object} options - The default underpost runner options for customizing workflow
347
368
  * @memberof UnderpostRun
348
369
  */
349
- clean: (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
370
+ clean: (path = '', options = DEFAULT_OPTION) => {
350
371
  Underpost.repo.clean({ paths: path ? path.split(',') : ['/home/dd/engine', '/home/dd/engine/engine-private'] });
351
372
  },
352
373
  /**
@@ -356,7 +377,7 @@ class UnderpostRun {
356
377
  * @param {Object} options - The default underpost runner options for customizing workflow
357
378
  * @memberof UnderpostRun
358
379
  */
359
- pull: (path, options = UnderpostRun.DEFAULT_OPTION) => {
380
+ pull: (path, options = DEFAULT_OPTION) => {
360
381
  if (!fs.existsSync(`/home/dd`) || !fs.existsSync(`/home/dd/engine`)) {
361
382
  fs.mkdirSync(`/home/dd`, { recursive: true });
362
383
  shellExec(`cd /home/dd && underpost clone ${process.env.GITHUB_USERNAME}/engine`, {
@@ -387,7 +408,7 @@ class UnderpostRun {
387
408
  * @param {Object} options - The default underpost runner options for customizing workflow
388
409
  * @memberof UnderpostRun
389
410
  */
390
- 'release-deploy': (path, options = UnderpostRun.DEFAULT_OPTION) => {
411
+ 'release-deploy': (path, options = DEFAULT_OPTION) => {
391
412
  actionInitLog();
392
413
  shellExec(`underpost --version`);
393
414
  shellCd(`/home/dd/engine`);
@@ -403,7 +424,7 @@ class UnderpostRun {
403
424
  * @param {Object} options - The default underpost runner options for customizing workflow
404
425
  * @memberof UnderpostRun
405
426
  */
406
- 'ssh-deploy': (path, options = UnderpostRun.DEFAULT_OPTION) => {
427
+ 'ssh-deploy': (path, options = DEFAULT_OPTION) => {
407
428
  actionInitLog();
408
429
  const baseCommand = options.dev ? 'node bin' : 'underpost';
409
430
  shellCd('/home/dd/engine');
@@ -419,7 +440,7 @@ class UnderpostRun {
419
440
  * @param {Object} options - The default underpost runner options for customizing workflow
420
441
  * @memberof UnderpostRun
421
442
  */
422
- ide: (path, options = UnderpostRun.DEFAULT_OPTION) => {
443
+ ide: (path, options = DEFAULT_OPTION) => {
423
444
  const { underpostRoot } = options;
424
445
  if (path === 'install') {
425
446
  shellExec(`sudo curl -f https://zed.dev/install.sh | sh`);
@@ -429,6 +450,16 @@ class UnderpostRun {
429
450
  shellExec(`sudo dnf install -y sublime-text`);
430
451
  } else shellExec(`node ${underpostRoot}/bin/zed ${path}`);
431
452
  },
453
+ /**
454
+ * @method crypto-policy
455
+ * @description Sets the system's crypto policies to `DEFAULT:SHA1` using `update-crypto-policies` command.
456
+ * @param {string} path - The input value, identifier, or path for the operation.
457
+ * @param {Object} options - The default underpost runner options for customizing workflow
458
+ * @memberof UnderpostRun
459
+ */
460
+ 'crypto-policy': (path, options = DEFAULT_OPTION) => {
461
+ shellExec(`sudo update-crypto-policies --set DEFAULT:SHA1`);
462
+ },
432
463
  /**
433
464
  * @method sync
434
465
  * @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).
@@ -436,7 +467,7 @@ class UnderpostRun {
436
467
  * @param {Object} options - The default underpost runner options for customizing workflow
437
468
  * @memberof UnderpostRun
438
469
  */
439
- sync: async (path, options = UnderpostRun.DEFAULT_OPTION) => {
470
+ sync: async (path, options = DEFAULT_OPTION) => {
440
471
  // Dev usage: node bin run --dev --build sync dd-default
441
472
  const env = options.dev ? 'development' : 'production';
442
473
  const baseCommand = options.dev ? 'node bin' : 'underpost';
@@ -456,42 +487,45 @@ class UnderpostRun {
456
487
  node = node ? node : defaultPath[4];
457
488
  shellExec(`${baseCommand} cluster --ns-use ${options.namespace}`);
458
489
  if (isDeployRunnerContext(path, options)) {
459
- const { validVersion } = UnderpostRepository.API.privateConfUpdate(deployId);
460
- if (!validVersion) throw new Error('Version mismatch');
490
+ if (!options.disablePrivateConfUpdate) {
491
+ const { validVersion } = Underpost.repo.privateConfUpdate(deployId);
492
+ if (!validVersion) throw new Error('Version mismatch');
493
+ }
461
494
  if (options.timezone !== 'none') shellExec(`${baseCommand} run${baseClusterCommand} tz`);
462
495
  if (options.cronJobs !== 'none') shellExec(`${baseCommand} run${baseClusterCommand} cron`);
463
496
  }
464
497
 
465
498
  const currentTraffic = isDeployRunnerContext(path, options)
466
- ? UnderpostDeploy.API.getCurrentTraffic(deployId, { namespace: options.namespace })
499
+ ? Underpost.deploy.getCurrentTraffic(deployId, { namespace: options.namespace })
467
500
  : '';
468
501
  let targetTraffic = currentTraffic ? (currentTraffic === 'blue' ? 'green' : 'blue') : 'green';
469
- if (targetTraffic) versions = targetTraffic;
502
+ if (targetTraffic) versions = versions ? versions : targetTraffic;
503
+
504
+ const timeoutFlags = Underpost.deploy.timeoutFlagsFactory(options);
505
+ const cmdString = options.cmd
506
+ ? ' --cmd ' + (options.cmd.find((c) => c.match('"')) ? '"' + options.cmd + '"' : "'" + options.cmd + "'")
507
+ : '';
470
508
 
471
509
  shellExec(
472
- `${baseCommand} deploy --kubeadm --build-manifest --sync --info-router --replicas ${
473
- replicas
474
- } --node ${node}${image ? ` --image ${image}` : ''}${versions ? ` --versions ${versions}` : ''}${options.namespace ? ` --namespace ${options.namespace}` : ''} dd ${env}`,
510
+ `${baseCommand} deploy --kubeadm --build-manifest --sync --info-router --replicas ${replicas} --node ${node}${
511
+ image ? ` --image ${image}` : ''
512
+ }${versions ? ` --versions ${versions}` : ''}${
513
+ options.namespace ? ` --namespace ${options.namespace}` : ''
514
+ }${timeoutFlags}${cmdString} dd ${env}`,
475
515
  );
476
516
 
477
517
  if (isDeployRunnerContext(path, options)) {
478
- const cmdString = options.cmd
479
- ? ` --cmd ${options.cmd.find((c) => c.match('"')) ? `"${options.cmd}"` : `'${options.cmd}'`}`
480
- : '';
481
518
  shellExec(
482
- `${baseCommand} deploy --kubeadm${cmdString} --replicas ${
483
- replicas
484
- } --disable-update-proxy ${deployId} ${env} --versions ${versions}${options.namespace ? ` --namespace ${options.namespace}` : ''}`,
519
+ `${baseCommand} deploy --kubeadm${cmdString} --replicas ${replicas} --disable-update-proxy ${deployId} ${env} --versions ${versions}${
520
+ options.namespace ? ` --namespace ${options.namespace}` : ''
521
+ }${timeoutFlags}`,
485
522
  );
486
523
  if (!targetTraffic)
487
- targetTraffic = UnderpostDeploy.API.getCurrentTraffic(deployId, { namespace: options.namespace });
488
- await UnderpostDeploy.API.monitorReadyRunner(deployId, env, targetTraffic, [], options.namespace, 'underpost');
489
- UnderpostDeploy.API.switchTraffic(deployId, env, targetTraffic, replicas, options.namespace);
524
+ targetTraffic = Underpost.deploy.getCurrentTraffic(deployId, { namespace: options.namespace });
525
+ await Underpost.deploy.monitorReadyRunner(deployId, env, targetTraffic, [], options.namespace, 'underpost');
526
+ Underpost.deploy.switchTraffic(deployId, env, targetTraffic, replicas, options.namespace, options);
490
527
  } else
491
- logger.info(
492
- 'current traffic',
493
- UnderpostDeploy.API.getCurrentTraffic(deployId, { namespace: options.namespace }),
494
- );
528
+ logger.info('current traffic', Underpost.deploy.getCurrentTraffic(deployId, { namespace: options.namespace }));
495
529
  },
496
530
 
497
531
  /**
@@ -501,8 +535,8 @@ class UnderpostRun {
501
535
  * @param {Object} options - The default underpost runner options for customizing workflow
502
536
  * @memberof UnderpostRun
503
537
  */
504
- stop: async (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
505
- let currentTraffic = UnderpostDeploy.API.getCurrentTraffic(options.deployId, {
538
+ stop: async (path = '', options = DEFAULT_OPTION) => {
539
+ let currentTraffic = Underpost.deploy.getCurrentTraffic(options.deployId, {
506
540
  namespace: options.namespace,
507
541
  hostTest: options.hosts,
508
542
  });
@@ -510,7 +544,9 @@ class UnderpostRun {
510
544
 
511
545
  if (!path.match('current')) currentTraffic === 'blue' ? (currentTraffic = 'green') : (currentTraffic = 'blue');
512
546
  const [_deployId] = path.split(',');
513
- const deploymentId = `${_deployId ? _deployId : options.deployId}${options.instanceId ? `-${options.instanceId}` : ''}-${env}-${currentTraffic}`;
547
+ const deploymentId = `${_deployId ? _deployId : options.deployId}${
548
+ options.instanceId ? `-${options.instanceId}` : ''
549
+ }-${env}-${currentTraffic}`;
514
550
 
515
551
  shellExec(`kubectl delete deployment ${deploymentId} -n ${options.namespace}`);
516
552
  shellExec(`kubectl delete svc ${deploymentId}-service -n ${options.namespace}`);
@@ -523,30 +559,122 @@ class UnderpostRun {
523
559
  * @param {Object} options - The default underpost runner options for customizing workflow
524
560
  * @memberof UnderpostRun
525
561
  */
526
- 'ssh-deploy-stop': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
527
- const env = options.dev ? 'development' : 'production';
562
+ 'ssh-deploy-stop': async (path, options = DEFAULT_OPTION) => {
528
563
  const baseCommand = options.dev ? 'node bin' : 'underpost';
529
564
  const baseClusterCommand = options.dev ? ' --dev' : '';
530
- await UnderpostSSH.API.setDefautlSshCredentials(options);
531
- shellExec(`#!/usr/bin/env bash
532
- set -euo pipefail
533
565
 
534
- REMOTE_USER=$(node bin config get --plain DEFAULT_SSH_USER)
535
- REMOTE_HOST=$(node bin config get --plain DEFAULT_SSH_HOST)
536
- REMOTE_PORT=$(node bin config get --plain DEFAULT_SSH_PORT)
537
- SSH_KEY=$(node bin config get --plain DEFAULT_SSH_KEY_PATH)
538
-
539
- chmod 600 "$SSH_KEY"
540
-
541
- ssh -i "$SSH_KEY" -o BatchMode=yes "$REMOTE_USER@$REMOTE_HOST" -p $REMOTE_PORT sh <<EOF
542
- cd /home/dd/engine
543
- sudo -n -- /bin/bash -lc "${[
566
+ const remoteCommand = [
544
567
  `${baseCommand} run${baseClusterCommand} stop${path ? ` ${path}` : ''}`,
545
568
  ` --deploy-id ${options.deployId}${options.instanceId ? ` --instance-id ${options.instanceId}` : ''}`,
546
569
  ` --namespace ${options.namespace}${options.hosts ? ` --hosts ${options.hosts}` : ''}`,
547
- ].join('')}"
548
- EOF
549
- `);
570
+ ].join('');
571
+
572
+ await Underpost.ssh.sshRemoteRunner(remoteCommand, {
573
+ deployId: options.deployId,
574
+ user: options.user,
575
+ dev: options.dev,
576
+ remote: true,
577
+ useSudo: true,
578
+ cd: '/home/dd/engine',
579
+ });
580
+ },
581
+
582
+ /**
583
+ * @method ssh-deploy-db-rollback
584
+ * @description Performs a database rollback on remote deployment via SSH.
585
+ * @param {string} path - Comma-separated deployId and optional number of commits to reset (format: "deployId,nCommits")
586
+ * @param {Object} options - The default underpost runner options for customizing workflow
587
+ * @param {string} options.deployId - The deployment identifier
588
+ * @param {string} options.user - The SSH user for credential lookup
589
+ * @param {boolean} options.dev - Development mode flag
590
+ * @memberof UnderpostRun
591
+ */
592
+ 'ssh-deploy-db-rollback': async (path = '', options = DEFAULT_OPTION) => {
593
+ const baseCommand = options.dev ? 'node bin' : 'underpost';
594
+ let [deployId, nCommitsReset] = path.split(',');
595
+ if (!nCommitsReset) nCommitsReset = 1;
596
+
597
+ const remoteCommand = `${baseCommand} db ${deployId} --git --kubeadm --primary-pod --force-clone --macro-rollback-export ${nCommitsReset}${options.namespace ? ` --ns ${options.namespace}` : ''}`;
598
+
599
+ await Underpost.ssh.sshRemoteRunner(remoteCommand, {
600
+ deployId: options.deployId,
601
+ user: options.user,
602
+ dev: options.dev,
603
+ remote: true,
604
+ useSudo: true,
605
+ cd: '/home/dd/engine',
606
+ });
607
+ },
608
+
609
+ /**
610
+ * @method ssh-deploy-db
611
+ * @description Imports/restores a database on remote deployment via SSH.
612
+ * @param {string} path - The deployment ID for database import
613
+ * @param {Object} options - The default underpost runner options for customizing workflow
614
+ * @param {string} options.deployId - The deployment identifier
615
+ * @param {string} options.user - The SSH user for credential lookup
616
+ * @param {boolean} options.dev - Development mode flag
617
+ * @memberof UnderpostRun
618
+ */
619
+ 'ssh-deploy-db': async (path, options = DEFAULT_OPTION) => {
620
+ const baseCommand = options.dev ? 'node bin' : 'underpost';
621
+
622
+ const remoteCommand = `${baseCommand} db ${path} --import --drop --preserveUUID --git --kubeadm --primary-pod --force-clone${options.namespace ? ` --ns ${options.namespace}` : ''}`;
623
+
624
+ await Underpost.ssh.sshRemoteRunner(remoteCommand, {
625
+ deployId: options.deployId,
626
+ user: options.user,
627
+ dev: options.dev,
628
+ remote: true,
629
+ useSudo: true,
630
+ cd: '/home/dd/engine',
631
+ });
632
+ },
633
+
634
+ /**
635
+ * @method ssh-deploy-db-status
636
+ * @description Retrieves database status/stats for a deployment (or all deployments from dd.router) via SSH.
637
+ * @param {string} path - Comma-separated deployId(s) or 'dd' to use the dd.router list.
638
+ * @param {Object} options - Runner options (uses options.deployId for SSH host lookup).
639
+ * @param {string} options.deployId - Deployment identifier used for SSH config lookup.
640
+ * @param {string} options.user - SSH user for credential lookup.
641
+ * @param {boolean} options.dev - Development mode flag.
642
+ * @param {string} [options.namespace] - Kubernetes namespace to pass to the db check.
643
+ * @memberof UnderpostRun
644
+ */
645
+ 'ssh-deploy-db-status': async (path = '', options = DEFAULT_OPTION) => {
646
+ const baseCommand = options.dev ? 'node bin' : 'underpost';
647
+
648
+ let deployList = [];
649
+ if (!path || path === 'dd') {
650
+ if (!fs.existsSync('./engine-private/deploy/dd.router')) {
651
+ logger.warn('dd.router not found; nothing to run');
652
+ return;
653
+ }
654
+ deployList = fs
655
+ .readFileSync('./engine-private/deploy/dd.router', 'utf8')
656
+ .split(',')
657
+ .map((d) => d.trim())
658
+ .filter(Boolean);
659
+ } else {
660
+ deployList = path
661
+ .split(',')
662
+ .map((d) => d.trim())
663
+ .filter(Boolean);
664
+ }
665
+
666
+ for (const deployId of deployList) {
667
+ const remoteCommand = `${baseCommand} db ${deployId} --stats --kubeadm --primary-pod${options.namespace ? ` --ns ${options.namespace}` : ''}`;
668
+
669
+ await Underpost.ssh.sshRemoteRunner(remoteCommand, {
670
+ deployId: options.deployId,
671
+ user: options.user,
672
+ dev: options.dev,
673
+ remote: true,
674
+ useSudo: true,
675
+ cd: '/home/dd/engine',
676
+ });
677
+ }
550
678
  },
551
679
 
552
680
  /**
@@ -556,14 +684,14 @@ EOF
556
684
  * @param {Object} options - The default underpost runner options for customizing workflow
557
685
  * @memberof UnderpostRun
558
686
  */
559
- tz: (path, options = UnderpostRun.DEFAULT_OPTION) => {
687
+ tz: (path, options = DEFAULT_OPTION) => {
560
688
  const tz =
561
689
  options.timezone && options.timezone !== 'none'
562
690
  ? options.timezone
563
691
  : path
564
692
  ? path
565
- : UnderpostRootEnv.API.get('TIME_ZONE', undefined, { disableLog: true })
566
- ? UnderpostRootEnv.API.get('TIME_ZONE')
693
+ : Underpost.env.get('TIME_ZONE', undefined, { disableLog: true })
694
+ ? Underpost.env.get('TIME_ZONE')
567
695
  : process.env.TIME_ZONE
568
696
  ? process.env.TIME_ZONE
569
697
  : 'America/New_York';
@@ -577,7 +705,7 @@ EOF
577
705
  * @param {Object} options - The default underpost runner options for customizing workflow
578
706
  * @memberof UnderpostRun
579
707
  */
580
- cron: (path, options = UnderpostRun.DEFAULT_OPTION) => {
708
+ cron: (path, options = DEFAULT_OPTION) => {
581
709
  const env = options.dev ? 'development' : 'production';
582
710
  shellExec(`node bin env ${path ? path : 'dd-cron'} ${env}`);
583
711
  shellExec(`npm start`);
@@ -591,7 +719,7 @@ EOF
591
719
  * @param {Object} options - The default underpost runner options for customizing workflow
592
720
  * @memberof UnderpostRun
593
721
  */
594
- 'get-proxy': async (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
722
+ 'get-proxy': async (path = '', options = DEFAULT_OPTION) => {
595
723
  console.log(
596
724
  shellExec(`kubectl get HTTPProxy -n ${options.namespace} ${path} -o yaml`, {
597
725
  silent: true,
@@ -608,7 +736,7 @@ EOF
608
736
  );
609
737
  },
610
738
 
611
- 'instance-promote': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
739
+ 'instance-promote': async (path, options = DEFAULT_OPTION) => {
612
740
  const env = options.dev ? 'development' : 'production';
613
741
  const baseCommand = options.dev ? 'node bin' : 'underpost';
614
742
  const baseClusterCommand = options.dev ? ' --dev' : '';
@@ -630,14 +758,14 @@ EOF
630
758
  } = instance;
631
759
  if (id !== _id) continue;
632
760
  const _deployId = `${deployId}-${_id}`;
633
- const currentTraffic = UnderpostDeploy.API.getCurrentTraffic(_deployId, {
761
+ const currentTraffic = Underpost.deploy.getCurrentTraffic(_deployId, {
634
762
  hostTest: _host,
635
763
  namespace: options.namespace,
636
764
  });
637
765
  const targetTraffic = currentTraffic ? (currentTraffic === 'blue' ? 'green' : 'blue') : 'blue';
638
766
  let proxyYaml =
639
- UnderpostDeploy.API.baseProxyYamlFactory({ host: _host, env: options.tls ? 'production' : env, options }) +
640
- UnderpostDeploy.API.deploymentYamlServiceFactory({
767
+ Underpost.deploy.baseProxyYamlFactory({ host: _host, env: options.tls ? 'production' : env, options }) +
768
+ Underpost.deploy.deploymentYamlServiceFactory({
641
769
  path: _path,
642
770
  port: _fromPort,
643
771
  // serviceId: deployId,
@@ -648,7 +776,7 @@ EOF
648
776
  });
649
777
  if (options.tls) {
650
778
  shellExec(`sudo kubectl delete Certificate ${_host} -n ${options.namespace} --ignore-not-found`);
651
- proxyYaml += UnderpostDeploy.API.buildCertManagerCertificate({ ...options, host: _host });
779
+ proxyYaml += Underpost.deploy.buildCertManagerCertificate({ ...options, host: _host });
652
780
  }
653
781
  // console.log(proxyYaml);
654
782
  shellExec(`kubectl delete HTTPProxy ${_host} --namespace ${options.namespace} --ignore-not-found`);
@@ -668,7 +796,7 @@ EOF
668
796
  * @param {Object} options - The default underpost runner options for customizing workflow
669
797
  * @memberof UnderpostRun
670
798
  */
671
- instance: async (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
799
+ instance: async (path = '', options = DEFAULT_OPTION) => {
672
800
  const env = options.dev ? 'development' : 'production';
673
801
  const baseCommand = options.dev ? 'node bin' : 'underpost';
674
802
  const baseClusterCommand = options.dev ? ' --dev' : '';
@@ -706,20 +834,20 @@ EOF
706
834
  shellExec(`sudo kind load docker-image ${_image}`);
707
835
  }
708
836
 
709
- const currentTraffic = UnderpostDeploy.API.getCurrentTraffic(_deployId, {
837
+ const currentTraffic = Underpost.deploy.getCurrentTraffic(_deployId, {
710
838
  hostTest: _host,
711
839
  namespace: options.namespace,
712
840
  });
713
841
 
714
842
  const targetTraffic = currentTraffic ? (currentTraffic === 'blue' ? 'green' : 'blue') : 'blue';
715
843
  const podId = `${_deployId}-${env}-${targetTraffic}`;
716
- const ignorePods = UnderpostDeploy.API.get(podId, 'pods', options.namespace).map((p) => p.NAME);
717
- UnderpostDeploy.API.configMap(env, options.namespace);
844
+ const ignorePods = Underpost.deploy.get(podId, 'pods', options.namespace).map((p) => p.NAME);
845
+ Underpost.deploy.configMap(env, options.namespace);
718
846
  shellExec(`kubectl delete service ${podId}-service --namespace ${options.namespace} --ignore-not-found`);
719
847
  shellExec(`kubectl delete deployment ${podId} --namespace ${options.namespace} --ignore-not-found`);
720
848
  for (const _volume of _volumes)
721
849
  if (_volume.claimName)
722
- UnderpostDeploy.API.deployVolume(_volume, {
850
+ Underpost.deploy.deployVolume(_volume, {
723
851
  namespace: options.namespace,
724
852
  deployId: _deployId,
725
853
  env,
@@ -727,17 +855,19 @@ EOF
727
855
  nodeName: options.nodeName,
728
856
  });
729
857
  let deploymentYaml = `---
730
- ${UnderpostDeploy.API.deploymentYamlPartsFactory({
731
- deployId: _deployId,
732
- env,
733
- suffix: targetTraffic,
734
- resources: UnderpostDeploy.API.resourcesFactory(options),
735
- replicas,
736
- image: _image,
737
- namespace: options.namespace,
738
- volumes: _volumes,
739
- cmd: _cmd[env],
740
- }).replace('{{ports}}', buildKindPorts(_fromPort, _toPort))}
858
+ ${Underpost.deploy
859
+ .deploymentYamlPartsFactory({
860
+ deployId: _deployId,
861
+ env,
862
+ suffix: targetTraffic,
863
+ resources: Underpost.deploy.resourcesFactory(options),
864
+ replicas,
865
+ image: _image,
866
+ namespace: options.namespace,
867
+ volumes: _volumes,
868
+ cmd: _cmd[env],
869
+ })
870
+ .replace('{{ports}}', buildKindPorts(_fromPort, _toPort))}
741
871
  `;
742
872
  // console.log(deploymentYaml);
743
873
  shellExec(
@@ -747,7 +877,7 @@ EOF
747
877
  `,
748
878
  { disableLog: true },
749
879
  );
750
- const { ready, readyPods } = await UnderpostDeploy.API.monitorReadyRunner(
880
+ const { ready, readyPods } = await Underpost.deploy.monitorReadyRunner(
751
881
  _deployId,
752
882
  env,
753
883
  targetTraffic,
@@ -768,20 +898,20 @@ EOF
768
898
  );
769
899
  }
770
900
  if (options.etcHosts) {
771
- const hostListenResult = UnderpostDeploy.API.etcHostFactory(etcHosts);
901
+ const hostListenResult = Underpost.deploy.etcHostFactory(etcHosts);
772
902
  logger.info(hostListenResult.renderHosts);
773
903
  }
774
904
  },
775
905
 
776
906
  /**
777
907
  * @method ls-deployments
778
- * @description Retrieves and logs a table of Kubernetes deployments using `UnderpostDeploy.API.get`.
908
+ * @description Retrieves and logs a table of Kubernetes deployments using `Underpost.deploy.get`.
779
909
  * @param {string} path - The input value, identifier, or path for the operation (used as an optional deployment name filter).
780
910
  * @param {Object} options - The default underpost runner options for customizing workflow
781
911
  * @memberof UnderpostRun
782
912
  */
783
- 'ls-deployments': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
784
- console.table(await UnderpostDeploy.API.get(path, 'deployments', options.namespace));
913
+ 'ls-deployments': async (path, options = DEFAULT_OPTION) => {
914
+ console.table(await Underpost.deploy.get(path, 'deployments', options.namespace));
785
915
  },
786
916
 
787
917
  /**
@@ -791,7 +921,7 @@ EOF
791
921
  * @param {Object} options - The default underpost runner options for customizing workflow
792
922
  * @memberof UnderpostRun
793
923
  */
794
- 'host-update': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
924
+ 'host-update': async (path, options = DEFAULT_OPTION) => {
795
925
  // const baseCommand = options.dev ? 'node bin' : 'underpost';
796
926
  shellExec(`chmod +x ${options.underpostRoot}/scripts/rocky-setup.sh`);
797
927
  shellExec(`${options.underpostRoot}/scripts/rocky-setup.sh${options.dev ? ' --install-dev' : ``}`);
@@ -804,14 +934,14 @@ EOF
804
934
  * @param {Object} options - The default underpost runner options for customizing workflow
805
935
  * @memberof UnderpostRun
806
936
  */
807
- 'dd-container': async (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
937
+ 'dd-container': async (path = '', options = DEFAULT_OPTION) => {
808
938
  const baseCommand = options.dev ? 'node bin' : 'underpost';
809
939
  const baseClusterCommand = options.dev ? ' --dev' : '';
810
940
  const currentImage = options.imageName
811
941
  ? options.imageName
812
- : UnderpostDeploy.API.getCurrentLoadedImages(options.nodeName ? options.nodeName : 'kind-worker', false).find(
813
- (o) => o.IMAGE.match('underpost'),
814
- );
942
+ : Underpost.deploy
943
+ .getCurrentLoadedImages(options.nodeName ? options.nodeName : 'kind-worker', false)
944
+ .find((o) => o.IMAGE.match('underpost'));
815
945
  const podName = options.podName || `underpost-dev-container`;
816
946
  const volumeHostPath = options.claimName || '/home/dd';
817
947
  const claimName = options.claimName || `pvc-dd`;
@@ -851,7 +981,7 @@ EOF
851
981
  args: [daemonProcess(path ? path : `cd /home/dd/engine && npm install && npm run test`)],
852
982
  };
853
983
 
854
- await UnderpostRun.RUNNERS['deploy-job'](path, payload);
984
+ await Underpost.run.RUNNERS['deploy-job'](path, payload);
855
985
  },
856
986
 
857
987
  /**
@@ -861,7 +991,7 @@ EOF
861
991
  * @param {Object} options - The default underpost runner options for customizing workflow
862
992
  * @memberof UnderpostRun
863
993
  */
864
- 'ip-info': (path, options = UnderpostRun.DEFAULT_OPTION) => {
994
+ 'ip-info': (path, options = DEFAULT_OPTION) => {
865
995
  const { underpostRoot } = options;
866
996
  shellExec(`chmod +x ${underpostRoot}/scripts/ip-info.sh`);
867
997
  shellExec(`${underpostRoot}/scripts/ip-info.sh ${path}`);
@@ -874,12 +1004,12 @@ EOF
874
1004
  * @param {Object} options - The default underpost runner options for customizing workflow
875
1005
  * @memberof UnderpostRun
876
1006
  */
877
- monitor: (path, options = UnderpostRun.DEFAULT_OPTION) => {
1007
+ monitor: (path, options = DEFAULT_OPTION) => {
878
1008
  const pid = getTerminalPid();
879
1009
  logger.info('monitor pid', pid);
880
1010
  const checkPath = '/await';
881
1011
  const _monitor = async () => {
882
- const result = UnderpostDeploy.API.existsContainerFile({ podName: path, path: checkPath });
1012
+ const result = Underpost.deploy.existsContainerFile({ podName: path, path: checkPath });
883
1013
  logger.info('monitor', result);
884
1014
  if (result === true) {
885
1015
  switch (path) {
@@ -916,7 +1046,7 @@ EOF
916
1046
  const checkPath = `/latent_space_plot.png`;
917
1047
  const outsPaths = [];
918
1048
  logger.info('monitor', checkPath);
919
- while (!UnderpostDeploy.API.existsContainerFile({ podName, path: `/home/dd/docs${checkPath}` }))
1049
+ while (!Underpost.deploy.existsContainerFile({ podName, path: `/home/dd/docs${checkPath}` }))
920
1050
  await timer(1000);
921
1051
 
922
1052
  {
@@ -954,7 +1084,7 @@ EOF
954
1084
  * @param {Object} options - The default underpost runner options for customizing workflow
955
1085
  * @memberof UnderpostRun
956
1086
  */
957
- 'db-client': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
1087
+ 'db-client': async (path, options = DEFAULT_OPTION) => {
958
1088
  const { underpostRoot } = options;
959
1089
 
960
1090
  const image = 'adminer:4.7.6-standalone';
@@ -969,7 +1099,7 @@ EOF
969
1099
 
970
1100
  shellExec(`kubectl delete deployment adminer -n ${options.namespace} --ignore-not-found`);
971
1101
  shellExec(`kubectl apply -k ${underpostRoot}/manifests/deployment/adminer/. -n ${options.namespace}`);
972
- const successInstance = await UnderpostTest.API.statusMonitor('adminer', 'Running', 'pods', 1000, 60 * 10);
1102
+ const successInstance = await Underpost.test.statusMonitor('adminer', 'Running', 'pods', 1000, 60 * 10);
973
1103
 
974
1104
  if (successInstance) {
975
1105
  shellExec(`underpost deploy --expose adminer --namespace ${options.namespace}`);
@@ -983,16 +1113,16 @@ EOF
983
1113
  * @param {Object} options - The default underpost runner options for customizing workflow
984
1114
  * @memberof UnderpostRun
985
1115
  */
986
- 'git-conf': (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
987
- const defaultUsername = UnderpostRootEnv.API.get('GITHUB_USERNAME');
988
- const defaultEmail = UnderpostRootEnv.API.get('GITHUB_EMAIL');
1116
+ 'git-conf': (path = '', options = DEFAULT_OPTION) => {
1117
+ const defaultUsername = Underpost.env.get('GITHUB_USERNAME');
1118
+ const defaultEmail = Underpost.env.get('GITHUB_EMAIL');
989
1119
  const validPath = path && path.split(',').length;
990
1120
  const [username, email] = validPath ? path.split(',') : [defaultUsername, defaultEmail];
991
1121
  if (validPath) {
992
- UnderpostRootEnv.API.set('GITHUB_USERNAME', username);
993
- UnderpostRootEnv.API.set('GITHUB_EMAIL', email);
994
- UnderpostRootEnv.API.get('GITHUB_USERNAME');
995
- UnderpostRootEnv.API.get('GITHUB_EMAIL');
1122
+ Underpost.env.set('GITHUB_USERNAME', username);
1123
+ Underpost.env.set('GITHUB_EMAIL', email);
1124
+ Underpost.env.get('GITHUB_USERNAME');
1125
+ Underpost.env.get('GITHUB_EMAIL');
996
1126
  }
997
1127
  shellExec(
998
1128
  `git config --global credential.helper "" && ` +
@@ -1022,20 +1152,27 @@ EOF
1022
1152
  * @param {Object} options - The default underpost runner options for customizing workflow
1023
1153
  * @memberof UnderpostRun
1024
1154
  */
1025
- promote: async (path, options = UnderpostRun.DEFAULT_OPTION) => {
1155
+ promote: async (path, options = DEFAULT_OPTION) => {
1026
1156
  let [inputDeployId, inputEnv, inputReplicas] = path.split(',');
1027
1157
  if (!inputEnv) inputEnv = 'production';
1028
1158
  if (!inputReplicas) inputReplicas = 1;
1029
1159
  if (inputDeployId === 'dd') {
1030
1160
  for (const deployId of fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8').split(',')) {
1031
- const currentTraffic = UnderpostDeploy.API.getCurrentTraffic(deployId, { namespace: options.namespace });
1161
+ const currentTraffic = Underpost.deploy.getCurrentTraffic(deployId, { namespace: options.namespace });
1032
1162
  const targetTraffic = currentTraffic === 'blue' ? 'green' : 'blue';
1033
- UnderpostDeploy.API.switchTraffic(deployId, inputEnv, targetTraffic, inputReplicas, options.namespace);
1163
+ Underpost.deploy.switchTraffic(deployId, inputEnv, targetTraffic, inputReplicas, options.namespace, options);
1034
1164
  }
1035
1165
  } else {
1036
- const currentTraffic = UnderpostDeploy.API.getCurrentTraffic(inputDeployId, { namespace: options.namespace });
1166
+ const currentTraffic = Underpost.deploy.getCurrentTraffic(inputDeployId, { namespace: options.namespace });
1037
1167
  const targetTraffic = currentTraffic === 'blue' ? 'green' : 'blue';
1038
- UnderpostDeploy.API.switchTraffic(inputDeployId, inputEnv, targetTraffic, inputReplicas, options.namespace);
1168
+ Underpost.deploy.switchTraffic(
1169
+ inputDeployId,
1170
+ inputEnv,
1171
+ targetTraffic,
1172
+ inputReplicas,
1173
+ options.namespace,
1174
+ options,
1175
+ );
1039
1176
  }
1040
1177
  },
1041
1178
  /**
@@ -1045,7 +1182,7 @@ EOF
1045
1182
  * @param {Object} options - The default underpost runner options for customizing workflow
1046
1183
  * @memberof UnderpostRun
1047
1184
  */
1048
- metrics: async (path, options = UnderpostRun.DEFAULT_OPTION) => {
1185
+ metrics: async (path, options = DEFAULT_OPTION) => {
1049
1186
  const deployList = fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8').split(',');
1050
1187
  let hosts = [];
1051
1188
  for (const deployId of deployList) {
@@ -1062,7 +1199,7 @@ EOF
1062
1199
  * @param {Object} options - The default underpost runner options for customizing workflow
1063
1200
  * @memberof UnderpostRun
1064
1201
  */
1065
- cluster: async (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
1202
+ cluster: async (path = '', options = DEFAULT_OPTION) => {
1066
1203
  const { underpostRoot } = options;
1067
1204
  const env = options.dev ? 'development' : 'production';
1068
1205
  const baseCommand = options.dev ? 'node bin' : 'underpost';
@@ -1097,7 +1234,9 @@ EOF
1097
1234
  }
1098
1235
  await timer(5000);
1099
1236
  for (const deployId of deployList) {
1100
- shellExec(`${baseCommand} db ${deployId} --import --git --drop --preserveUUID --primary-pod`);
1237
+ shellExec(
1238
+ `${baseCommand} db ${deployId} --import --git --drop --preserveUUID --primary-pod${options.namespace ? ` --ns ${options.namespace}` : ''}`,
1239
+ );
1101
1240
  }
1102
1241
  await timer(5000);
1103
1242
  shellExec(`${baseCommand} cluster${baseClusterCommand} --${clusterType} --pull-image --valkey`);
@@ -1111,7 +1250,7 @@ EOF
1111
1250
  shellExec(
1112
1251
  `${baseCommand} deploy ${deployId} ${env} --${clusterType}${env === 'production' ? ' --cert' : ''}${
1113
1252
  env === 'development' ? ' --etc-hosts' : ''
1114
- }`,
1253
+ }${options.namespace ? ` --namespace ${options.namespace}` : ''}`,
1115
1254
  );
1116
1255
  }
1117
1256
  },
@@ -1122,20 +1261,20 @@ EOF
1122
1261
  * @param {Object} options - The default underpost runner options for customizing workflow
1123
1262
  * @memberof UnderpostRun
1124
1263
  */
1125
- deploy: async (path, options = UnderpostRun.DEFAULT_OPTION) => {
1264
+ deploy: async (path, options = DEFAULT_OPTION) => {
1126
1265
  const deployId = path;
1127
- const { validVersion } = UnderpostRepository.API.privateConfUpdate(deployId);
1266
+ const { validVersion } = Underpost.repo.privateConfUpdate(deployId);
1128
1267
  if (!validVersion) throw new Error('Version mismatch');
1129
- const currentTraffic = UnderpostDeploy.API.getCurrentTraffic(deployId, { namespace: options.namespace });
1268
+ const currentTraffic = Underpost.deploy.getCurrentTraffic(deployId, { namespace: options.namespace });
1130
1269
  const targetTraffic = currentTraffic === 'blue' ? 'green' : 'blue';
1131
- const env = 'production';
1132
- const ignorePods = UnderpostDeploy.API.get(`${deployId}-${env}-${targetTraffic}`, 'pods', options.namespace).map(
1133
- (p) => p.NAME,
1134
- );
1270
+ const env = options.dev ? 'development' : 'production';
1271
+ const ignorePods = Underpost.deploy
1272
+ .get(`${deployId}-${env}-${targetTraffic}`, 'pods', options.namespace)
1273
+ .map((p) => p.NAME);
1135
1274
 
1136
1275
  shellExec(`sudo kubectl rollout restart deployment/${deployId}-${env}-${targetTraffic} -n ${options.namespace}`);
1137
1276
 
1138
- await UnderpostDeploy.API.monitorReadyRunner(
1277
+ await Underpost.deploy.monitorReadyRunner(
1139
1278
  deployId,
1140
1279
  env,
1141
1280
  targetTraffic,
@@ -1144,7 +1283,7 @@ EOF
1144
1283
  'underpost',
1145
1284
  );
1146
1285
 
1147
- UnderpostDeploy.API.switchTraffic(deployId, env, targetTraffic, options.replicas, options.namespace);
1286
+ Underpost.deploy.switchTraffic(deployId, env, targetTraffic, options.replicas, options.namespace, options);
1148
1287
  },
1149
1288
 
1150
1289
  /**
@@ -1154,7 +1293,7 @@ EOF
1154
1293
  * @param {Object} options - The default underpost runner options for customizing workflow
1155
1294
  * @memberof UnderpostRun
1156
1295
  */
1157
- 'disk-clean': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
1296
+ 'disk-clean': async (path, options = DEFAULT_OPTION) => {
1158
1297
  const { underpostRoot } = options;
1159
1298
  shellExec(`chmod +x ${underpostRoot}/scripts/disk-clean.sh`);
1160
1299
  shellExec(`./scripts/disk-clean.sh`);
@@ -1167,7 +1306,7 @@ EOF
1167
1306
  * @param {Object} options - The default underpost runner options for customizing workflow
1168
1307
  * @memberof UnderpostRun
1169
1308
  */
1170
- 'disk-usage': async (path = '/', options = UnderpostRun.DEFAULT_OPTION) => {
1309
+ 'disk-usage': async (path = '/', options = DEFAULT_OPTION) => {
1171
1310
  if (!path) path = '/';
1172
1311
  logger.info('Mount filesystem');
1173
1312
  shellExec(`df -h${path === '/' ? '' : ` ${path}`}`);
@@ -1182,7 +1321,7 @@ EOF
1182
1321
  * @param {Object} options - The default underpost runner options for customizing workflow
1183
1322
  * @memberof UnderpostRun
1184
1323
  */
1185
- dev: async (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
1324
+ dev: async (path = '', options = DEFAULT_OPTION) => {
1186
1325
  let [deployId, subConf, host, _path, clientHostPort] = path.split(',');
1187
1326
  if (options.confServerPath) {
1188
1327
  const confServer = JSON.parse(fs.readFileSync(options.confServerPath, 'utf8'));
@@ -1216,7 +1355,9 @@ EOF
1216
1355
  }
1217
1356
  shellExec(`node bin run dev-cluster --expose --namespace ${options.namespace}`, { async: true });
1218
1357
  {
1219
- const cmd = `npm run dev-api ${deployId} ${subConf} ${host} ${_path} ${clientHostPort}${options.tls ? ' tls' : ''}`;
1358
+ const cmd = `npm run dev-api ${deployId} ${subConf} ${host} ${_path} ${clientHostPort}${
1359
+ options.tls ? ' tls' : ''
1360
+ }`;
1220
1361
  options.terminal ? openTerminal(cmd) : shellExec(cmd, { async: true });
1221
1362
  }
1222
1363
  await awaitDeployMonitor(true);
@@ -1239,7 +1380,7 @@ EOF
1239
1380
  * @param {Object} options - The default underpost runner options for customizing workflow
1240
1381
  * @memberof UnderpostRun
1241
1382
  */
1242
- service: async (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
1383
+ service: async (path = '', options = DEFAULT_OPTION) => {
1243
1384
  const env = options.dev ? 'development' : 'production';
1244
1385
  const baseCommand = options.dev ? 'node bin' : 'underpost';
1245
1386
  const baseClusterCommand = options.dev ? ' --dev' : '';
@@ -1304,25 +1445,49 @@ EOF
1304
1445
  break;
1305
1446
  }
1306
1447
  }
1307
- const success = await UnderpostTest.API.statusMonitor(podToMonitor);
1448
+ const success = await Underpost.test.statusMonitor(podToMonitor);
1308
1449
  if (success) {
1309
- const versions = UnderpostDeploy.API.getCurrentTraffic(deployId, { namespace: options.namespace }) || 'blue';
1450
+ const versions = Underpost.deploy.getCurrentTraffic(deployId, { namespace: options.namespace }) || 'blue';
1310
1451
  if (!node) node = os.hostname();
1452
+ const timeoutFlags = Underpost.deploy.timeoutFlagsFactory(options);
1311
1453
  shellExec(
1312
- `${baseCommand} deploy${options.dev ? '' : ' --kubeadm'}${options.devProxyPortOffset ? ' --disable-deployment-proxy' : ''} --build-manifest --sync --info-router --replicas ${
1313
- replicas
1314
- } --node ${node}${image ? ` --image ${image}` : ''}${versions ? ` --versions ${versions}` : ''} dd ${env}`,
1454
+ `${baseCommand} deploy${options.dev ? '' : ' --kubeadm'}${
1455
+ options.devProxyPortOffset ? ' --disable-deployment-proxy' : ''
1456
+ } --build-manifest --sync --info-router --replicas ${replicas} --node ${node}${
1457
+ image ? ` --image ${image}` : ''
1458
+ }${versions ? ` --versions ${versions}` : ''}${timeoutFlags} dd ${env}`,
1315
1459
  );
1316
1460
  shellExec(
1317
- `${baseCommand} deploy${options.dev ? '' : ' --kubeadm'}${options.devProxyPortOffset ? ' --disable-deployment-proxy' : ''} --disable-update-deployment ${deployId} ${env} --versions ${versions}`,
1461
+ `${baseCommand} deploy${options.dev ? '' : ' --kubeadm'}${
1462
+ options.devProxyPortOffset ? ' --disable-deployment-proxy' : ''
1463
+ } --disable-update-deployment ${deployId} ${env} --versions ${versions}`,
1318
1464
  );
1319
1465
  } else logger.error(`Service pod ${podToMonitor} failed to start in time.`);
1320
1466
  if (options.etcHosts === true) {
1321
- const hostListenResult = UnderpostDeploy.API.etcHostFactory([host]);
1467
+ const hostListenResult = Underpost.deploy.etcHostFactory([host]);
1322
1468
  logger.info(hostListenResult.renderHosts);
1323
1469
  }
1324
1470
  },
1325
1471
 
1472
+ /**
1473
+ * @method etc-hosts
1474
+ * @description Generates and logs the contents for the `/etc/hosts` file based on provided hosts or deployment configurations.
1475
+ * @param {string} path - The input value, identifier, or path for the operation (used as a comma-separated list of hosts).
1476
+ * @param {Object} options - The default underpost runner options for customizing workflow
1477
+ * @memberof UnderpostRun
1478
+ */
1479
+ 'etc-hosts': async (path = '', options = DEFAULT_OPTION) => {
1480
+ const hosts = path ? path.split(',') : [];
1481
+ if (options.deployId) {
1482
+ const confServer = JSON.parse(
1483
+ fs.readFileSync(`./engine-private/conf/${options.deployId}/conf.server.json`, 'utf8'),
1484
+ );
1485
+ hosts.push(...Object.keys(confServer));
1486
+ }
1487
+ const hostListenResult = Underpost.deploy.etcHostFactory(hosts);
1488
+ logger.info(hostListenResult.renderHosts);
1489
+ },
1490
+
1326
1491
  /**
1327
1492
  * @method sh
1328
1493
  * @description Enables remote control for the Kitty terminal emulator.
@@ -1330,11 +1495,13 @@ EOF
1330
1495
  * @param {Object} options - The default underpost runner options for customizing workflow
1331
1496
  * @memberof UnderpostRun
1332
1497
  */
1333
- sh: async (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
1498
+ sh: async (path = '', options = DEFAULT_OPTION) => {
1334
1499
  let [operator, arg0, arg1] = path.split(',');
1335
1500
  if (operator == 'copy') {
1336
1501
  shellExec(
1337
- `kitty @ get-text ${arg0 === 'all' ? '--match all' : '--self'} --extent all${arg1 === 'ansi' ? ' --ansi yes' : ''} | kitty +kitten clipboard`,
1502
+ `kitty @ get-text ${arg0 === 'all' ? '--match all' : '--self'} --extent all${
1503
+ arg1 === 'ansi' ? ' --ansi yes' : ''
1504
+ } | kitty +kitten clipboard`,
1338
1505
  );
1339
1506
  return;
1340
1507
  }
@@ -1348,7 +1515,7 @@ EOF
1348
1515
  * @param {Object} options - The default underpost runner options for customizing workflow
1349
1516
  * @memberof UnderpostRun
1350
1517
  */
1351
- log: async (path, options = UnderpostRun.DEFAULT_OPTION) => {
1518
+ log: async (path, options = DEFAULT_OPTION) => {
1352
1519
  const [filePath, keywords, lines] = path.split(',');
1353
1520
  let result = shellExec(`grep -i -E ${lines ? `-C ${lines} ` : ''}'${keywords}' ${filePath}`, {
1354
1521
  stdout: true,
@@ -1365,12 +1532,22 @@ EOF
1365
1532
  * @param {Object} options - The default underpost runner options for customizing workflow
1366
1533
  * @memberof UnderpostRun
1367
1534
  */
1368
- ps: async (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
1369
- const out = shellExec(`ps aux${path ? `| grep '${path}' | grep -v grep` : ''}`, {
1370
- stdout: true,
1371
- silent: true,
1372
- });
1373
- console.log(path ? out.replaceAll(path, path.bgYellow.black.bold) : out);
1535
+ ps: async (path = '', options = DEFAULT_OPTION) => {
1536
+ const out = shellExec(
1537
+ path.startsWith('top-consumers')
1538
+ ? `ps -eo pid,%cpu,%mem,rss,cmd --sort=-%cpu | head -n ${path.split(',')[1] || 15}`
1539
+ : path
1540
+ ? `(ps -eo pid,%cpu,%mem,rss,cmd -ww | head -n1; ps -eo pid,%cpu,%mem,rss,cmd -ww | tail -n +2 | grep -F ${path})`
1541
+ : `ps -eo pid,%cpu,%mem,rss,cmd -ww`,
1542
+ {
1543
+ stdout: true,
1544
+ silent: true,
1545
+ },
1546
+ );
1547
+
1548
+ console.log(
1549
+ path ? out.replaceAll(path.split(',')[2] || path, (path.split(',')[2] || path).bgYellow.black.bold) : out,
1550
+ );
1374
1551
  },
1375
1552
 
1376
1553
  /**
@@ -1380,7 +1557,7 @@ EOF
1380
1557
  * @param {Object} options - The default underpost runner options for customizing workflow
1381
1558
  * @memberof UnderpostRun
1382
1559
  */
1383
- ptls: async (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
1560
+ ptls: async (path = '', options = DEFAULT_OPTION) => {
1384
1561
  shellExec(`chmod +x ${options.underpostRoot}/scripts/ports-ls.sh`);
1385
1562
  shellExec(`${options.underpostRoot}/scripts/ports-ls.sh`);
1386
1563
  },
@@ -1391,7 +1568,7 @@ EOF
1391
1568
  * @param {Object} options - The default underpost runner options for customizing workflow
1392
1569
  * @memberof UnderpostRun
1393
1570
  */
1394
- 'release-cmt': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
1571
+ 'release-cmt': async (path, options = DEFAULT_OPTION) => {
1395
1572
  shellExec(`underpost run pull`);
1396
1573
  shellExec(`underpost run secret`);
1397
1574
  shellCd(`/home/dd/engine`);
@@ -1406,7 +1583,7 @@ EOF
1406
1583
  * @param {Object} options - The default underpost runner options for customizing workflow
1407
1584
  * @memberof UnderpostRun
1408
1585
  */
1409
- 'deploy-test': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
1586
+ 'deploy-test': async (path, options = DEFAULT_OPTION) => {
1410
1587
  // Note: use recomendation empty deploy cluster: node bin --dev cluster
1411
1588
  const env = options.dev ? 'development' : 'production';
1412
1589
  const baseCommand = options.dev ? 'node bin' : 'underpost';
@@ -1431,7 +1608,7 @@ EOF
1431
1608
  * @param {Object} options - The default underpost runner options for customizing workflow
1432
1609
  * @memberof UnderpostRun
1433
1610
  */
1434
- 'sync-replica': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
1611
+ 'sync-replica': async (path, options = DEFAULT_OPTION) => {
1435
1612
  const env = options.dev ? 'development' : 'production';
1436
1613
  const baseCommand = options.dev ? 'node bin' : 'underpost';
1437
1614
 
@@ -1462,10 +1639,10 @@ EOF
1462
1639
  * @param {Object} options - The default underpost runner options for customizing workflow
1463
1640
  * @memberof UnderpostRun
1464
1641
  */
1465
- 'tf-vae-test': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
1642
+ 'tf-vae-test': async (path, options = DEFAULT_OPTION) => {
1466
1643
  const { underpostRoot } = options;
1467
1644
  const podName = 'tf-vae-test';
1468
- await UnderpostRun.RUNNERS['deploy-job']('', {
1645
+ await Underpost.run.CALL('deploy-job', '', {
1469
1646
  podName,
1470
1647
  // volumeMountPath: '/custom_images',
1471
1648
  // volumeHostPath: '/home/dd/engine/src/client/public/cyberia/assets/skin',
@@ -1503,7 +1680,7 @@ EOF
1503
1680
  * @param {Object} options - The default underpost runner options for customizing workflow
1504
1681
  * @memberof UnderpostRun
1505
1682
  */
1506
- 'spark-template': (path, options = UnderpostRun.DEFAULT_OPTION) => {
1683
+ 'spark-template': (path, options = DEFAULT_OPTION) => {
1507
1684
  const dir = '/home/dd/spark-template';
1508
1685
  shellExec(`sudo rm -rf ${dir}`);
1509
1686
  shellCd('/home/dd');
@@ -1530,7 +1707,7 @@ EOF
1530
1707
  * @param {Object} options - The default underpost runner options for customizing workflow
1531
1708
  * @memberof UnderpostRun
1532
1709
  */
1533
- rmi: (path, options = UnderpostRun.DEFAULT_OPTION) => {
1710
+ rmi: (path, options = DEFAULT_OPTION) => {
1534
1711
  shellExec(`podman rmi $(podman images -qa) --force`);
1535
1712
  },
1536
1713
  /**
@@ -1540,7 +1717,7 @@ EOF
1540
1717
  * @param {Object} options - The default underpost runner options for customizing workflow
1541
1718
  * @memberof UnderpostRun
1542
1719
  */
1543
- kill: (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
1720
+ kill: (path = '', options = DEFAULT_OPTION) => {
1544
1721
  if (options.pid) return shellExec(`sudo kill -9 ${options.pid}`);
1545
1722
  for (const _path of path.split(',')) {
1546
1723
  if (_path.split('+')[1]) {
@@ -1559,7 +1736,7 @@ EOF
1559
1736
  * @param {Object} options - The default underpost runner options for customizing workflow
1560
1737
  * @memberof UnderpostRun
1561
1738
  */
1562
- secret: (path, options = UnderpostRun.DEFAULT_OPTION) => {
1739
+ secret: (path, options = DEFAULT_OPTION) => {
1563
1740
  const secretPath = path ? path : `/home/dd/engine/engine-private/conf/dd-cron/.env.production`;
1564
1741
  const command = options.dev
1565
1742
  ? `node bin secret underpost --create-from-file ${secretPath}`
@@ -1568,13 +1745,13 @@ EOF
1568
1745
  },
1569
1746
  /**
1570
1747
  * @method underpost-config
1571
- * @description Calls `UnderpostDeploy.API.configMap` to create a Kubernetes ConfigMap, defaulting to the 'production' environment.
1748
+ * @description Calls `Underpost.deploy.configMap` to create a Kubernetes ConfigMap, defaulting to the 'production' environment.
1572
1749
  * @param {string} path - The input value, identifier, or path for the operation (used as the optional configuration name/environment).
1573
1750
  * @param {Object} options - The default underpost runner options for customizing workflow
1574
1751
  * @memberof UnderpostRun
1575
1752
  */
1576
- 'underpost-config': (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
1577
- UnderpostDeploy.API.configMap(path ? path : 'production', options.namespace);
1753
+ 'underpost-config': (path = '', options = DEFAULT_OPTION) => {
1754
+ Underpost.deploy.configMap(path ? path : 'production', options.namespace);
1578
1755
  },
1579
1756
  /**
1580
1757
  * @method gpu-env
@@ -1583,7 +1760,7 @@ EOF
1583
1760
  * @param {Object} options - The default underpost runner options for customizing workflow
1584
1761
  * @memberof UnderpostRun
1585
1762
  */
1586
- 'gpu-env': (path, options = UnderpostRun.DEFAULT_OPTION) => {
1763
+ 'gpu-env': (path, options = DEFAULT_OPTION) => {
1587
1764
  shellExec(
1588
1765
  `node bin cluster --dev --reset && node bin cluster --dev --dedicated-gpu --kubeadm && kubectl get pods --all-namespaces -o wide -w`,
1589
1766
  );
@@ -1595,7 +1772,7 @@ EOF
1595
1772
  * @param {Object} options - The default underpost runner options for customizing workflow
1596
1773
  * @memberof UnderpostRun
1597
1774
  */
1598
- 'tf-gpu-test': (path, options = UnderpostRun.DEFAULT_OPTION) => {
1775
+ 'tf-gpu-test': (path, options = DEFAULT_OPTION) => {
1599
1776
  const { underpostRoot, namespace } = options;
1600
1777
  shellExec(`kubectl delete configmap tf-gpu-test-script -n ${namespace} --ignore-not-found`);
1601
1778
  shellExec(`kubectl delete pod tf-gpu-test-pod -n ${namespace} --ignore-not-found`);
@@ -1609,7 +1786,7 @@ EOF
1609
1786
  * @param {Object} options - The default underpost runner options for customizing workflow
1610
1787
  * @memberof UnderpostRun
1611
1788
  */
1612
- 'deploy-job': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
1789
+ 'deploy-job': async (path, options = DEFAULT_OPTION) => {
1613
1790
  const podName = options.podName || 'deploy-job';
1614
1791
  const volumeName = `${podName}-volume`;
1615
1792
  if (typeof options.args === 'string') options.args = options.args.split(',');
@@ -1646,7 +1823,7 @@ EOF
1646
1823
  ? 'Directory'
1647
1824
  : 'File';
1648
1825
 
1649
- const envs = UnderpostRootEnv.API.list();
1826
+ const envs = Underpost.env.list();
1650
1827
 
1651
1828
  const cmd = `kubectl apply -f - <<EOF
1652
1829
  apiVersion: ${apiVersion}
@@ -1689,14 +1866,14 @@ ${Object.keys(envs)
1689
1866
  .join('\n')}`}
1690
1867
  ${
1691
1868
  enableVolumeMount
1692
- ? UnderpostDeploy.API.volumeFactory([{ volumeMountPath, volumeName, volumeHostPath, volumeType, claimName }]).render
1869
+ ? Underpost.deploy.volumeFactory([{ volumeMountPath, volumeName, volumeHostPath, volumeType, claimName }]).render
1693
1870
  : ''
1694
1871
  }
1695
1872
  EOF`;
1696
1873
  shellExec(`kubectl delete pod ${podName} -n ${namespace} --ignore-not-found`);
1697
1874
  console.log(cmd);
1698
1875
  shellExec(cmd, { disableLog: true });
1699
- const successInstance = await UnderpostTest.API.statusMonitor(podName);
1876
+ const successInstance = await Underpost.test.statusMonitor(podName);
1700
1877
  if (successInstance) {
1701
1878
  options.on?.init ? await options.on.init() : null;
1702
1879
  shellExec(`kubectl logs -f ${podName} -n ${namespace}`);
@@ -1705,6 +1882,39 @@ EOF`;
1705
1882
  };
1706
1883
 
1707
1884
  static API = {
1885
+ /**
1886
+ * @method DEFAULT_OPTION
1887
+ * @description The default options for Underpost runners, including development mode, namespace, replicas, and underpost root path.
1888
+ * @memberof UnderpostRun
1889
+ * @static
1890
+ * @returns {Object} The default options object.
1891
+ */
1892
+ get DEFAULT_OPTION() {
1893
+ return DEFAULT_OPTION;
1894
+ },
1895
+ /**
1896
+ * @method RUNNERS
1897
+ * @description Retrieves the list of available runner IDs from the UnderpostRun class.
1898
+ * @memberof UnderpostRun
1899
+ * @returns {string[]} An array of runner IDs.
1900
+ */
1901
+ get RUNNERS() {
1902
+ return Object.keys(UnderpostRun.RUNNERS);
1903
+ },
1904
+
1905
+ /**
1906
+ * @method CALL
1907
+ * @description Executes a specified runner function from the UnderpostRun class with the provided path and options.
1908
+ * @param {string} runner - The name of the runner to execute.
1909
+ * @param {string} path - The input value, identifier, or path for the operation.
1910
+ * @param {Object} options - The default underpost runner options for customizing workflow
1911
+ * @memberof UnderpostRun
1912
+ * @returns {Promise<any>} The result of the runner execution.
1913
+ */
1914
+ async CALL(runner = '', path = '', options = DEFAULT_OPTION) {
1915
+ return await UnderpostRun.RUNNERS[runner](path, options);
1916
+ },
1917
+
1708
1918
  /**
1709
1919
  * @method callback
1710
1920
  * @description Initiates the execution of a specified CLI command (runner) with the given input value (`path`) and processed options.
@@ -1714,7 +1924,7 @@ EOF`;
1714
1924
  * @memberof UnderpostRun
1715
1925
  * @returns {Promise<any>} The result of the callback execution.
1716
1926
  */
1717
- async callback(runner, path, options = UnderpostRun.DEFAULT_OPTION) {
1927
+ async callback(runner, path, options = DEFAULT_OPTION) {
1718
1928
  try {
1719
1929
  const npmRoot = getNpmRootPath();
1720
1930
  const underpostRoot = options?.dev === true ? '.' : `${npmRoot}/underpost`;
@@ -1726,8 +1936,8 @@ EOF`;
1726
1936
  options.replicas = 1;
1727
1937
  options.npmRoot = npmRoot;
1728
1938
  logger.info('callback', { path, options });
1729
- if (!(runner in UnderpostRun.RUNNERS)) throw new Error(`Runner not found: ${runner}`);
1730
- const result = await UnderpostRun.RUNNERS[runner](path, options);
1939
+ if (!Underpost.run.RUNNERS.includes(runner)) throw new Error(`Runner not found: ${runner}`);
1940
+ const result = await Underpost.run.CALL(runner, path, options);
1731
1941
  return result;
1732
1942
  } catch (error) {
1733
1943
  console.log(error);