@underpostnet/underpost 2.99.1 → 2.99.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/cli/index.js CHANGED
@@ -557,6 +557,20 @@ program
557
557
  .option('--retry-count <count>', 'Sets HTTPProxy per-route retry count (e.g., 3).')
558
558
  .option('--retry-per-try-timeout <duration>', 'Sets HTTPProxy retry per-try timeout (e.g., "150ms").')
559
559
  .option('--disable-private-conf-update', 'Disables updates to private configuration during execution.')
560
+ .option('--logs', 'Streams logs during the runner execution.')
561
+ .option('--monitor-status <status>', 'Sets the status to monitor for pod/resource (default: "Running").')
562
+ .option(
563
+ '--monitor-status-kind-type <kind-type>',
564
+ 'Sets the Kubernetes resource kind type to monitor (default: "pods").',
565
+ )
566
+ .option(
567
+ '--monitor-status-delta-ms <milliseconds>',
568
+ 'Sets the polling interval in milliseconds for status monitoring (default: 1000).',
569
+ )
570
+ .option(
571
+ '--monitor-status-max-attempts <attempts>',
572
+ 'Sets the maximum number of status check attempts (default: 600).',
573
+ )
560
574
  .description('Runs specified scripts using various runners.')
561
575
  .action(Underpost.run.callback);
562
576
 
@@ -596,7 +610,13 @@ program
596
610
  .action(Underpost.lxd.callback);
597
611
 
598
612
  program
599
- .command('baremetal [workflow-id] [ip-address] [hostname] [ip-file-server] [ip-config] [netmask] [dns-server]')
613
+ .command('baremetal [workflow-id]')
614
+ .option('--ip-address <ip-address>', 'The IP address of the control server or the local machine.')
615
+ .option('--hostname <hostname>', 'The hostname of the target baremetal machine.')
616
+ .option('--ip-file-server <ip-file-server>', 'The IP address of the file server (NFS/TFTP).')
617
+ .option('--ip-config <ip-config>', 'IP configuration string for the baremetal machine.')
618
+ .option('--netmask <netmask>', 'Netmask of network.')
619
+ .option('--dns-server <dns-server>', 'DNS server IP address.')
600
620
  .option('--control-server-install', 'Installs the baremetal control server.')
601
621
  .option('--control-server-uninstall', 'Uninstalls the baremetal control server.')
602
622
  .option('--control-server-restart', 'Restarts the baremetal control server.')
package/src/cli/run.js CHANGED
@@ -80,6 +80,11 @@ const logger = loggerFactory(import.meta);
80
80
  * @property {string} user - The user to run as.
81
81
  * @property {string} pid - The process ID.
82
82
  * @property {boolean} disablePrivateConfUpdate - Whether to disable private configuration updates.
83
+ * @property {string} monitorStatus - The monitor status option.
84
+ * @property {string} monitorStatusKindType - The monitor status kind type option.
85
+ * @property {string} monitorStatusDeltaMs - The monitor status delta in milliseconds.
86
+ * @property {string} monitorStatusMaxAttempts - The maximum number of attempts for monitor status.
87
+ * @property {boolean} logs - Whether to enable logs.
83
88
  * @memberof UnderpostRun
84
89
  */
85
90
  const DEFAULT_OPTION = {
@@ -134,6 +139,11 @@ const DEFAULT_OPTION = {
134
139
  user: '',
135
140
  pid: '',
136
141
  disablePrivateConfUpdate: false,
142
+ monitorStatus: '',
143
+ monitorStatusKindType: '',
144
+ monitorStatusDeltaMs: '',
145
+ monitorStatusMaxAttempts: '',
146
+ logs: false,
137
147
  };
138
148
 
139
149
  /**
@@ -997,86 +1007,6 @@ EOF
997
1007
  shellExec(`${underpostRoot}/scripts/ip-info.sh ${path}`);
998
1008
  },
999
1009
 
1000
- /**
1001
- * @method monitor
1002
- * @description Monitors a specific pod (identified by `path`) for the existence of a file (`/await`), and performs conditional actions (like file copying and opening Firefox) when the file is removed.
1003
- * @param {string} path - The input value, identifier, or path for the operation (used as the name of the pod to monitor).
1004
- * @param {Object} options - The default underpost runner options for customizing workflow
1005
- * @memberof UnderpostRun
1006
- */
1007
- monitor: (path, options = DEFAULT_OPTION) => {
1008
- const pid = getTerminalPid();
1009
- logger.info('monitor pid', pid);
1010
- const checkPath = '/await';
1011
- const _monitor = async () => {
1012
- const result = Underpost.deploy.existsContainerFile({ podName: path, path: checkPath });
1013
- logger.info('monitor', result);
1014
- if (result === true) {
1015
- switch (path) {
1016
- case 'tf-vae-test':
1017
- {
1018
- const nameSpace = options.namespace;
1019
- const podName = path;
1020
- const basePath = '/home/dd';
1021
- const scriptPath = '/site/en/tutorials/generative/cvae.py';
1022
- // shellExec(
1023
- // `sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${scriptPath} ${basePath}/lab/src/${scriptPath
1024
- // .split('/')
1025
- // .pop()}`,
1026
- // );
1027
- // const file = fs.readFileSync(`${basePath}/lab/src/${scriptPath.split('/').pop()}`, 'utf8');
1028
- // fs.writeFileSync(
1029
- // `${basePath}/lab/src/${scriptPath.split('/').pop()}`,
1030
- // file.replace(
1031
- // `import time`,
1032
- // `import time
1033
- // print('=== SCRIPT UPDATE TEST ===')`,
1034
- // ),
1035
- // 'utf8',
1036
- // );
1037
- shellExec(
1038
- `sudo kubectl cp ${basePath}/lab/src/${scriptPath
1039
- .split('/')
1040
- .pop()} ${nameSpace}/${podName}:${basePath}/docs${scriptPath}`,
1041
- );
1042
- // shellExec(`sudo kubectl exec -i ${podName} -- sh -c "ipython ${basePath}/docs${scriptPath}"`);
1043
- shellExec(`sudo kubectl exec -i ${podName} -- sh -c "rm -rf ${checkPath}"`);
1044
-
1045
- {
1046
- const checkPath = `/latent_space_plot.png`;
1047
- const outsPaths = [];
1048
- logger.info('monitor', checkPath);
1049
- while (!Underpost.deploy.existsContainerFile({ podName, path: `/home/dd/docs${checkPath}` }))
1050
- await timer(1000);
1051
-
1052
- {
1053
- const toPath = `${basePath}/lab${checkPath}`;
1054
- outsPaths.push(toPath);
1055
- shellExec(`sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${checkPath} ${toPath}`);
1056
- }
1057
-
1058
- for (let i of range(1, 10)) {
1059
- i = `/image_at_epoch_${setPad(i, '0', 4)}.png`;
1060
- const toPath = `${basePath}/lab/${i}`;
1061
- outsPaths.push(toPath);
1062
- shellExec(`sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${i} ${toPath}`);
1063
- }
1064
- openTerminal(`firefox ${outsPaths.join(' ')}`, { single: true });
1065
- }
1066
- shellExec(`sudo kill -9 ${pid}`);
1067
- }
1068
- break;
1069
-
1070
- default:
1071
- break;
1072
- }
1073
- return;
1074
- }
1075
- await timer(1000);
1076
- _monitor();
1077
- };
1078
- _monitor();
1079
- },
1080
1010
  /**
1081
1011
  * @method db-client
1082
1012
  * @description Deploys and exposes the Adminer database client application (using `adminer:4.7.6-standalone` image) on the cluster.
@@ -1134,15 +1064,20 @@ EOF
1134
1064
  `git config user.email '${email}' && ` +
1135
1065
  `git config credential.interactive always &&` +
1136
1066
  `git config pull.rebase false`,
1067
+ {
1068
+ disableLog: true,
1069
+ silent: true,
1070
+ },
1137
1071
  );
1138
1072
 
1139
- console.log(
1140
- shellExec(`git config list`, { silent: true, stdout: true })
1141
- .replaceAll('user.email', 'user.email'.yellow)
1142
- .replaceAll(username, username.green)
1143
- .replaceAll('user.name', 'user.name'.yellow)
1144
- .replaceAll(email, email.green),
1145
- );
1073
+ if (options.logs)
1074
+ console.log(
1075
+ shellExec(`git config list`, { silent: true, stdout: true })
1076
+ .replaceAll('user.email', 'user.email'.yellow)
1077
+ .replaceAll(username, username.green)
1078
+ .replaceAll('user.name', 'user.name'.yellow)
1079
+ .replaceAll(email, email.green),
1080
+ );
1146
1081
  },
1147
1082
 
1148
1083
  /**
@@ -1370,7 +1305,11 @@ EOF
1370
1305
  });
1371
1306
  }
1372
1307
  await awaitDeployMonitor(true);
1373
- shellExec(`npm run dev-proxy ${deployId} ${subConf} ${host} ${_path}${options.tls ? ' tls' : ''}`);
1308
+ shellExec(
1309
+ `./node_modules/.bin/env-cmd -f .env.development node src/proxy proxy ${deployId} ${subConf} ${host} ${_path}${
1310
+ options.tls ? ' tls' : ''
1311
+ }`,
1312
+ );
1374
1313
  },
1375
1314
 
1376
1315
  /**
@@ -1640,15 +1579,74 @@ EOF
1640
1579
  * @memberof UnderpostRun
1641
1580
  */
1642
1581
  'tf-vae-test': async (path, options = DEFAULT_OPTION) => {
1643
- const { underpostRoot } = options;
1644
1582
  const podName = 'tf-vae-test';
1645
1583
  await Underpost.run.CALL('deploy-job', '', {
1584
+ logs: options.logs,
1646
1585
  podName,
1647
1586
  // volumeMountPath: '/custom_images',
1648
1587
  // volumeHostPath: '/home/dd/engine/src/client/public/cyberia/assets/skin',
1649
1588
  on: {
1650
1589
  init: async () => {
1651
- openTerminal(`node bin run --dev monitor ${podName}`);
1590
+ // const pid = getTerminalPid();
1591
+ // shellExec(`sudo kill -9 ${pid}`);
1592
+ (async () => {
1593
+ const nameSpace = options.namespace;
1594
+ const basePath = '/home/dd';
1595
+ const scriptPath = '/site/en/tutorials/generative/cvae.py';
1596
+
1597
+ const { close } = await (async () => {
1598
+ const checkAwaitPath = '/await';
1599
+ while (!Underpost.deploy.existsContainerFile({ podName, path: checkAwaitPath })) {
1600
+ logger.info('monitor', checkAwaitPath);
1601
+ await timer(1000);
1602
+ }
1603
+
1604
+ return {
1605
+ close: () => shellExec(`sudo kubectl exec -i ${podName} -- sh -c "rm -rf ${checkAwaitPath}"`),
1606
+ };
1607
+ })();
1608
+
1609
+ const localScriptPath = `${basePath}/lab/src/${scriptPath.split('/').pop()}`;
1610
+ if (!fs.existsSync(localScriptPath)) {
1611
+ throw new Error(`Local override script not found: ${localScriptPath}`);
1612
+ }
1613
+
1614
+ shellExec(`sudo kubectl cp ${localScriptPath} ${nameSpace}/${podName}:${basePath}/docs${scriptPath}`);
1615
+
1616
+ close();
1617
+
1618
+ {
1619
+ const checkPath = `/latent_space_plot.png`;
1620
+ const outsPaths = [];
1621
+ const labDir = `${basePath}/lab`;
1622
+
1623
+ logger.info('monitor', checkPath);
1624
+ {
1625
+ const checkAwaitPath = `/home/dd/docs${checkPath}`;
1626
+ while (!Underpost.deploy.existsContainerFile({ podName, path: checkAwaitPath })) {
1627
+ logger.info('waiting for', checkAwaitPath);
1628
+ await timer(1000);
1629
+ }
1630
+ }
1631
+
1632
+ {
1633
+ const toPath = `${labDir}${checkPath}`;
1634
+ outsPaths.push(toPath);
1635
+ shellExec(`sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${checkPath} ${toPath}`);
1636
+ }
1637
+
1638
+ for (let i of range(1, 10)) {
1639
+ const fileName = `image_at_epoch_${setPad(i, '0', 4)}.png`;
1640
+ const fromPath = `/${fileName}`;
1641
+ const toPath = `${labDir}/${fileName}`;
1642
+ outsPaths.push(toPath);
1643
+ shellExec(`sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${fromPath} ${toPath}`);
1644
+ }
1645
+
1646
+ openTerminal(`firefox ${outsPaths.join(' ')}`, { single: true });
1647
+ process.exit(0);
1648
+ }
1649
+ })();
1652
1650
  },
1653
1651
  },
1654
1652
  args: [
@@ -1873,10 +1871,16 @@ EOF`;
1873
1871
  shellExec(`kubectl delete pod ${podName} -n ${namespace} --ignore-not-found`);
1874
1872
  console.log(cmd);
1875
1873
  shellExec(cmd, { disableLog: true });
1876
- const successInstance = await Underpost.test.statusMonitor(podName);
1874
+ const successInstance = await Underpost.test.statusMonitor(
1875
+ podName,
1876
+ options.monitorStatus || 'Running',
1877
+ options.monitorStatusKindType || 'pods',
1878
+ options.monitorStatusDeltaMs || 1000,
1879
+ options.monitorStatusMaxAttempts || 600,
1880
+ );
1877
1881
  if (successInstance) {
1878
1882
  options.on?.init ? await options.on.init() : null;
1879
- shellExec(`kubectl logs -f ${podName} -n ${namespace}`);
1883
+ if (options.logs) shellExec(`kubectl logs -f ${podName} -n ${namespace}`, { async: true });
1880
1884
  }
1881
1885
  },
1882
1886
  };
package/src/cli/test.js CHANGED
@@ -59,7 +59,19 @@ class UnderpostTest {
59
59
  * @param {number} options.maxAttempts - The maximum number of attempts.
60
60
  * @memberof UnderpostTest
61
61
  */
62
- async callback(deployList = '', options = { itc: false, sh: false, logs: false }) {
62
+ async callback(
63
+ deployList = '',
64
+ options = {
65
+ itc: false,
66
+ sh: false,
67
+ logs: false,
68
+ podName: '',
69
+ podStatus: '',
70
+ kindType: '',
71
+ deltaMs: 1000,
72
+ maxAttempts: 60 * 5,
73
+ },
74
+ ) {
63
75
  if (
64
76
  options.podName &&
65
77
  typeof options.podName === 'string' &&