underpost 2.8.82 → 2.8.85
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.development +1 -0
- package/.env.production +1 -0
- package/.env.test +1 -0
- package/.github/workflows/{ghpkg.yml → ghpkg.ci.yml} +5 -5
- package/.github/workflows/{npmpkg.yml → npmpkg.ci.yml} +5 -5
- package/.github/workflows/{publish.yml → publish.ci.yml} +1 -1
- package/.github/workflows/{pwa-microservices-template.page.yml → pwa-microservices-template-page.cd.yml} +1 -1
- package/.github/workflows/{pwa-microservices-template.test.yml → pwa-microservices-template-test.ci.yml} +1 -1
- package/.vscode/extensions.json +1 -1
- package/.vscode/settings.json +0 -44
- package/README.md +62 -2
- package/bin/build.js +15 -5
- package/bin/deploy.js +42 -92
- package/bin/file.js +33 -9
- package/bin/vs.js +12 -4
- package/cli.md +90 -42
- package/conf.js +1 -1
- package/docker-compose.yml +1 -1
- package/manifests/deployment/dd-template-development/deployment.yaml +2 -2
- package/manifests/deployment/tensorflow/tf-gpu-test.yaml +65 -0
- package/manifests/maas/device-scan.sh +3 -3
- package/manifests/maas/gpu-diag.sh +19 -0
- package/manifests/maas/maas-setup.sh +10 -10
- package/manifests/maas/snap-clean.sh +26 -0
- package/package.json +4 -6
- package/src/api/user/user.router.js +24 -1
- package/src/api/user/user.service.js +1 -4
- package/src/cli/baremetal.js +105 -73
- package/src/cli/cloud-init.js +21 -12
- package/src/cli/cluster.js +227 -133
- package/src/cli/deploy.js +34 -0
- package/src/cli/index.js +28 -1
- package/src/cli/monitor.js +8 -12
- package/src/cli/repository.js +7 -4
- package/src/cli/run.js +367 -0
- package/src/cli/ssh.js +32 -0
- package/src/cli/test.js +1 -1
- package/src/client/Default.index.js +7 -3
- package/src/client/components/core/Account.js +1 -1
- package/src/client/components/core/Chat.js +1 -1
- package/src/client/components/core/CommonJs.js +24 -22
- package/src/client/components/core/Content.js +1 -5
- package/src/client/components/core/Css.js +258 -18
- package/src/client/components/core/CssCore.js +8 -8
- package/src/client/components/core/Docs.js +14 -61
- package/src/client/components/core/DropDown.js +137 -82
- package/src/client/components/core/EventsUI.js +92 -5
- package/src/client/components/core/LoadingAnimation.js +8 -15
- package/src/client/components/core/Modal.js +597 -136
- package/src/client/components/core/NotificationManager.js +2 -2
- package/src/client/components/core/ObjectLayerEngine.js +638 -0
- package/src/client/components/core/Panel.js +158 -34
- package/src/client/components/core/PanelForm.js +12 -3
- package/src/client/components/core/Recover.js +1 -1
- package/src/client/components/core/Router.js +77 -17
- package/src/client/components/core/SocketIo.js +3 -3
- package/src/client/components/core/Translate.js +6 -2
- package/src/client/components/core/VanillaJs.js +0 -3
- package/src/client/components/core/Worker.js +3 -1
- package/src/client/components/default/CssDefault.js +17 -3
- package/src/client/components/default/MenuDefault.js +264 -45
- package/src/client/components/default/RoutesDefault.js +6 -12
- package/src/client/public/default/android-chrome-144x144.png +0 -0
- package/src/client/public/default/android-chrome-192x192.png +0 -0
- package/src/client/public/default/android-chrome-256x256.png +0 -0
- package/src/client/public/default/android-chrome-36x36.png +0 -0
- package/src/client/public/default/android-chrome-48x48.png +0 -0
- package/src/client/public/default/android-chrome-72x72.png +0 -0
- package/src/client/public/default/android-chrome-96x96.png +0 -0
- package/src/client/public/default/apple-touch-icon-114x114-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-114x114.png +0 -0
- package/src/client/public/default/apple-touch-icon-120x120-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-120x120.png +0 -0
- package/src/client/public/default/apple-touch-icon-144x144-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-144x144.png +0 -0
- package/src/client/public/default/apple-touch-icon-152x152-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-152x152.png +0 -0
- package/src/client/public/default/apple-touch-icon-180x180-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-180x180.png +0 -0
- package/src/client/public/default/apple-touch-icon-57x57-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-57x57.png +0 -0
- package/src/client/public/default/apple-touch-icon-60x60-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-60x60.png +0 -0
- package/src/client/public/default/apple-touch-icon-72x72-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-72x72.png +0 -0
- package/src/client/public/default/apple-touch-icon-76x76-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon-76x76.png +0 -0
- package/src/client/public/default/apple-touch-icon-precomposed.png +0 -0
- package/src/client/public/default/apple-touch-icon.png +0 -0
- package/src/client/public/default/assets/background/dark.jpg +0 -0
- package/src/client/public/default/assets/background/dark.svg +557 -0
- package/src/client/public/default/assets/logo/base-icon.png +0 -0
- package/src/client/public/default/assets/logo/underpost.gif +0 -0
- package/src/client/public/default/assets/mailer/api-user-check.png +0 -0
- package/src/client/public/default/assets/mailer/api-user-invalid-token.png +0 -0
- package/src/client/public/default/assets/mailer/api-user-recover.png +0 -0
- package/src/client/public/default/favicon-16x16.png +0 -0
- package/src/client/public/default/favicon-32x32.png +0 -0
- package/src/client/public/default/favicon.ico +0 -0
- package/src/client/public/default/mstile-144x144.png +0 -0
- package/src/client/public/default/mstile-150x150.png +0 -0
- package/src/client/public/default/mstile-310x150.png +0 -0
- package/src/client/public/default/mstile-310x310.png +0 -0
- package/src/client/public/default/mstile-70x70.png +0 -0
- package/src/client/public/default/safari-pinned-tab.svg +24 -0
- package/src/client/ssr/body/DefaultSplashScreen.js +2 -2
- package/src/index.js +34 -17
- package/src/monitor.js +24 -0
- package/src/runtime/lampp/Dockerfile +30 -39
- package/src/runtime/lampp/Lampp.js +11 -2
- package/src/server/client-build-docs.js +205 -0
- package/src/server/client-build.js +16 -166
- package/src/server/conf.js +18 -8
- package/src/server/process.js +16 -19
- package/src/server/valkey.js +102 -41
package/src/cli/index.js
CHANGED
|
@@ -4,9 +4,9 @@ import Underpost from '../index.js';
|
|
|
4
4
|
import { getNpmRootPath, getUnderpostRootPath, loadConf } from '../server/conf.js';
|
|
5
5
|
import fs from 'fs-extra';
|
|
6
6
|
import { commitData } from '../client/components/core/CommonJs.js';
|
|
7
|
-
import { shellExec } from '../server/process.js';
|
|
8
7
|
import UnderpostLxd from './lxd.js';
|
|
9
8
|
import UnderpostBaremetal from './baremetal.js';
|
|
9
|
+
import UnderpostRun from './run.js';
|
|
10
10
|
|
|
11
11
|
// Load environment variables from .env file
|
|
12
12
|
const underpostRootPath = getUnderpostRootPath();
|
|
@@ -112,6 +112,7 @@ program
|
|
|
112
112
|
.option('--mariadb', 'Initializes the cluster with a MariaDB statefulset.')
|
|
113
113
|
.option('--mysql', 'Initializes the cluster with a MySQL statefulset.')
|
|
114
114
|
.option('--mongodb', 'Initializes the cluster with a MongoDB statefulset.')
|
|
115
|
+
.option('--mongo-db-host <host>', 'Set custom mongo db host')
|
|
115
116
|
.option('--postgresql', 'Initializes the cluster with a PostgreSQL statefulset.')
|
|
116
117
|
.option('--mongodb4', 'Initializes the cluster with a MongoDB 4.4 service.')
|
|
117
118
|
.option('--valkey', 'Initializes the cluster with a Valkey service.')
|
|
@@ -128,6 +129,7 @@ program
|
|
|
128
129
|
.option('--info-capacity-pod', 'Displays the current machine capacity information per pod.')
|
|
129
130
|
.option('--pull-image', 'Sets an optional associated image to pull during initialization.')
|
|
130
131
|
.option('--init-host', 'Installs necessary Kubernetes node CLI tools (e.g., kind, kubeadm, docker, podman, helm).')
|
|
132
|
+
.option('--uninstall-host', 'Uninstalls all host components installed by init-host.')
|
|
131
133
|
.option('--config', 'Sets the base Kubernetes node configuration.')
|
|
132
134
|
.option('--worker', 'Sets the context for a worker node.')
|
|
133
135
|
.option('--chown', 'Sets the appropriate ownership for Kubernetes kubeconfig files.')
|
|
@@ -314,6 +316,31 @@ program
|
|
|
314
316
|
.description('Manages health server monitoring for specified deployments.')
|
|
315
317
|
.action(Underpost.monitor.callback);
|
|
316
318
|
|
|
319
|
+
// 'ssh' command: SSH management
|
|
320
|
+
program
|
|
321
|
+
.command('ssh')
|
|
322
|
+
.option('--generate', 'Generates new ssh credential and stores it in current private keys file storage.')
|
|
323
|
+
.description('Import and start ssh server and client based on current default deployment ID.')
|
|
324
|
+
.action(Underpost.ssh.callback);
|
|
325
|
+
|
|
326
|
+
// 'run' command: Run a script
|
|
327
|
+
program
|
|
328
|
+
.command('run')
|
|
329
|
+
.argument('<runner-id>', `The runner ID to run. Options: ${Object.keys(UnderpostRun.RUNNERS).join(', ')}.`)
|
|
330
|
+
.argument('[path]', 'The absolute or relative directory path where the script is located.')
|
|
331
|
+
.option('--command <command-array>', 'Array of commands to run.')
|
|
332
|
+
.option('--args <args-array>', 'Array of arguments to pass to the command.')
|
|
333
|
+
.option('--dev', 'Sets the development context environment for the script.')
|
|
334
|
+
.option('--pod-name <pod-name>', 'Optional: Specifies the pod name for test execution.')
|
|
335
|
+
.option('--volume-host-path <volume-host-path>', 'Optional: Specifies the volume host path for test execution.')
|
|
336
|
+
.option('--volume-mount-path <volume-mount-path>', 'Optional: Specifies the volume mount path for test execution.')
|
|
337
|
+
.option('--volume-type <volume-type>', 'Optional: Specifies the volume type for test execution.')
|
|
338
|
+
.option('--image-name <image-name>', 'Optional: Specifies the image name for test execution.')
|
|
339
|
+
.option('--container-name <container-name>', 'Optional: Specifies the container name for test execution.')
|
|
340
|
+
.option('--namespace <namespace>', 'Optional: Specifies the namespace for test execution.')
|
|
341
|
+
.description('Runs a script from the specified path.')
|
|
342
|
+
.action(UnderpostRun.API.callback);
|
|
343
|
+
|
|
317
344
|
// 'lxd' command: LXD management
|
|
318
345
|
program
|
|
319
346
|
.command('lxd')
|
package/src/cli/monitor.js
CHANGED
|
@@ -173,19 +173,15 @@ class UnderpostMonitor {
|
|
|
173
173
|
monitorTrafficName = undefined;
|
|
174
174
|
monitorPodName = undefined;
|
|
175
175
|
}
|
|
176
|
-
const cmd = `underpost config get container-status`;
|
|
177
176
|
const checkDeploymentReadyStatus = () => {
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
monitorPodName = NAME;
|
|
187
|
-
monitorTrafficName = `${traffic}`;
|
|
188
|
-
}
|
|
177
|
+
const { ready, notReadyPods, readyPods } = UnderpostDeploy.API.checkDeploymentReadyStatus(
|
|
178
|
+
deployId,
|
|
179
|
+
env,
|
|
180
|
+
traffic,
|
|
181
|
+
);
|
|
182
|
+
if (ready) {
|
|
183
|
+
monitorPodName = readyPods[0].NAME;
|
|
184
|
+
monitorTrafficName = `${traffic}`;
|
|
189
185
|
}
|
|
190
186
|
};
|
|
191
187
|
if (!monitorPodName) {
|
package/src/cli/repository.js
CHANGED
|
@@ -60,7 +60,7 @@ class UnderpostRepository {
|
|
|
60
60
|
},
|
|
61
61
|
|
|
62
62
|
push(repoPath = './', gitUri = 'underpostnet/pwa-microservices-template', options = { f: false, g8: false }) {
|
|
63
|
-
const gExtension = options.g8 === true ? '.g8' : '.git';
|
|
63
|
+
const gExtension = options.g8 === true || options.G8 === true ? '.g8' : '.git';
|
|
64
64
|
shellExec(
|
|
65
65
|
`cd ${repoPath} && git push https://${process.env.GITHUB_TOKEN}@github.com/${gitUri}${gExtension}${
|
|
66
66
|
options?.f === true ? ' --force' : ''
|
|
@@ -71,9 +71,12 @@ class UnderpostRepository {
|
|
|
71
71
|
);
|
|
72
72
|
logger.info(
|
|
73
73
|
'commit url',
|
|
74
|
-
`http://github.com/${gitUri}
|
|
75
|
-
|
|
76
|
-
|
|
74
|
+
`http://github.com/${gitUri}${gExtension === '.g8' ? '.g8' : ''}/commit/${shellExec(
|
|
75
|
+
`cd ${repoPath} && git rev-parse --verify HEAD`,
|
|
76
|
+
{
|
|
77
|
+
stdout: true,
|
|
78
|
+
},
|
|
79
|
+
).trim()}`,
|
|
77
80
|
);
|
|
78
81
|
},
|
|
79
82
|
|
package/src/cli/run.js
ADDED
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
import { daemonProcess, getTerminalPid, openTerminal, pbcopy, shellCd, shellExec } from '../server/process.js';
|
|
2
|
+
import read from 'read';
|
|
3
|
+
import { getNpmRootPath } from '../server/conf.js';
|
|
4
|
+
import { loggerFactory } from '../server/logger.js';
|
|
5
|
+
import UnderpostTest from './test.js';
|
|
6
|
+
import fs from 'fs-extra';
|
|
7
|
+
import { range, setPad, timer } from '../client/components/core/CommonJs.js';
|
|
8
|
+
import UnderpostDeploy from './deploy.js';
|
|
9
|
+
import UnderpostRootEnv from './env.js';
|
|
10
|
+
|
|
11
|
+
const logger = loggerFactory(import.meta);
|
|
12
|
+
|
|
13
|
+
class UnderpostRun {
|
|
14
|
+
static DEFAULT_OPTION = {
|
|
15
|
+
dev: false,
|
|
16
|
+
podName: '',
|
|
17
|
+
volumeHostPath: '',
|
|
18
|
+
volumeMountPath: '',
|
|
19
|
+
imageName: '',
|
|
20
|
+
containerName: '',
|
|
21
|
+
namespace: '',
|
|
22
|
+
};
|
|
23
|
+
static RUNNERS = {
|
|
24
|
+
'spark-template': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
25
|
+
const dir = '/home/dd/spark-template';
|
|
26
|
+
shellExec(`sudo rm -rf ${dir}`);
|
|
27
|
+
shellCd('/home/dd');
|
|
28
|
+
|
|
29
|
+
// pbcopy(`cd /home/dd && sbt new underpostnet/spark-template.g8`);
|
|
30
|
+
// await read({ prompt: 'Command copy to clipboard, press enter to continue.\n' });
|
|
31
|
+
shellExec(`cd /home/dd && sbt new underpostnet/spark-template.g8 '--name=spark-template'`);
|
|
32
|
+
|
|
33
|
+
shellCd(dir);
|
|
34
|
+
|
|
35
|
+
shellExec(`git init && git add . && git commit -m "Base implementation"`);
|
|
36
|
+
shellExec(`chmod +x ./replace_params.sh`);
|
|
37
|
+
shellExec(`chmod +x ./build.sh`);
|
|
38
|
+
|
|
39
|
+
shellExec(`./replace_params.sh`);
|
|
40
|
+
shellExec(`./build.sh`);
|
|
41
|
+
|
|
42
|
+
shellCd('/home/dd/engine');
|
|
43
|
+
},
|
|
44
|
+
rmi: (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
45
|
+
shellExec(`podman rmi $(podman images -qa) --force`);
|
|
46
|
+
},
|
|
47
|
+
kill: (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
48
|
+
shellExec(`sudo kill -9 $(lsof -t -i:${path})`);
|
|
49
|
+
},
|
|
50
|
+
secret: (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
51
|
+
shellExec(
|
|
52
|
+
`underpost secret underpost --create-from-file ${
|
|
53
|
+
path ? path : `/home/dd/engine/engine-private/conf/dd-cron/.env.production`
|
|
54
|
+
}`,
|
|
55
|
+
);
|
|
56
|
+
},
|
|
57
|
+
'gpu-env': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
58
|
+
shellExec(
|
|
59
|
+
`node bin cluster --dev --reset && node bin cluster --dev --dedicated-gpu --kubeadm && kubectl get pods --all-namespaces -o wide -w`,
|
|
60
|
+
);
|
|
61
|
+
},
|
|
62
|
+
'tf-gpu-test': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
63
|
+
const { underpostRoot } = options;
|
|
64
|
+
shellExec(`kubectl delete configmap tf-gpu-test-script`);
|
|
65
|
+
shellExec(`kubectl delete pod tf-gpu-test-pod`);
|
|
66
|
+
shellExec(`kubectl apply -f ${underpostRoot}/manifests/deployment/tensorflow/tf-gpu-test.yaml`);
|
|
67
|
+
},
|
|
68
|
+
'dev-cluster': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
69
|
+
const baseCommand = options.dev ? 'node bin' : 'underpost';
|
|
70
|
+
shellExec(`${baseCommand} cluster${options.dev ? ' --dev' : ''} --reset`);
|
|
71
|
+
shellExec(`${baseCommand} cluster${options.dev ? ' --dev' : ''}`);
|
|
72
|
+
shellExec(
|
|
73
|
+
`${baseCommand} cluster${options.dev ? ' --dev' : ''} --mongodb --mongo-db-host ${'127.0.0.1'} --pull-image`,
|
|
74
|
+
);
|
|
75
|
+
shellExec(`${baseCommand} cluster${options.dev ? ' --dev' : ''} --valkey --pull-image`);
|
|
76
|
+
shellExec(`${baseCommand} deploy --expose mongo`, { async: true });
|
|
77
|
+
shellExec(`${baseCommand} deploy --expose valkey`, { async: true });
|
|
78
|
+
},
|
|
79
|
+
'cyberia-ide': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
80
|
+
const baseCommand = options.dev ? 'node bin' : 'underpost';
|
|
81
|
+
shellExec(`${baseCommand} run ide /home/dd/cyberia-server`);
|
|
82
|
+
shellExec(`${baseCommand} run ide /home/dd/cyberia-client`);
|
|
83
|
+
},
|
|
84
|
+
'engine-ide': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
85
|
+
const baseCommand = options.dev ? 'node bin' : 'underpost';
|
|
86
|
+
shellExec(`${baseCommand} run ide /home/dd/engine`);
|
|
87
|
+
shellExec(`${baseCommand} run ide /home/dd/engine/engine-private`);
|
|
88
|
+
},
|
|
89
|
+
'template-deploy': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
90
|
+
const baseCommand = options.dev || true ? 'node bin' : 'underpost';
|
|
91
|
+
shellCd('/home/dd/engine');
|
|
92
|
+
shellExec(`git reset`);
|
|
93
|
+
shellExec(`${baseCommand} cmt . --empty ci package-pwa-microservices-template`);
|
|
94
|
+
shellExec(`${baseCommand} push . underpostnet/engine`);
|
|
95
|
+
},
|
|
96
|
+
'ssh-deploy': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
97
|
+
const baseCommand = options.dev || true ? 'node bin' : 'underpost';
|
|
98
|
+
shellCd('/home/dd/engine');
|
|
99
|
+
shellExec(`git reset`);
|
|
100
|
+
shellExec(`${baseCommand} cmt . --empty cd ssh-${path}`);
|
|
101
|
+
shellExec(`${baseCommand} push . underpostnet/engine`);
|
|
102
|
+
},
|
|
103
|
+
ide: (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
104
|
+
const { underpostRoot } = options;
|
|
105
|
+
shellExec(`node ${underpostRoot}/bin/vs ${path}`);
|
|
106
|
+
},
|
|
107
|
+
monitor: (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
108
|
+
const pid = getTerminalPid();
|
|
109
|
+
logger.info('monitor pid', pid);
|
|
110
|
+
const checkPath = '/await';
|
|
111
|
+
const _monitor = async () => {
|
|
112
|
+
const result = UnderpostDeploy.API.existsContainerFile({ podName: path, path: checkPath });
|
|
113
|
+
logger.info('monitor', result);
|
|
114
|
+
if (result === true) {
|
|
115
|
+
switch (path) {
|
|
116
|
+
case 'tf-vae-test':
|
|
117
|
+
{
|
|
118
|
+
const nameSpace = 'default';
|
|
119
|
+
const podName = path;
|
|
120
|
+
const basePath = '/home/dd';
|
|
121
|
+
const scriptPath = '/site/en/tutorials/generative/cvae.py';
|
|
122
|
+
// shellExec(
|
|
123
|
+
// `sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${scriptPath} ${basePath}/lab/src/${scriptPath
|
|
124
|
+
// .split('/')
|
|
125
|
+
// .pop()}`,
|
|
126
|
+
// );
|
|
127
|
+
// const file = fs.readFileSync(`${basePath}/lab/src/${scriptPath.split('/').pop()}`, 'utf8');
|
|
128
|
+
// fs.writeFileSync(
|
|
129
|
+
// `${basePath}/lab/src/${scriptPath.split('/').pop()}`,
|
|
130
|
+
// file.replace(
|
|
131
|
+
// `import time`,
|
|
132
|
+
// `import time
|
|
133
|
+
// print('=== SCRIPT UPDATE TEST ===')`,
|
|
134
|
+
// ),
|
|
135
|
+
// 'utf8',
|
|
136
|
+
// );
|
|
137
|
+
shellExec(
|
|
138
|
+
`sudo kubectl cp ${basePath}/lab/src/${scriptPath
|
|
139
|
+
.split('/')
|
|
140
|
+
.pop()} ${nameSpace}/${podName}:${basePath}/docs${scriptPath}`,
|
|
141
|
+
);
|
|
142
|
+
// shellExec(`sudo kubectl exec -i ${podName} -- sh -c "ipython ${basePath}/docs${scriptPath}"`);
|
|
143
|
+
shellExec(`sudo kubectl exec -i ${podName} -- sh -c "rm -rf ${checkPath}"`);
|
|
144
|
+
|
|
145
|
+
{
|
|
146
|
+
const checkPath = `/latent_space_plot.png`;
|
|
147
|
+
const outsPaths = [];
|
|
148
|
+
logger.info('monitor', checkPath);
|
|
149
|
+
while (!UnderpostDeploy.API.existsContainerFile({ podName, path: `/home/dd/docs${checkPath}` }))
|
|
150
|
+
await timer(1000);
|
|
151
|
+
|
|
152
|
+
{
|
|
153
|
+
const toPath = `${basePath}/lab${checkPath}`;
|
|
154
|
+
outsPaths.push(toPath);
|
|
155
|
+
shellExec(`sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${checkPath} ${toPath}`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
for (let i of range(1, 10)) {
|
|
159
|
+
i = `/image_at_epoch_${setPad(i, '0', 4)}.png`;
|
|
160
|
+
const toPath = `${basePath}/lab/${i}`;
|
|
161
|
+
outsPaths.push(toPath);
|
|
162
|
+
shellExec(`sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${i} ${toPath}`);
|
|
163
|
+
}
|
|
164
|
+
openTerminal(`firefox ${outsPaths.join(' ')}`, { single: true });
|
|
165
|
+
}
|
|
166
|
+
shellExec(`sudo kill -9 ${pid}`);
|
|
167
|
+
}
|
|
168
|
+
break;
|
|
169
|
+
|
|
170
|
+
default:
|
|
171
|
+
break;
|
|
172
|
+
}
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
await timer(1000);
|
|
176
|
+
_monitor();
|
|
177
|
+
};
|
|
178
|
+
_monitor();
|
|
179
|
+
},
|
|
180
|
+
'db-client': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
181
|
+
const { underpostRoot } = options;
|
|
182
|
+
shellExec(`kubectl apply -k ${underpostRoot}/manifests/deployment/adminer/.`);
|
|
183
|
+
},
|
|
184
|
+
cluster: async (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
185
|
+
const deployList = fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8').split(',');
|
|
186
|
+
const env = 'production';
|
|
187
|
+
shellCd(`/home/dd/engine`);
|
|
188
|
+
shellExec(`underpost cluster --reset`);
|
|
189
|
+
await timer(5000);
|
|
190
|
+
shellExec(`underpost cluster --kubeadm`);
|
|
191
|
+
await timer(5000);
|
|
192
|
+
shellExec(`underpost dockerfile-pull-base-images --path /home/dd/engine/src/runtime/lampp --kubeadm-load`);
|
|
193
|
+
await timer(5000);
|
|
194
|
+
shellExec(`underpost cluster --kubeadm --pull-image --mongodb`);
|
|
195
|
+
await timer(5000);
|
|
196
|
+
shellExec(`underpost cluster --kubeadm --pull-image --mariadb`);
|
|
197
|
+
await timer(5000);
|
|
198
|
+
for (const deployId of deployList) {
|
|
199
|
+
shellExec(`underpost db ${deployId} --import --git`);
|
|
200
|
+
}
|
|
201
|
+
await timer(5000);
|
|
202
|
+
shellExec(`underpost cluster --kubeadm --pull-image --valkey`);
|
|
203
|
+
await timer(5000);
|
|
204
|
+
shellExec(`underpost cluster --kubeadm --contour`);
|
|
205
|
+
await timer(5000);
|
|
206
|
+
shellExec(`underpost cluster --kubeadm --cert-manager`);
|
|
207
|
+
for (const deployId of deployList) {
|
|
208
|
+
shellExec(`underpost deploy ${deployId} ${env} --kubeadm --cert`);
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
deploy: async (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
212
|
+
const deployId = path;
|
|
213
|
+
const currentTraffic = UnderpostDeploy.API.getCurrentTraffic(deployId);
|
|
214
|
+
const targetTraffic = currentTraffic === 'blue' ? 'green' : 'blue';
|
|
215
|
+
const env = 'production';
|
|
216
|
+
const ignorePods = UnderpostDeploy.API.get(`${deployId}-${env}-${targetTraffic}`).map((p) => p.NAME);
|
|
217
|
+
shellExec(`sudo kubectl rollout restart deployment/${deployId}-${env}-${targetTraffic}`);
|
|
218
|
+
|
|
219
|
+
let secondsElapsed = 0;
|
|
220
|
+
logger.info('Deployment init', { deployId, env, targetTraffic });
|
|
221
|
+
|
|
222
|
+
while (!UnderpostDeploy.API.checkDeploymentReadyStatus(deployId, env, targetTraffic, ignorePods).ready) {
|
|
223
|
+
await timer(1000);
|
|
224
|
+
secondsElapsed++;
|
|
225
|
+
logger.info(`Deployment in progress, seconds elapsed: ${secondsElapsed}`);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
logger.info(`Deployment ready, seconds elapsed: ${secondsElapsed}`);
|
|
229
|
+
|
|
230
|
+
UnderpostRootEnv.API.set(`${deployId}-${env}-traffic`, targetTraffic);
|
|
231
|
+
|
|
232
|
+
shellExec(
|
|
233
|
+
`node bin deploy --info-router --build-manifest --traffic ${targetTraffic} --replicas ${
|
|
234
|
+
options.replicas ? options.replicas : 1
|
|
235
|
+
} ${deployId} ${env}`,
|
|
236
|
+
);
|
|
237
|
+
shellExec(`sudo kubectl apply -f ./engine-private/conf/${deployId}/build/${env}/proxy.yaml`);
|
|
238
|
+
shellExec(`sudo kubectl rollout restart deployment/${deployId}-${env}-${currentTraffic}`);
|
|
239
|
+
},
|
|
240
|
+
'tf-vae-test': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
241
|
+
const { underpostRoot } = options;
|
|
242
|
+
const podName = 'tf-vae-test';
|
|
243
|
+
await UnderpostRun.RUNNERS['deploy-job']('', {
|
|
244
|
+
podName,
|
|
245
|
+
// volumeMountPath: '/custom_images',
|
|
246
|
+
// volumeHostPath: '/home/dd/engine/src/client/public/cyberia/assets/skin',
|
|
247
|
+
on: {
|
|
248
|
+
init: async () => {
|
|
249
|
+
openTerminal(`node bin run --dev monitor ${podName}`);
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
args: [
|
|
253
|
+
`pip install --upgrade \
|
|
254
|
+
nbconvert \
|
|
255
|
+
tensorflow-probability==0.23.0 \
|
|
256
|
+
imageio \
|
|
257
|
+
git+https://github.com/tensorflow/docs \
|
|
258
|
+
matplotlib \
|
|
259
|
+
"numpy<1.25,>=1.21"`,
|
|
260
|
+
'mkdir -p /home/dd',
|
|
261
|
+
'cd /home/dd',
|
|
262
|
+
'git clone https://github.com/tensorflow/docs.git',
|
|
263
|
+
'cd docs',
|
|
264
|
+
'jupyter nbconvert --to python site/en/tutorials/generative/cvae.ipynb',
|
|
265
|
+
`echo '' > /await`,
|
|
266
|
+
`echo '=== WAITING SCRIPT LAUNCH ==='`,
|
|
267
|
+
`while [ -f /await ]; do sleep 1; done`,
|
|
268
|
+
`echo '=== FINISHED ==='`,
|
|
269
|
+
daemonProcess(`ipython site/en/tutorials/generative/cvae.py`),
|
|
270
|
+
],
|
|
271
|
+
});
|
|
272
|
+
},
|
|
273
|
+
'deploy-job': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
274
|
+
const podName = options.podName || 'deploy-job';
|
|
275
|
+
const volumeName = `${podName}-volume`;
|
|
276
|
+
const args = (options.args ? options.args : path ? [`python ${path}`] : []).filter((c) => c.trim());
|
|
277
|
+
const imageName = options.imageName || 'nvcr.io/nvidia/tensorflow:24.04-tf2-py3';
|
|
278
|
+
const containerName = options.containerName || `${podName}-container`;
|
|
279
|
+
const gpuEnable = imageName.match('nvidia');
|
|
280
|
+
const runtimeClassName = gpuEnable ? 'nvidia' : '';
|
|
281
|
+
const namespace = options.namespace || 'default';
|
|
282
|
+
const volumeMountPath = options.volumeMountPath || path;
|
|
283
|
+
const volumeHostPath = options.volumeHostPath || path;
|
|
284
|
+
const enableVolumeMount = volumeHostPath && volumeMountPath;
|
|
285
|
+
|
|
286
|
+
if (options.volumeType === 'dev') options.volumeType = 'FileOrCreate';
|
|
287
|
+
const volumeType =
|
|
288
|
+
options.volumeType || (enableVolumeMount && fs.statSync(volumeHostPath).isDirectory()) ? 'Directory' : 'File';
|
|
289
|
+
|
|
290
|
+
const envs = UnderpostRootEnv.API.list();
|
|
291
|
+
|
|
292
|
+
const cmd = `kubectl apply -f - <<EOF
|
|
293
|
+
apiVersion: v1
|
|
294
|
+
kind: Pod
|
|
295
|
+
metadata:
|
|
296
|
+
name: ${podName}
|
|
297
|
+
namespace: ${namespace}
|
|
298
|
+
spec:
|
|
299
|
+
restartPolicy: Never
|
|
300
|
+
${runtimeClassName ? ` runtimeClassName: ${runtimeClassName}` : ''}
|
|
301
|
+
containers:
|
|
302
|
+
- name: ${containerName}
|
|
303
|
+
image: ${imageName}
|
|
304
|
+
imagePullPolicy: IfNotPresent
|
|
305
|
+
tty: true
|
|
306
|
+
stdin: true
|
|
307
|
+
command: ${JSON.stringify(options.command ? options.command : ['/bin/bash', '-c'])}
|
|
308
|
+
${
|
|
309
|
+
args.length > 0
|
|
310
|
+
? ` args:
|
|
311
|
+
- |
|
|
312
|
+
${args.map((arg) => ` ${arg}`).join('\n')}`
|
|
313
|
+
: ''
|
|
314
|
+
}
|
|
315
|
+
${`${
|
|
316
|
+
gpuEnable
|
|
317
|
+
? ` resources:
|
|
318
|
+
limits:
|
|
319
|
+
nvidia.com/gpu: '1'
|
|
320
|
+
`
|
|
321
|
+
: ''
|
|
322
|
+
} env:
|
|
323
|
+
${Object.keys(envs)
|
|
324
|
+
.map((key) => ({ key, value: typeof envs[key] === 'number' ? envs[key] : `"${envs[key]}"` }))
|
|
325
|
+
.concat(gpuEnable ? [{ key: 'NVIDIA_VISIBLE_DEVICES', value: 'all' }] : [])
|
|
326
|
+
.map((env) => ` - name: ${env.key}\n value: ${env.value}`)
|
|
327
|
+
.join('\n')}`}
|
|
328
|
+
${
|
|
329
|
+
enableVolumeMount
|
|
330
|
+
? `
|
|
331
|
+
volumeMounts:
|
|
332
|
+
- name: ${volumeName}
|
|
333
|
+
mountPath: ${volumeMountPath}
|
|
334
|
+
volumes:
|
|
335
|
+
- name: ${volumeName}
|
|
336
|
+
hostPath:
|
|
337
|
+
path: ${volumeHostPath}
|
|
338
|
+
type: ${volumeType}`
|
|
339
|
+
: ''
|
|
340
|
+
}
|
|
341
|
+
EOF`;
|
|
342
|
+
shellExec(`kubectl delete pod ${podName}`);
|
|
343
|
+
console.log(cmd);
|
|
344
|
+
shellExec(cmd, { disableLog: true });
|
|
345
|
+
const successInstance = await UnderpostTest.API.statusMonitor(podName);
|
|
346
|
+
if (successInstance) {
|
|
347
|
+
options.on?.init ? await options.on.init() : null;
|
|
348
|
+
shellExec(`kubectl logs -f ${podName}`);
|
|
349
|
+
}
|
|
350
|
+
},
|
|
351
|
+
};
|
|
352
|
+
static API = {
|
|
353
|
+
async callback(runner, path, options = UnderpostRun.DEFAULT_OPTION) {
|
|
354
|
+
const npmRoot = getNpmRootPath();
|
|
355
|
+
const underpostRoot = options?.dev === true ? '.' : `${npmRoot}/underpost`;
|
|
356
|
+
if (options.command) options.command = options.command.split(',');
|
|
357
|
+
if (options.args) options.args = options.args.split(',');
|
|
358
|
+
options.underpostRoot = underpostRoot;
|
|
359
|
+
options.npmRoot = npmRoot;
|
|
360
|
+
logger.info('callback', { path, options });
|
|
361
|
+
const result = await UnderpostRun.RUNNERS[runner](path, options);
|
|
362
|
+
return result;
|
|
363
|
+
},
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
export default UnderpostRun;
|
package/src/cli/ssh.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { getNpmRootPath } from '../server/conf.js';
|
|
2
|
+
import { shellExec } from '../server/process.js';
|
|
3
|
+
|
|
4
|
+
class UnderpostSSH {
|
|
5
|
+
static API = {
|
|
6
|
+
/**
|
|
7
|
+
* @method callback
|
|
8
|
+
* @param {object} options
|
|
9
|
+
* @param {boolean} options.generate - Generates new ssh credential and stores it in current private keys file storage.
|
|
10
|
+
* @description Import and start ssh server and client based on current default deployment ID.
|
|
11
|
+
*/
|
|
12
|
+
callback: async (
|
|
13
|
+
options = {
|
|
14
|
+
generate: false,
|
|
15
|
+
},
|
|
16
|
+
) => {
|
|
17
|
+
// only import + start
|
|
18
|
+
// node bin/deploy ssh root@<host> <password> import
|
|
19
|
+
|
|
20
|
+
// generate + import + start
|
|
21
|
+
// node bin/deploy ssh root@<host> <password>
|
|
22
|
+
|
|
23
|
+
shellExec(
|
|
24
|
+
`node bin/deploy ssh root@${process.env.DEFAULT_DEPLOY_HOST} ${process.env.DEFAULT_DEPLOY_PASSWORD ?? `''`}${
|
|
25
|
+
options.generate === true ? '' : ' import'
|
|
26
|
+
}`,
|
|
27
|
+
);
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default UnderpostSSH;
|
package/src/cli/test.js
CHANGED
|
@@ -94,7 +94,7 @@ class UnderpostTest {
|
|
|
94
94
|
const _monitor = async () => {
|
|
95
95
|
await timer(deltaMs);
|
|
96
96
|
const pods = UnderpostDeploy.API.get(podName, kindType);
|
|
97
|
-
|
|
97
|
+
let result = pods.find((p) => p.STATUS === status || (status === 'Running' && p.STATUS === 'Completed'));
|
|
98
98
|
logger.info(
|
|
99
99
|
`Testing pod ${podName}... ${result ? 1 : 0}/1 - elapsed time ${deltaMs * (index + 1)}s - attempt ${
|
|
100
100
|
index + 1
|
|
@@ -16,21 +16,25 @@ import { SocketIo } from './components/core/SocketIo.js';
|
|
|
16
16
|
import { SocketIoDefault } from './components/default/SocketIoDefault.js';
|
|
17
17
|
import { ElementsDefault } from './components/default/ElementsDefault.js';
|
|
18
18
|
import { Scroll } from './components/core/Scroll.js';
|
|
19
|
+
import { CssDefaultDark, CssDefaultLight } from './components/default/CssDefault.js';
|
|
19
20
|
|
|
20
21
|
const htmlMainBody = async () => {
|
|
21
|
-
return html`<span
|
|
22
|
+
return html`<span>Hello World!!</span>`;
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
window.onload = () =>
|
|
25
26
|
Worker.instance({
|
|
26
27
|
router: RouterDefault,
|
|
27
28
|
render: async () => {
|
|
28
|
-
await Css.loadThemes();
|
|
29
|
+
await Css.loadThemes([CssDefaultLight, CssDefaultDark]);
|
|
29
30
|
await TranslateCore.Init();
|
|
30
31
|
await TranslateDefault.Init();
|
|
31
32
|
await Responsive.Init();
|
|
32
33
|
await MenuDefault.Render({ htmlMainBody });
|
|
33
|
-
await SocketIo.Init({
|
|
34
|
+
await SocketIo.Init({
|
|
35
|
+
channels: ElementsDefault.Data,
|
|
36
|
+
path: `/`,
|
|
37
|
+
});
|
|
34
38
|
await SocketIoDefault.Init();
|
|
35
39
|
await LogInDefault();
|
|
36
40
|
await LogOutDefault();
|
|
@@ -44,7 +44,7 @@ const Account = {
|
|
|
44
44
|
{ model: 'email', id: `account-email`, rules: [{ type: 'isEmpty' }, { type: 'isEmail' }] },
|
|
45
45
|
{
|
|
46
46
|
model: 'password',
|
|
47
|
-
defaultValue: '
|
|
47
|
+
defaultValue: '#Changethis123',
|
|
48
48
|
id: `account-password`,
|
|
49
49
|
rules: [{ type: 'isStrongPassword' }],
|
|
50
50
|
},
|
|
@@ -822,70 +822,72 @@ const generateRandomPasswordSelection = (length) => {
|
|
|
822
822
|
|
|
823
823
|
const commitData = {
|
|
824
824
|
feat: {
|
|
825
|
-
description: '
|
|
825
|
+
description: 'New feature or enhancement (frontend, backend, API, or UX)',
|
|
826
826
|
title: 'Features',
|
|
827
827
|
emoji: '✨',
|
|
828
828
|
},
|
|
829
829
|
fix: {
|
|
830
|
-
description: '
|
|
830
|
+
description: 'Fix a bug',
|
|
831
831
|
title: 'Bug Fixes',
|
|
832
832
|
emoji: '🐛',
|
|
833
833
|
},
|
|
834
834
|
docs: {
|
|
835
|
-
description: 'Documentation
|
|
835
|
+
description: 'Documentation changes',
|
|
836
836
|
title: 'Documentation',
|
|
837
837
|
emoji: '📚',
|
|
838
838
|
},
|
|
839
839
|
style: {
|
|
840
|
-
description:
|
|
841
|
-
'Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)',
|
|
840
|
+
description: 'Formatting, whitespace, semicolons, code style',
|
|
842
841
|
title: 'Styles',
|
|
843
842
|
emoji: '💎',
|
|
844
843
|
},
|
|
845
844
|
refactor: {
|
|
846
|
-
description: '
|
|
845
|
+
description: 'Code refactor.',
|
|
847
846
|
title: 'Code Refactoring',
|
|
848
847
|
emoji: '📦',
|
|
849
848
|
},
|
|
850
849
|
perf: {
|
|
851
|
-
description: '
|
|
850
|
+
description: 'Performance improvements across the stack.',
|
|
852
851
|
title: 'Performance Improvements',
|
|
853
852
|
emoji: '⚡️',
|
|
854
853
|
},
|
|
854
|
+
ci: {
|
|
855
|
+
description: 'CI pipeline changes (GitHub Actions, runners, caching)',
|
|
856
|
+
title: 'Continuous Integration',
|
|
857
|
+
emoji: '⚙️',
|
|
858
|
+
},
|
|
855
859
|
cd: {
|
|
856
|
-
description:
|
|
857
|
-
'Changes to our Continuous Delivery configuration files and scripts (example scopes: Jenkins, Spinnaker, ArgoCD)',
|
|
860
|
+
description: 'CD / deployment changes (Remote ssh deployment scripts)',
|
|
858
861
|
title: 'Continuous Delivery',
|
|
859
862
|
emoji: '🚀',
|
|
860
863
|
},
|
|
861
|
-
|
|
862
|
-
description: '
|
|
863
|
-
title: '
|
|
864
|
-
emoji: '
|
|
864
|
+
infra: {
|
|
865
|
+
description: 'Infrastructure changes (MAAS, LXD, cloud infra, networking, provisioning).',
|
|
866
|
+
title: 'Infrastructure',
|
|
867
|
+
emoji: '🏗️',
|
|
865
868
|
},
|
|
866
869
|
build: {
|
|
867
|
-
description: '
|
|
870
|
+
description: 'Build system or dependency changes (tooling, bundler, build scripts).',
|
|
868
871
|
title: 'Builds',
|
|
869
872
|
emoji: '🛠',
|
|
870
873
|
},
|
|
871
|
-
|
|
872
|
-
description:
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
emoji: '⚙️',
|
|
874
|
+
test: {
|
|
875
|
+
description: 'Unit or integration tests added/updated, test helpers, flake fixes.',
|
|
876
|
+
title: 'Tests',
|
|
877
|
+
emoji: '🚨',
|
|
876
878
|
},
|
|
877
879
|
chore: {
|
|
878
|
-
description: "Other changes that don't modify src or
|
|
880
|
+
description: "Other changes that don't modify src or tests (automation, housekeeping).",
|
|
879
881
|
title: 'Chores',
|
|
880
882
|
emoji: '♻️',
|
|
881
883
|
},
|
|
882
884
|
revert: {
|
|
883
|
-
description: '
|
|
885
|
+
description: 'Revert a previous commit or change.',
|
|
884
886
|
title: 'Reverts',
|
|
885
887
|
emoji: '🗑',
|
|
886
888
|
},
|
|
887
889
|
backup: {
|
|
888
|
-
description: '
|
|
890
|
+
description: 'Backups, snapshotting, restore scripts, or backup docs.',
|
|
889
891
|
title: 'Backups',
|
|
890
892
|
emoji: '💾',
|
|
891
893
|
},
|