@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/index.js CHANGED
@@ -1,16 +1,14 @@
1
1
  import dotenv from 'dotenv';
2
+ import fs from 'fs-extra';
3
+
2
4
  import { Command } from 'commander';
3
- import Underpost, { UnderpostRootEnv } from '../index.js';
4
5
  import { getNpmRootPath, getUnderpostRootPath, loadConf } from '../server/conf.js';
5
- import fs from 'fs-extra';
6
6
  import { commitData } from '../client/components/core/CommonJs.js';
7
- import UnderpostLxd from './lxd.js';
8
- import UnderpostBaremetal from './baremetal.js';
9
- import UnderpostRun from './run.js';
10
- import Dns from '../server/dns.js';
11
- import UnderpostStatic from './static.js';
7
+
8
+ import Underpost from '../index.js';
12
9
 
13
10
  const underpostRootPath = getUnderpostRootPath();
11
+
14
12
  fs.existsSync(`${underpostRootPath}/.env`)
15
13
  ? dotenv.config({ path: `${underpostRootPath}/.env`, override: true })
16
14
  : dotenv.config();
@@ -108,9 +106,8 @@ program
108
106
  if (fs.existsSync(`./engine-private/conf/${deployId}/.env.${env}`))
109
107
  dotenv.config({ path: `./engine-private/conf/${deployId}/.env.${env}`, override: true });
110
108
  else if (deployId === 'root') {
111
- deployId = UnderpostRootEnv.API.get('DEPLOY_ID');
109
+ deployId = Underpost.env.get('DEPLOY_ID');
112
110
  } else dotenv.config({ path: `./.env`, override: true });
113
-
114
111
  loadConf(deployId, subConf);
115
112
  });
116
113
 
@@ -157,7 +154,7 @@ program
157
154
  .option('--dev', 'Sets the development cli context')
158
155
 
159
156
  .description(`Manages static build of page, bundles, and documentation with comprehensive customization options.`)
160
- .action(UnderpostStatic.API.callback);
157
+ .action(Underpost.static.callback);
161
158
 
162
159
  program
163
160
  .command('config')
@@ -166,6 +163,8 @@ program
166
163
  .argument('[value]', 'Optional: The value to set for the configuration key.')
167
164
  .option('--plain', 'Prints the configuration value in plain text.')
168
165
  .option('--filter <keyword>', 'Filters the list by matching key or value (only for list operation).')
166
+ .option('--deploy-id <deploy-id>', 'Sets the deployment configuration ID for the operation context.')
167
+ .option('--build', 'Sets the build context for the operation.')
169
168
  .description(`Manages Underpost configurations using various operators.`)
170
169
  .action((...args) => Underpost.env[args[0]](args[1], args[2], args[3]));
171
170
 
@@ -190,7 +189,7 @@ program
190
189
  .option('--ban-both-add', 'Adds IP addresses to both banned ingress and egress lists.')
191
190
  .option('--ban-both-remove', 'Removes IP addresses from both banned ingress and egress lists.')
192
191
  .description('Displays the current public machine IP addresses.')
193
- .action(Dns.ipDispatcher);
192
+ .action(Underpost.dns.ipDispatcher);
194
193
 
195
194
  program
196
195
  .command('cluster')
@@ -262,6 +261,13 @@ program
262
261
  .option('--image <image>', 'Sets a custom image for deployments.')
263
262
  .option('--versions <deployment-versions>', 'A comma-separated list of custom deployment versions.')
264
263
  .option('--traffic <traffic-versions>', 'A comma-separated list of custom deployment traffic weights.')
264
+ .option(
265
+ '--timeout-response <duration>',
266
+ 'Sets HTTPProxy per-route response timeout (e.g., "1s", "300ms", "infinity").',
267
+ )
268
+ .option('--timeout-idle <duration>', 'Sets HTTPProxy per-route idle timeout (e.g., "10s", "infinity").')
269
+ .option('--retry-count <count>', 'Sets HTTPProxy per-route retry count (e.g., 3).')
270
+ .option('--retry-per-try-timeout <duration>', 'Sets HTTPProxy retry per-try timeout (e.g., "150ms").')
265
271
  .option('--disable-update-deployment', 'Disables updates to deployments.')
266
272
  .option('--disable-update-proxy', 'Disables updates to proxies.')
267
273
  .option('--disable-deployment-proxy', 'Disables proxies of deployments.')
@@ -393,28 +399,12 @@ program
393
399
  .description('Manages cluster metadata operations, including import and export.')
394
400
  .action(Underpost.db.clusterMetadataBackupCallback);
395
401
 
396
- program
397
- .command('script')
398
- .argument('operator', `The script operation to perform. Options: ${Object.keys(Underpost.script).join(', ')}.`)
399
- .argument('<script-name>', 'The name of the script to execute.')
400
- .argument('[script-value]', 'Optional: A literal command or a path to a script file.')
401
- .option('--itc', 'Executes the script within the container execution context.')
402
- .option('--itc-path', 'Specifies container path options for script execution.')
403
- .option('--ns <ns-name>', 'Optional: Specifies the namespace context for script execution.')
404
- .option('--pod-name <pod-name>', 'Optional: Specifies the pod name for script execution.')
405
- .description(
406
- 'Supports a variety of built-in Underpost global scripts, their preset lifecycle events, and arbitrary custom scripts.',
407
- )
408
- .action((...args) => Underpost.script[args[0]](args[1], args[2], args[3]));
409
-
410
402
  program
411
403
  .command('cron')
412
404
  .argument('[deploy-list]', 'A comma-separated list of deployment IDs (e.g., "default-a,default-b").')
413
405
  .argument(
414
406
  '[job-list]',
415
- `A comma-separated list of job IDs. Options: ${Object.keys(Underpost.cron).join(
416
- ', ',
417
- )}. Defaults to all available jobs.`,
407
+ `A comma-separated list of job IDs. Options: ${Underpost.cron.getJobsIDs()}. Defaults to all available jobs.`,
418
408
  )
419
409
  .option('--init-pm2-cronjobs', 'Initializes PM2 cron jobs from configuration for the specified deployment IDs.')
420
410
  .option('--git', 'Uploads cron job configurations to GitHub.')
@@ -461,6 +451,14 @@ program
461
451
  .option('--type <type>', 'Sets a custom monitor type.')
462
452
  .option('--sync', 'Synchronizes with current proxy deployments and traffic configurations.')
463
453
  .option('--namespace <namespace>', 'Sets the Kubernetes namespace for the deployment. Defaults to "default".')
454
+ .option('--timeout-response <duration>', 'Sets HTTPProxy per-route response timeout (e.g., "5s").')
455
+ .option('--timeout-idle <duration>', 'Sets HTTPProxy per-route idle timeout (e.g., "10s", "infinity").')
456
+ .option('--retry-count <count>', 'Sets HTTPProxy per-route retry count (e.g., 3).')
457
+ .option('--retry-per-try-timeout <duration>', 'Sets HTTPProxy retry per-try timeout (e.g., "150ms").')
458
+ .option('--disable-private-conf-update', 'Disables updates to private configuration during execution.')
459
+ .option('--versions <deployment-versions>', 'Specifies the deployment versions to monitor. eg. "blue,green", "green"')
460
+ .option('--ready-deployment', 'Run in ready deployment monitor mode.')
461
+ .option('--promote', 'Promotes the deployment after monitoring.')
464
462
  .description('Manages health server monitoring for specified deployments.')
465
463
  .action(Underpost.monitor.callback);
466
464
 
@@ -491,7 +489,7 @@ program
491
489
 
492
490
  program
493
491
  .command('run')
494
- .argument('<runner-id>', `The runner ID to run. Options: ${Object.keys(UnderpostRun.RUNNERS).join(', ')}.`)
492
+ .argument('<runner-id>', `The runner ID to run. Options: ${Underpost.run.RUNNERS}.`)
495
493
  .argument('[path]', 'The input value, identifier, or path for the operation.')
496
494
  .option('--cmd <command-list>', 'Comma-separated list of commands to execute.')
497
495
  .option('--args <args-array>', 'Array of arguments to pass to the command.')
@@ -551,8 +549,16 @@ program
551
549
  .option('--hosts <hosts>', 'Comma-separated list of hosts for the runner execution.')
552
550
  .option('--instance-id <instance-id>', 'Sets instance id context for the runner execution.')
553
551
  .option('--pid <process-id>', 'Sets process id context for the runner execution.')
552
+ .option(
553
+ '--timeout-response <duration>',
554
+ 'Sets HTTPProxy per-route response timeout (e.g., "1s", "300ms", "infinity").',
555
+ )
556
+ .option('--timeout-idle <duration>', 'Sets HTTPProxy per-route idle timeout (e.g., "10s", "infinity").')
557
+ .option('--retry-count <count>', 'Sets HTTPProxy per-route retry count (e.g., 3).')
558
+ .option('--retry-per-try-timeout <duration>', 'Sets HTTPProxy retry per-try timeout (e.g., "150ms").')
559
+ .option('--disable-private-conf-update', 'Disables updates to private configuration during execution.')
554
560
  .description('Runs specified scripts using various runners.')
555
- .action(UnderpostRun.API.callback);
561
+ .action(Underpost.run.callback);
556
562
 
557
563
  program
558
564
  .command('lxd')
@@ -587,7 +593,7 @@ program
587
593
  .option('--deploy-id <deploy-id>', 'Sets the deployment ID context for LXD operations.')
588
594
  .option('--namespace <namespace>', 'Kubernetes namespace for LXD operations (defaults to "default").')
589
595
  .description('Manages LXD containers and virtual machines.')
590
- .action(UnderpostLxd.API.callback);
596
+ .action(Underpost.lxd.callback);
591
597
 
592
598
  program
593
599
  .command('baremetal [workflow-id] [ip-address] [hostname] [ip-file-server] [ip-config] [netmask] [dns-server]')
@@ -652,6 +658,6 @@ program
652
658
  .description(
653
659
  'Manages baremetal server operations, including installation, database setup, commissioning, and user management.',
654
660
  )
655
- .action(UnderpostBaremetal.API.callback);
661
+ .action(Underpost.baremetal.callback);
656
662
 
657
663
  export { program };
package/src/cli/lxd.js CHANGED
@@ -5,10 +5,10 @@
5
5
  */
6
6
 
7
7
  import { getNpmRootPath } from '../server/conf.js';
8
- import { getLocalIPv4Address } from '../server/dns.js';
9
8
  import { pbcopy, shellExec } from '../server/process.js';
10
9
  import fs from 'fs-extra';
11
10
  import { loggerFactory } from '../server/logger.js';
11
+ import Underpost from '../index.js';
12
12
 
13
13
  const logger = loggerFactory(import.meta);
14
14
 
@@ -83,7 +83,7 @@ class UnderpostLxd {
83
83
  shellExec(`sudo systemctl status snap.lxd.daemon`);
84
84
  const lxdPressedContent = fs
85
85
  .readFileSync(`${underpostRoot}/manifests/lxd/lxd-preseed.yaml`, 'utf8')
86
- .replaceAll(`127.0.0.1`, getLocalIPv4Address());
86
+ .replaceAll(`127.0.0.1`, Underpost.dns.getLocalIPv4Address());
87
87
  shellExec(`echo "${lxdPressedContent}" | lxd init --preseed`);
88
88
  shellExec(`lxc cluster list`);
89
89
  }
@@ -129,7 +129,7 @@ ipv6.address=none`);
129
129
  // Default to kubeadm if not K3s
130
130
  flag = ' -s -- --kubeadm';
131
131
  }
132
- await UnderpostLxd.API.runWorkflow({
132
+ await Underpost.lxd.runWorkflow({
133
133
  workflowId: 'engine',
134
134
  vmName: options.initVm,
135
135
  });
@@ -147,7 +147,7 @@ ipv6.address=none`);
147
147
  }
148
148
 
149
149
  if (options.workflowId) {
150
- await UnderpostLxd.API.runWorkflow({
150
+ await Underpost.lxd.runWorkflow({
151
151
  workflowId: options.workflowId,
152
152
  vmName: options.vmId,
153
153
  deployId: options.deployId,
@@ -201,7 +201,7 @@ ipv6.address=none`);
201
201
  const [vmName, ports] = options.expose.split(':');
202
202
  console.log({ vmName, ports });
203
203
  const protocols = ['tcp']; // udp
204
- const hostIp = getLocalIPv4Address();
204
+ const hostIp = Underpost.dns.getLocalIPv4Address();
205
205
  const vmIp = shellExec(
206
206
  `lxc list ${vmName} --format json | jq -r '.[0].state.network.enp5s0.addresses[] | select(.family=="inet") | .address'`,
207
207
  { stdout: true },
@@ -6,12 +6,10 @@
6
6
 
7
7
  import { loadReplicas, pathPortAssignmentFactory } from '../server/conf.js';
8
8
  import { loggerFactory } from '../server/logger.js';
9
- import UnderpostDeploy from './deploy.js';
10
9
  import axios from 'axios';
11
- import UnderpostRootEnv from './env.js';
12
10
  import fs from 'fs-extra';
13
11
  import { shellExec } from '../server/process.js';
14
- import { isInternetConnection } from '../server/dns.js';
12
+ import Underpost from '../index.js';
15
13
 
16
14
  const logger = loggerFactory(import.meta);
17
15
 
@@ -40,6 +38,13 @@ class UnderpostMonitor {
40
38
  * @param {string} [options.replicas='1'] - Number of replicas for the deployment. Defaults to 1.
41
39
  * @param {boolean} [options.sync=false] - Synchronize traffic switching with the deployment.
42
40
  * @param {string} [options.namespace='default'] - Kubernetes namespace for the deployment. Defaults to 'default'.
41
+ * @param {string} [options.timeoutResponse=''] - Timeout for server response checks.
42
+ * @param {string} [options.timeoutIdle=''] - Timeout for idle connections.
43
+ * @param {string} [options.retryCount=''] - Number of retry attempts for health checks.
44
+ * @param {string} [options.retryPerTryTimeout=''] - Timeout per retry attempt.
45
+ * @param {boolean} [options.promote=false] - Promote the deployment after monitoring.
46
+ * @param {boolean} [options.readyDeployment=false] - Monitor until the deployment is ready.
47
+ * @param {string} [options.versions=''] - Specific version of the deployment to monitor.
43
48
  * @param {object} [commanderOptions] - Options passed from the command line interface.
44
49
  * @param {object} [auxRouter] - Optional router configuration for the deployment.
45
50
  * @memberof UnderpostMonitor
@@ -55,6 +60,13 @@ class UnderpostMonitor {
55
60
  replicas: '1',
56
61
  sync: false,
57
62
  namespace: 'default',
63
+ timeoutResponse: '',
64
+ timeoutIdle: '',
65
+ retryCount: '',
66
+ retryPerTryTimeout: '',
67
+ promote: false,
68
+ readyDeployment: false,
69
+ versions: '',
58
70
  },
59
71
  commanderOptions,
60
72
  auxRouter,
@@ -63,17 +75,28 @@ class UnderpostMonitor {
63
75
  if (!options.replicas) options.replicas = '1';
64
76
  if (deployId === 'dd' && fs.existsSync(`./engine-private/deploy/dd.router`)) {
65
77
  for (const _deployId of fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8').split(','))
66
- UnderpostMonitor.API.callback(
78
+ Underpost.monitor.callback(
67
79
  _deployId.trim(),
68
80
  env,
69
81
  options,
70
82
  commanderOptions,
71
- await UnderpostDeploy.API.routerFactory(_deployId, env),
83
+ await Underpost.deploy.routerFactory(_deployId, env),
72
84
  );
73
85
  return;
74
86
  }
75
87
 
76
- const router = auxRouter ?? (await UnderpostDeploy.API.routerFactory(deployId, env));
88
+ if (options.readyDeployment) {
89
+ for (const version of options.versions.split(',')) {
90
+ (async () => {
91
+ await Underpost.deploy.monitorReadyRunner(deployId, env, version, [], options.namespace, 'underpost');
92
+ if (options.promote)
93
+ Underpost.deploy.switchTraffic(deployId, env, version, options.replicas, options.namespace, options);
94
+ })();
95
+ }
96
+ return;
97
+ }
98
+
99
+ const router = auxRouter ?? (await Underpost.deploy.routerFactory(deployId, env));
77
100
 
78
101
  const confServer = loadReplicas(
79
102
  deployId,
@@ -84,10 +107,10 @@ class UnderpostMonitor {
84
107
 
85
108
  let errorPayloads = [];
86
109
  if (options.sync === true) {
87
- const currentTraffic = UnderpostDeploy.API.getCurrentTraffic(deployId, { namespace: options.namespace });
88
- if (currentTraffic) UnderpostRootEnv.API.set(`${deployId}-${env}-traffic`, currentTraffic);
110
+ const currentTraffic = Underpost.deploy.getCurrentTraffic(deployId, { namespace: options.namespace });
111
+ if (currentTraffic) Underpost.env.set(`${deployId}-${env}-traffic`, currentTraffic);
89
112
  }
90
- let traffic = UnderpostRootEnv.API.get(`${deployId}-${env}-traffic`) ?? 'blue';
113
+ let traffic = Underpost.env.get(`${deployId}-${env}-traffic`) ?? 'blue';
91
114
  const maxAttempts = parseInt(
92
115
  Object.keys(pathPortAssignmentData)
93
116
  .map((host) => pathPortAssignmentData[host].length)
@@ -102,22 +125,15 @@ class UnderpostMonitor {
102
125
  traffic,
103
126
  });
104
127
 
105
- const switchTraffic = () => {
106
- if (traffic === 'blue') traffic = 'green';
107
- else traffic = 'blue';
108
- UnderpostRootEnv.API.set(`${deployId}-${env}-traffic`, traffic);
109
- const namespace = options.namespace;
110
- shellExec(
111
- `node bin deploy --info-router --build-manifest --traffic ${traffic} --replicas ${
112
- options.replicas
113
- } --namespace ${namespace} ${deployId} ${env}`,
114
- );
115
- shellExec(`sudo kubectl apply -f ./engine-private/conf/${deployId}/build/${env}/proxy.yaml -n ${namespace}`);
128
+ const switchTraffic = (targetTraffic) => {
129
+ const nextTraffic = targetTraffic ?? (traffic === 'blue' ? 'green' : 'blue');
130
+ // Delegate traffic switching to centralized deploy implementation so behavior is consistent
131
+ Underpost.deploy.switchTraffic(deployId, env, nextTraffic, options.replicas, options.namespace, options);
132
+ // Keep local traffic in sync with the environment
133
+ traffic = nextTraffic;
116
134
  };
117
135
 
118
136
  const monitor = async (reject) => {
119
- if (UnderpostRootEnv.API.get(`monitor-init-callback-script`))
120
- shellExec(UnderpostRootEnv.API.get(`monitor-init-callback-script`));
121
137
  const currentTimestamp = new Date().getTime();
122
138
  errorPayloads = errorPayloads.filter((e) => currentTimestamp - e.timestamp < 60 * 1000 * 5);
123
139
  logger.info(`[${deployId}-${env}] Check server health`);
@@ -125,19 +141,12 @@ class UnderpostMonitor {
125
141
  for (const instance of pathPortAssignmentData[host]) {
126
142
  const { port, path } = instance;
127
143
  if (path.match('peer') || path.match('socket')) continue;
128
- let urlTest = `http://localhost:${port}${path}`;
129
- switch (options.type) {
130
- case 'remote':
131
- case 'blue-green':
132
- urlTest = `https://${host}${path}`;
133
- break;
134
-
135
- default:
136
- break;
144
+ const urlTest = `http${env === 'development' ? '' : 's'}://${host}${path}`;
145
+ if (env === 'development') {
146
+ const { renderHosts } = Underpost.deploy.etcHostFactory([host]);
147
+ logger.info('renderHosts', renderHosts);
137
148
  }
138
- // logger.info('Test instance', urlTest);
139
149
  await axios.get(urlTest, { timeout: 10000 }).catch((error) => {
140
- // console.log(error);
141
150
  const errorPayload = {
142
151
  urlTest,
143
152
  host,
@@ -152,39 +161,29 @@ class UnderpostMonitor {
152
161
  if (errorPayload.status !== 404) {
153
162
  errorPayloads.push(errorPayload);
154
163
  if (errorPayloads.length >= maxAttempts) {
155
- const message = JSON.stringify(errorPayloads, null, 4);
156
164
  logger.error(
157
165
  `Deployment ${deployId} ${env} has been reached max attempts error payloads`,
158
166
  errorPayloads,
159
167
  );
160
168
  switch (options.type) {
161
169
  case 'blue-green':
162
- {
163
- const confServer = JSON.parse(
164
- fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'),
165
- );
170
+ default: {
171
+ const confServer = JSON.parse(
172
+ fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'),
173
+ );
166
174
 
167
- const namespace = options.namespace;
168
- UnderpostDeploy.API.configMap(env, namespace);
175
+ const namespace = options.namespace;
176
+ Underpost.deploy.configMap(env, namespace);
169
177
 
170
- for (const host of Object.keys(confServer)) {
171
- shellExec(`sudo kubectl delete HTTPProxy ${host} -n ${namespace} --ignore-not-found`);
172
- }
173
- shellExec(
174
- `sudo kubectl rollout restart deployment/${deployId}-${env}-${traffic} -n ${namespace}`,
175
- );
176
-
177
- switchTraffic();
178
+ for (const host of Object.keys(confServer)) {
179
+ shellExec(`sudo kubectl delete HTTPProxy ${host} -n ${namespace} --ignore-not-found`);
178
180
  }
181
+ shellExec(
182
+ `sudo kubectl rollout restart deployment/${deployId}-${env}-${traffic} -n ${namespace}`,
183
+ );
179
184
 
180
- break;
181
-
182
- case 'remote':
183
- break;
184
-
185
- default:
186
- if (reject) reject(message);
187
- else throw new Error(message);
185
+ switchTraffic();
186
+ }
188
187
  }
189
188
  errorPayloads = [];
190
189
  }
@@ -201,24 +200,29 @@ class UnderpostMonitor {
201
200
  let monitorTrafficName;
202
201
  let monitorPodName;
203
202
  const monitorCallBack = (resolve, reject) => {
204
- const envMsTimeout = UnderpostRootEnv.API.get(`${deployId}-${env}-monitor-ms`);
203
+ if (env === 'development') {
204
+ const { renderHosts } = Underpost.deploy.etcHostFactory([]);
205
+ logger.info('renderHosts', renderHosts);
206
+ }
207
+ const envMsTimeout = Underpost.env.get(`${deployId}-${env}-monitor-ms`);
205
208
  setTimeout(
206
209
  async () => {
207
- const isOnline = await isInternetConnection();
210
+ const isOnline = await Underpost.dns.isInternetConnection();
208
211
  if (!isOnline) {
209
212
  logger.warn('No internet connection');
210
213
  monitorCallBack(resolve, reject);
211
214
  return;
212
215
  }
213
- switch (options.type) {
214
- case 'blue-green':
215
- {
216
+ if (!options.now)
217
+ switch (options.type) {
218
+ case 'blue-green':
219
+ default: {
216
220
  if (monitorTrafficName !== traffic) {
217
221
  monitorTrafficName = undefined;
218
222
  monitorPodName = undefined;
219
223
  }
220
224
  const checkDeploymentReadyStatus = async () => {
221
- const { ready, notReadyPods, readyPods } = await UnderpostDeploy.API.checkDeploymentReadyStatus(
225
+ const { ready, notReadyPods, readyPods } = await Underpost.deploy.checkDeploymentReadyStatus(
222
226
  deployId,
223
227
  env,
224
228
  traffic,
@@ -236,33 +240,24 @@ class UnderpostMonitor {
236
240
  return;
237
241
  }
238
242
  }
239
-
240
- break;
241
-
242
- default:
243
- break;
244
- }
245
- for (const monitorStatus of [
246
- { key: `monitor-input`, value: UnderpostRootEnv.API.get(`monitor-input`) },
247
- {
248
- key: `${deployId}-${env}-monitor-input`,
249
- value: UnderpostRootEnv.API.get(`${deployId}-${env}-monitor-input`),
250
- },
251
- ])
252
- switch (monitorStatus.value) {
253
- case 'pause':
254
- monitorCallBack(resolve, reject);
255
- return;
256
- case 'restart':
257
- UnderpostRootEnv.API.delete(monitorStatus.key);
258
- return reject();
259
- case 'stop':
260
- UnderpostRootEnv.API.delete(monitorStatus.key);
261
- return resolve();
262
- case 'blue-green-switch':
263
- UnderpostRootEnv.API.delete(monitorStatus.key);
264
- switchTraffic();
265
243
  }
244
+ const monitorKey = `${deployId}-${env}-monitor-input`;
245
+ const monitorValue = Underpost.env.get(monitorKey);
246
+ switch (monitorValue) {
247
+ case 'pause':
248
+ monitorCallBack(resolve, reject);
249
+ return;
250
+ case 'restart':
251
+ case 'stop':
252
+ case 'blue-green-switch':
253
+ Underpost.env.delete(monitorKey);
254
+ case 'restart':
255
+ return reject();
256
+ case 'stop':
257
+ return resolve();
258
+ case 'blue-green-switch':
259
+ switchTraffic();
260
+ }
266
261
  await monitor(reject);
267
262
  monitorCallBack(resolve, reject);
268
263
  return;
@@ -12,6 +12,7 @@ import fs from 'fs-extra';
12
12
  import { getNpmRootPath } from '../server/conf.js';
13
13
  import { Config } from '../server/conf.js';
14
14
  import { DefaultConf } from '../../conf.js';
15
+ import Underpost from '../index.js';
15
16
 
16
17
  dotenv.config();
17
18
 
@@ -134,8 +135,8 @@ class UnderpostRepository {
134
135
  }
135
136
  if (options.lastMsg) {
136
137
  if (options.copy) {
137
- pbcopy(UnderpostRepository.API.getLastCommitMsg(options.lastMsg - 1));
138
- } else console.log(UnderpostRepository.API.getLastCommitMsg(options.lastMsg - 1));
138
+ pbcopy(Underpost.repo.getLastCommitMsg(options.lastMsg - 1));
139
+ } else console.log(Underpost.repo.getLastCommitMsg(options.lastMsg - 1));
139
140
  return;
140
141
  }
141
142
  if (options.diff) {
@@ -145,7 +146,7 @@ class UnderpostRepository {
145
146
  return;
146
147
  }
147
148
  if (options.log) {
148
- const history = UnderpostRepository.API.getHistory(options.log);
149
+ const history = Underpost.repo.getHistory(options.log);
149
150
  const chainCmd = history
150
151
  .reverse()
151
152
  .map((commitData, i) => `${i === 0 ? '' : ' && '}git ${diffCmd} ${commitData.hash}`)
@@ -174,7 +175,7 @@ class UnderpostRepository {
174
175
  return;
175
176
  }
176
177
  if (commitType === 'reset') {
177
- if (options.copy) pbcopy(UnderpostRepository.API.getLastCommitMsg());
178
+ if (options.copy) pbcopy(Underpost.repo.getLastCommitMsg());
178
179
  shellExec(`cd ${repoPath} && git reset --soft HEAD~${isNaN(parseInt(subModule)) ? 1 : parseInt(subModule)}`);
179
180
  return;
180
181
  }
@@ -283,7 +284,7 @@ class UnderpostRepository {
283
284
 
284
285
  // Handle defaultConf operation
285
286
  if (options.defaultConf) {
286
- UnderpostRepository.API.updateDefaultConf(options);
287
+ Underpost.repo.updateDefaultConf(options);
287
288
  return resolve(true);
288
289
  }
289
290
 
@@ -439,7 +440,7 @@ class UnderpostRepository {
439
440
  const commandUntrack = `cd ${path} && git ls-files --others --exclude-standard`;
440
441
  const diffOutput = shellExec(command, { stdout: true, silent: true });
441
442
  const diffUntrackOutput = shellExec(commandUntrack, { stdout: true, silent: true });
442
- const deleteFiles = UnderpostRepository.API.getDeleteFiles(path);
443
+ const deleteFiles = Underpost.repo.getDeleteFiles(path);
443
444
  return diffOutput
444
445
  .toString()
445
446
  .split('\n')