@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/LICENSE +1 -1
- package/README.md +30 -30
- package/bin/deploy.js +49 -3
- package/cli.md +42 -31
- package/jsconfig.json +4 -2
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +2 -2
- package/manifests/deployment/playwright/deployment.yaml +52 -0
- package/package.json +1 -1
- package/scripts/rocky-pwa.sh +2 -2
- package/scripts/ssl.sh +12 -6
- package/src/api/user/user.model.js +1 -0
- package/src/cli/baremetal.js +14 -12
- package/src/cli/deploy.js +6 -24
- package/src/cli/image.js +4 -4
- package/src/cli/index.js +21 -1
- package/src/cli/run.js +96 -92
- package/src/cli/test.js +13 -1
- package/src/client/components/core/Polyhedron.js +896 -7
- package/src/client/components/core/Translate.js +4 -0
- package/src/client/services/default/default.management.js +12 -2
- package/src/index.js +13 -1
- package/src/runtime/express/Express.js +3 -3
- package/src/server/conf.js +6 -4
- package/src/server/logger.js +11 -4
- package/src/server/process.js +27 -2
- package/src/server/proxy.js +4 -6
- package/src/server/tls.js +31 -26
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]
|
|
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
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
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(
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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' &&
|