underpost 2.8.82 → 2.8.84

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/run.js ADDED
@@ -0,0 +1,262 @@
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
+
10
+ const logger = loggerFactory(import.meta);
11
+
12
+ class UnderpostRun {
13
+ static DEFAULT_OPTION = {
14
+ dev: false,
15
+ podName: '',
16
+ volumeHostPath: '',
17
+ volumeMountPath: '',
18
+ imageName: '',
19
+ containerName: '',
20
+ namespace: '',
21
+ };
22
+ static RUNNERS = {
23
+ 'spark-template': (path, options = UnderpostRun.DEFAULT_OPTION) => {
24
+ const dir = '/home/dd/spark-template';
25
+ shellExec(`sudo rm -rf ${dir}`);
26
+ shellCd('/home/dd');
27
+
28
+ // pbcopy(`cd /home/dd && sbt new underpostnet/spark-template.g8`);
29
+ // await read({ prompt: 'Command copy to clipboard, press enter to continue.\n' });
30
+ shellExec(`cd /home/dd && sbt new underpostnet/spark-template.g8 '--name=spark-template'`);
31
+
32
+ shellCd(dir);
33
+
34
+ shellExec(`git init && git add . && git commit -m "Base implementation"`);
35
+ shellExec(`chmod +x ./replace_params.sh`);
36
+ shellExec(`chmod +x ./build.sh`);
37
+
38
+ shellExec(`./replace_params.sh`);
39
+ shellExec(`./build.sh`);
40
+
41
+ shellCd('/home/dd/engine');
42
+ },
43
+ rmi: (path, options = UnderpostRun.DEFAULT_OPTION) => {
44
+ shellExec(`podman rmi $(podman images -qa) --force`);
45
+ },
46
+ kill: (path, options = UnderpostRun.DEFAULT_OPTION) => {
47
+ shellExec(`sudo kill -9 $(lsof -t -i:${path})`);
48
+ },
49
+ secret: (path, options = UnderpostRun.DEFAULT_OPTION) => {
50
+ shellExec(
51
+ `underpost secret underpost --create-from-file ${
52
+ path ? path : `/home/dd/engine/engine-private/conf/dd-cron/.env.production`
53
+ }`,
54
+ );
55
+ },
56
+ 'gpu-env': (path, options = UnderpostRun.DEFAULT_OPTION) => {
57
+ shellExec(
58
+ `node bin cluster --dev --reset && node bin cluster --dev --dedicated-gpu --kubeadm && kubectl get pods --all-namespaces -o wide -w`,
59
+ );
60
+ },
61
+ 'tf-gpu-test': (path, options = UnderpostRun.DEFAULT_OPTION) => {
62
+ const { underpostRoot } = options;
63
+ shellExec(`kubectl delete configmap tf-gpu-test-script`);
64
+ shellExec(`kubectl delete pod tf-gpu-test-pod`);
65
+ shellExec(`kubectl apply -f ${underpostRoot}/manifests/deployment/tensorflow/tf-gpu-test.yaml`);
66
+ },
67
+ ide: (path, options = UnderpostRun.DEFAULT_OPTION) => {
68
+ const { underpostRoot } = options;
69
+ shellExec(`node ${underpostRoot}/bin/vs ${path}`);
70
+ },
71
+ monitor: (path, options = UnderpostRun.DEFAULT_OPTION) => {
72
+ const pid = getTerminalPid();
73
+ logger.info('monitor pid', pid);
74
+ const checkPath = '/await';
75
+ const _monitor = async () => {
76
+ const result = UnderpostDeploy.API.existsContainerFile({ podName: path, path: checkPath });
77
+ logger.info('monitor', result);
78
+ if (result === true) {
79
+ switch (path) {
80
+ case 'tf-vae-test':
81
+ {
82
+ const nameSpace = 'default';
83
+ const podName = path;
84
+ const basePath = '/home/dd';
85
+ const scriptPath = '/site/en/tutorials/generative/cvae.py';
86
+ // shellExec(
87
+ // `sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${scriptPath} ${basePath}/lab/src/${scriptPath
88
+ // .split('/')
89
+ // .pop()}`,
90
+ // );
91
+ // const file = fs.readFileSync(`${basePath}/lab/src/${scriptPath.split('/').pop()}`, 'utf8');
92
+ // fs.writeFileSync(
93
+ // `${basePath}/lab/src/${scriptPath.split('/').pop()}`,
94
+ // file.replace(
95
+ // `import time`,
96
+ // `import time
97
+ // print('=== SCRIPT UPDATE TEST ===')`,
98
+ // ),
99
+ // 'utf8',
100
+ // );
101
+ shellExec(
102
+ `sudo kubectl cp ${basePath}/lab/src/${scriptPath
103
+ .split('/')
104
+ .pop()} ${nameSpace}/${podName}:${basePath}/docs${scriptPath}`,
105
+ );
106
+ // shellExec(`sudo kubectl exec -i ${podName} -- sh -c "ipython ${basePath}/docs${scriptPath}"`);
107
+ shellExec(`sudo kubectl exec -i ${podName} -- sh -c "rm -rf ${checkPath}"`);
108
+
109
+ {
110
+ const checkPath = `/latent_space_plot.png`;
111
+ const outsPaths = [];
112
+ logger.info('monitor', checkPath);
113
+ while (!UnderpostDeploy.API.existsContainerFile({ podName, path: `/home/dd/docs${checkPath}` }))
114
+ await timer(1000);
115
+
116
+ {
117
+ const toPath = `${basePath}/lab${checkPath}`;
118
+ outsPaths.push(toPath);
119
+ shellExec(`sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${checkPath} ${toPath}`);
120
+ }
121
+
122
+ for (let i of range(1, 10)) {
123
+ i = `/image_at_epoch_${setPad(i, '0', 4)}.png`;
124
+ const toPath = `${basePath}/lab/${i}`;
125
+ outsPaths.push(toPath);
126
+ shellExec(`sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${i} ${toPath}`);
127
+ }
128
+ openTerminal(`firefox ${outsPaths.join(' ')}`, { single: true });
129
+ }
130
+ shellExec(`sudo kill -9 ${pid}`);
131
+ }
132
+ break;
133
+
134
+ default:
135
+ break;
136
+ }
137
+ return;
138
+ }
139
+ await timer(1000);
140
+ _monitor();
141
+ };
142
+ _monitor();
143
+ },
144
+ 'tf-vae-test': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
145
+ const { underpostRoot } = options;
146
+ const podName = 'tf-vae-test';
147
+ await UnderpostRun.RUNNERS['deploy-job']('', {
148
+ podName,
149
+ // volumeMountPath: '/custom_images',
150
+ // volumeHostPath: '/home/dd/engine/src/client/public/cyberia/assets/skin',
151
+ on: {
152
+ init: async () => {
153
+ openTerminal(`node bin run --dev monitor ${podName}`);
154
+ },
155
+ },
156
+ args: [
157
+ `pip install --upgrade \
158
+ nbconvert \
159
+ tensorflow-probability==0.23.0 \
160
+ imageio \
161
+ git+https://github.com/tensorflow/docs \
162
+ matplotlib \
163
+ "numpy<1.25,>=1.21"`,
164
+ 'mkdir -p /home/dd',
165
+ 'cd /home/dd',
166
+ 'git clone https://github.com/tensorflow/docs.git',
167
+ 'cd docs',
168
+ 'jupyter nbconvert --to python site/en/tutorials/generative/cvae.ipynb',
169
+ `echo '' > /await`,
170
+ `echo '=== WAITING SCRIPT LAUNCH ==='`,
171
+ `while [ -f /await ]; do sleep 1; done`,
172
+ `echo '=== FINISHED ==='`,
173
+ daemonProcess(`ipython site/en/tutorials/generative/cvae.py`),
174
+ ],
175
+ });
176
+ },
177
+ 'deploy-job': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
178
+ const podName = options.podName || 'deploy-job';
179
+ const volumeName = `${podName}-volume`;
180
+ const args = (options.args ? options.args : path ? [`python ${path}`] : []).filter((c) => c.trim());
181
+ const imageName = options.imageName || 'nvcr.io/nvidia/tensorflow:24.04-tf2-py3';
182
+ const containerName = options.containerName || `${podName}-container`;
183
+ const gpuEnable = imageName.match('nvidia');
184
+ const runtimeClassName = gpuEnable ? 'nvidia' : '';
185
+ const namespace = options.namespace || 'default';
186
+ const volumeMountPath = options.volumeMountPath || path;
187
+ const volumeHostPath = options.volumeHostPath || path;
188
+ const enableVolumeMount = volumeHostPath && volumeMountPath;
189
+
190
+ const cmd = `kubectl apply -f - <<EOF
191
+ apiVersion: v1
192
+ kind: Pod
193
+ metadata:
194
+ name: ${podName}
195
+ namespace: ${namespace}
196
+ spec:
197
+ restartPolicy: Never
198
+ ${runtimeClassName ? ` runtimeClassName: ${runtimeClassName}` : ''}
199
+ containers:
200
+ - name: ${containerName}
201
+ image: ${imageName}
202
+ imagePullPolicy: IfNotPresent
203
+ tty: true
204
+ stdin: true
205
+ command: ${JSON.stringify(options.command ? options.command : ['/bin/bash', '-c'])}
206
+ ${
207
+ args.length > 0
208
+ ? ` args:
209
+ - |
210
+ ${args.map((arg) => ` ${arg}`).join('\n')}`
211
+ : ''
212
+ }
213
+ ${
214
+ gpuEnable
215
+ ? ` resources:
216
+ limits:
217
+ nvidia.com/gpu: '1'
218
+ env:
219
+ - name: NVIDIA_VISIBLE_DEVICES
220
+ value: all`
221
+ : ''
222
+ }
223
+ ${
224
+ enableVolumeMount
225
+ ? `
226
+ volumeMounts:
227
+ - name: ${volumeName}
228
+ mountPath: ${volumeMountPath}
229
+ volumes:
230
+ - name: ${volumeName}
231
+ hostPath:
232
+ path: ${volumeHostPath}
233
+ type: ${fs.statSync(volumeHostPath).isDirectory() ? 'Directory' : 'File'}`
234
+ : ''
235
+ }
236
+ EOF`;
237
+ shellExec(`kubectl delete pod ${podName}`);
238
+ console.log(cmd);
239
+ shellExec(cmd, { disableLog: true });
240
+ const successInstance = await UnderpostTest.API.statusMonitor(podName);
241
+ if (successInstance) {
242
+ options.on?.init ? await options.on.init() : null;
243
+ shellExec(`kubectl logs -f ${podName}`);
244
+ }
245
+ },
246
+ };
247
+ static API = {
248
+ async callback(runner, path, options = UnderpostRun.DEFAULT_OPTION) {
249
+ const npmRoot = getNpmRootPath();
250
+ const underpostRoot = options?.dev === true ? '.' : `${npmRoot}/underpost`;
251
+ if (options.command) options.command = options.command.split(',');
252
+ if (options.args) options.args = options.args.split(',');
253
+ options.underpostRoot = underpostRoot;
254
+ options.npmRoot = npmRoot;
255
+ logger.info('callback', { path, options });
256
+ const result = await UnderpostRun.RUNNERS[runner](path, options);
257
+ return result;
258
+ },
259
+ };
260
+ }
261
+
262
+ export default UnderpostRun;
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
- const result = pods.find((p) => p.STATUS === status);
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
package/src/index.js CHANGED
@@ -16,6 +16,7 @@ import UnderpostImage from './cli/image.js';
16
16
  import UnderpostLxd from './cli/lxd.js';
17
17
  import UnderpostMonitor from './cli/monitor.js';
18
18
  import UnderpostRepository from './cli/repository.js';
19
+ import UnderpostRun from './cli/run.js';
19
20
  import UnderpostScript from './cli/script.js';
20
21
  import UnderpostSecret from './cli/secrets.js';
21
22
  import UnderpostTest from './cli/test.js';
@@ -33,102 +34,102 @@ class Underpost {
33
34
  * @type {String}
34
35
  * @memberof Underpost
35
36
  */
36
- static version = 'v2.8.82';
37
+ static version = 'v2.8.84';
37
38
  /**
38
39
  * Repository cli API
39
40
  * @static
40
- * @type {UnderpostRepository}
41
+ * @type {UnderpostRepository.API}
41
42
  * @memberof Underpost
42
43
  */
43
44
  static repo = UnderpostRepository.API;
44
45
  /**
45
46
  * Root Env cli API
46
47
  * @static
47
- * @type {UnderpostRootEnv}
48
+ * @type {UnderpostRootEnv.API}
48
49
  * @memberof Underpost
49
50
  */
50
51
  static env = UnderpostRootEnv.API;
51
52
  /**
52
53
  * Test cli API
53
54
  * @static
54
- * @type {UnderpostTest}
55
+ * @type {UnderpostTest.API}
55
56
  * @memberof Underpost
56
57
  */
57
58
  static test = UnderpostTest.API;
58
59
  /**
59
60
  * Underpost Start Up cli API
60
61
  * @static
61
- * @type {UnderpostStartUp}
62
+ * @type {UnderpostStartUp.API}
62
63
  * @memberof Underpost
63
64
  */
64
65
  static start = UnderpostStartUp.API;
65
66
  /**
66
67
  * Cluster cli API
67
68
  * @static
68
- * @type {UnderpostCluster}
69
+ * @type {UnderpostCluster.API}
69
70
  * @memberof Underpost
70
71
  */
71
72
  static cluster = UnderpostCluster.API;
72
73
  /**
73
74
  * Image cli API
74
75
  * @static
75
- * @type {UnderpostImage}
76
+ * @type {UnderpostImage.API}
76
77
  * @memberof Underpost
77
78
  */
78
79
  static image = UnderpostImage.API;
79
80
  /**
80
81
  * Secrets cli API
81
82
  * @static
82
- * @type {UnderpostSecret}
83
+ * @type {UnderpostSecret.API}
83
84
  * @memberof Underpost
84
85
  */
85
86
  static secret = UnderpostSecret.API;
86
87
  /**
87
88
  * Scripts cli API
88
89
  * @static
89
- * @type {UnderpostScript}
90
+ * @type {UnderpostScript.API}
90
91
  * @memberof Underpost
91
92
  */
92
93
  static script = UnderpostScript.API;
93
94
  /**
94
95
  * Database cli API
95
96
  * @static
96
- * @type {UnderpostDB}
97
+ * @type {UnderpostDB.API}
97
98
  * @memberof Underpost
98
99
  */
99
100
  static db = UnderpostDB.API;
100
101
  /**
101
102
  * Deployment cli API
102
103
  * @static
103
- * @type {UnderpostDeploy}
104
+ * @type {UnderpostDeploy.API}
104
105
  * @memberof Underpost
105
106
  */
106
107
  static deploy = UnderpostDeploy.API;
107
108
  /**
108
109
  * Cron cli API
109
110
  * @static
110
- * @type {UnderpostCron}
111
+ * @type {UnderpostCron.API}
111
112
  * @memberof Underpost
112
113
  */
113
114
  static cron = UnderpostCron.API;
114
115
  /**
115
116
  * File Storage cli API
116
117
  * @static
117
- * @type {UnderpostFileStorage}
118
+ * @type {UnderpostFileStorage.API}
118
119
  * @memberof Underpost
119
120
  */
120
121
  static fs = UnderpostFileStorage.API;
121
122
  /**
122
123
  * Monitor cli API
123
124
  * @static
124
- * @type {UnderpostMonitor}
125
+ * @type {UnderpostMonitor.API}
125
126
  * @memberof Underpost
126
127
  */
127
128
  static monitor = UnderpostMonitor.API;
128
129
  /**
129
130
  * LXD cli API
130
131
  * @static
131
- * @type {UnderpostLxd}
132
+ * @type {UnderpostLxd.API}
132
133
  * @memberof Underpost
133
134
  */
134
135
  static lxd = UnderpostLxd.API;
@@ -136,15 +137,23 @@ class Underpost {
136
137
  /**
137
138
  * Cloud Init cli API
138
139
  * @static
139
- * @type {UnderpostCloudInit}
140
+ * @type {UnderpostCloudInit.API}
140
141
  * @memberof Underpost
141
142
  */
142
143
  static cloudInit = UnderpostCloudInit.API;
143
144
 
145
+ /**
146
+ * Run cli API
147
+ * @static
148
+ * @type {UnderpostRun.API}
149
+ * @memberof Underpost
150
+ */
151
+ static run = UnderpostRun.API;
152
+
144
153
  /**
145
154
  * Baremetal cli API
146
155
  * @static
147
- * @type {UnderpostBaremetal}
156
+ * @type {UnderpostBaremetal.API}
148
157
  * @memberof Underpost
149
158
  */
150
159
  static baremetal = UnderpostBaremetal.API;
@@ -1171,7 +1171,7 @@ const writeEnv = (envPath, envObj) =>
1171
1171
  'utf8',
1172
1172
  );
1173
1173
 
1174
- const buildCliDoc = (program) => {
1174
+ const buildCliDoc = (program, oldVersion, newVersion) => {
1175
1175
  let md = shellExec(`node bin help`, { silent: true, stdout: true }).split('Options:');
1176
1176
  const baseOptions =
1177
1177
  `## ${md[0].split(`\n`)[2]}
@@ -1207,13 +1207,15 @@ const buildCliDoc = (program) => {
1207
1207
  `
1208
1208
  `;
1209
1209
  });
1210
+ md = md.replaceAll(oldVersion, newVersion);
1210
1211
  fs.writeFileSync(`./src/client/public/nexodev/docs/references/Command Line Interface.md`, md, 'utf8');
1211
1212
  fs.writeFileSync(`./cli.md`, md, 'utf8');
1212
1213
  const readmeSplit = `pwa-microservices-template</a>`;
1213
1214
  const readme = fs.readFileSync(`./README.md`, 'utf8').split(readmeSplit);
1214
1215
  fs.writeFileSync(
1215
1216
  './README.md',
1216
- readme[0] +
1217
+ (
1218
+ readme[0] +
1217
1219
  readmeSplit +
1218
1220
  `
1219
1221
 
@@ -1223,7 +1225,8 @@ const buildCliDoc = (program) => {
1223
1225
 
1224
1226
  <a target="_top" href="https://github.com/underpostnet/pwa-microservices-template/blob/master/cli.md">See complete CLI Docs here.</a>
1225
1227
 
1226
- `,
1228
+ `
1229
+ ).replaceAll(oldVersion, newVersion),
1227
1230
  'utf8',
1228
1231
  );
1229
1232
  };
@@ -10,8 +10,6 @@ dotenv.config();
10
10
 
11
11
  const logger = loggerFactory(import.meta);
12
12
 
13
- // process.exit();
14
-
15
13
  const getRootDirectory = () => process.cwd().replace(/\\/g, '/');
16
14
 
17
15
  const ProcessController = {
@@ -63,27 +61,26 @@ const shellCd = (cd, options = { disableLog: false }) => {
63
61
  return shell.cd(cd);
64
62
  };
65
63
 
66
- function pbcopy(data) {
67
- switch (process.platform) {
68
- case 'linux':
69
- {
70
- // sudo dnf install xclip
71
- // sudo apt update
72
- // sudo apt install xclip
73
- // paste: xclip -o
74
- // copy:
75
- // shellExec(`echo "${data}" | xclip -sel clip`, { async: true });
76
- }
64
+ const openTerminal = (cmd, options = { single: false }) => {
65
+ if (options.single === true) {
66
+ shellExec(`setsid gnome-terminal -- bash -ic "${cmd}; exec bash" >/dev/null 2>&1 &`);
67
+ return;
68
+ }
69
+ shellExec(`gnome-terminal -- bash -c "${cmd}; exec bash" & disown`, {
70
+ async: true,
71
+ stdout: true,
72
+ });
73
+ };
77
74
 
78
- break;
75
+ const daemonProcess = (cmd) => `exec bash -c '${cmd}; exec tail -f /dev/null'`;
79
76
 
80
- default:
81
- break;
82
- }
77
+ // list all terminals: pgrep gnome-terminal
78
+ // list last terminal: pgrep -n gnome-terminal
79
+ const getTerminalPid = () => JSON.parse(shellExec(`pgrep -n gnome-terminal`, { stdout: true, silent: true }));
83
80
 
81
+ function pbcopy(data) {
84
82
  clipboard.writeSync(data || '🦄');
85
-
86
83
  logger.info(`copied to clipboard`, clipboard.readSync());
87
84
  }
88
85
 
89
- export { ProcessController, getRootDirectory, shellExec, shellCd, pbcopy };
86
+ export { ProcessController, getRootDirectory, shellExec, shellCd, pbcopy, openTerminal, getTerminalPid, daemonProcess };