underpost 2.8.838 → 2.8.841

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/README.md CHANGED
@@ -25,10 +25,13 @@ template
25
25
 
26
26
 
27
27
 
28
+
29
+
30
+
28
31
  <!-- badges -->
29
32
 
30
33
 
31
- [![Node.js CI](https://github.com/underpostnet/engine/actions/workflows/docker-image.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/docker-image.yml) [![Test](https://github.com/underpostnet/engine/actions/workflows/coverall.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/coverall.yml) [![Downloads](https://img.shields.io/npm/dm/underpost.svg)](https://www.npmjs.com/package/underpost) [![Socket Badge](https://socket.dev/api/badge/npm/package/underpost/2.8.838)](https://socket.dev/npm/package/underpost/overview/2.8.838) [![Coverage Status](https://coveralls.io/repos/github/underpostnet/engine/badge.svg?branch=master)](https://coveralls.io/github/underpostnet/engine?branch=master) [![Version](https://img.shields.io/npm/v/underpost.svg)](https://www.npmjs.org/package/underpost) [![License](https://img.shields.io/npm/l/underpost.svg)](https://www.npmjs.com/package/underpost)
34
+ [![Node.js CI](https://github.com/underpostnet/engine/actions/workflows/docker-image.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/docker-image.yml) [![Test](https://github.com/underpostnet/engine/actions/workflows/coverall.yml/badge.svg?branch=master)](https://github.com/underpostnet/engine/actions/workflows/coverall.yml) [![Downloads](https://img.shields.io/npm/dm/underpost.svg)](https://www.npmjs.com/package/underpost) [![Socket Badge](https://socket.dev/api/badge/npm/package/underpost/2.8.841)](https://socket.dev/npm/package/underpost/overview/2.8.841) [![Coverage Status](https://coveralls.io/repos/github/underpostnet/engine/badge.svg?branch=master)](https://coveralls.io/github/underpostnet/engine?branch=master) [![Version](https://img.shields.io/npm/v/underpost.svg)](https://www.npmjs.org/package/underpost) [![License](https://img.shields.io/npm/l/underpost.svg)](https://www.npmjs.com/package/underpost)
32
35
 
33
36
 
34
37
  <!-- end-badges -->
@@ -36,6 +39,9 @@ template
36
39
 
37
40
 
38
41
 
42
+
43
+
44
+
39
45
  </div>
40
46
 
41
47
  <div align="center">
@@ -80,7 +86,7 @@ Run dev client server
80
86
  npm run dev
81
87
  ```
82
88
  <!-- -->
83
- ## underpost ci/cd cli v2.8.838
89
+ ## underpost ci/cd cli v2.8.841
84
90
 
85
91
  ### Usage: `underpost [options] [command]`
86
92
  ```
package/cli.md CHANGED
@@ -1,4 +1,4 @@
1
- ## underpost ci/cd cli v2.8.838
1
+ ## underpost ci/cd cli v2.8.8411
2
2
 
3
3
  ### Usage: `underpost [options] [command]`
4
4
  ```
@@ -554,28 +554,20 @@ Options:
554
554
  Runs a script from the specified path.
555
555
 
556
556
  Arguments:
557
- runner-id The runner ID to run. Options:
558
- spark-template, gpu-env, tf-gpu-test, ide,
559
- monitor, tf-vae-test, deploy-job.
560
- path The absolute or relative directory path
561
- where the script is located.
557
+ runner-id The runner ID to run. Options: spark-template, rmi, kill, secret, gpu-env, tf-gpu-test, ide, monitor, tf-vae-test, deploy-job.
558
+ path The absolute or relative directory path where the script is located.
562
559
 
563
560
  Options:
564
- --command <command-array> Array of commands to run.
565
- --args <args-array> Array of arguments to pass to the command.
566
- --dev Sets the development context environment
567
- for the script.
568
- --pod-name <pod-name> Optional: Specifies the pod name for test
569
- execution.
570
- --volume-name <volume-name> Optional: Specifies the volume name for
571
- test execution.
572
- --image-name <image-name> Optional: Specifies the image name for
573
- test execution.
574
- --container-name <container-name> Optional: Specifies the container name for
575
- test execution.
576
- --namespace <namespace> Optional: Specifies the namespace for test
577
- execution.
578
- -h, --help display help for command
561
+ --command <command-array> Array of commands to run.
562
+ --args <args-array> Array of arguments to pass to the command.
563
+ --dev Sets the development context environment for the script.
564
+ --pod-name <pod-name> Optional: Specifies the pod name for test execution.
565
+ --volume-host-path <volume-host-path> Optional: Specifies the volume host path for test execution.
566
+ --volume-mount-path <volume-mount-path> Optional: Specifies the volume mount path for test execution.
567
+ --image-name <image-name> Optional: Specifies the image name for test execution.
568
+ --container-name <container-name> Optional: Specifies the container name for test execution.
569
+ --namespace <namespace> Optional: Specifies the namespace for test execution.
570
+ -h, --help display help for command
579
571
 
580
572
  ```
581
573
 
@@ -58,7 +58,7 @@ services:
58
58
  cpus: '0.25'
59
59
  memory: 20M
60
60
  labels: # labels in Compose file instead of Dockerfile
61
- engine.version: '2.8.838'
61
+ engine.version: '2.8.841'
62
62
  networks:
63
63
  - load-balancer
64
64
 
@@ -17,7 +17,7 @@ spec:
17
17
  spec:
18
18
  containers:
19
19
  - name: dd-template-development-blue
20
- image: localhost/rockylinux9-underpost:v2.8.838
20
+ image: localhost/rockylinux9-underpost:v2.8.841
21
21
  # resources:
22
22
  # requests:
23
23
  # memory: "124Ki"
@@ -100,7 +100,7 @@ spec:
100
100
  spec:
101
101
  containers:
102
102
  - name: dd-template-development-green
103
- image: localhost/rockylinux9-underpost:v2.8.838
103
+ image: localhost/rockylinux9-underpost:v2.8.841
104
104
  # resources:
105
105
  # requests:
106
106
  # memory: "124Ki"
@@ -0,0 +1,19 @@
1
+ # GPUs and drivers in use
2
+ sudo lspci -nnk | egrep -i 'vga|3d' -A3
3
+
4
+ # modules loaded relevant
5
+ lsmod | egrep 'nvidia|nouveau|amdgpu' || true
6
+
7
+ # if exists nvidia tool
8
+ nvidia-smi 2>/dev/null || echo "nvidia-smi no disponible / driver no cargado"
9
+
10
+ # kernel related errors
11
+ sudo dmesg | egrep -i 'nvidia|nouveau|amdgpu' --color=auto
12
+
13
+ # recent system errors / gdm / mutter / X
14
+ sudo journalctl -b -p err --no-pager | head -n 200
15
+ journalctl -b _COMM=gdm --no-pager | tail -n 200
16
+ journalctl -b _COMM=Xorg --no-pager | tail -n 200
17
+
18
+ # X log (if exists)
19
+ sudo grep -E "(EE|WW|NVIDIA|nouveau|amdgpu)" /var/log/Xorg.0.log || true
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "type": "module",
3
3
  "main": "src/index.js",
4
4
  "name": "underpost",
5
- "version": "2.8.838",
5
+ "version": "2.8.841",
6
6
  "description": "pwa api rest template",
7
7
  "scripts": {
8
8
  "start": "env-cmd -f .env.production node --max-old-space-size=8192 src/server",
@@ -260,12 +260,12 @@ class UnderpostCluster {
260
260
 
261
261
  if (options.full === true || options.valkey === true) {
262
262
  if (options.pullImage === true) {
263
- shellExec(`docker pull valkey/valkey:latest`);
264
- shellExec(`sudo podman pull valkey/valkey:latest`);
265
- if (!options.kubeadm && !options.k3s)
263
+ // shellExec(`sudo podman pull valkey/valkey:latest`);
264
+ if (!options.kubeadm && !options.k3s) {
266
265
  // Only load if not kubeadm/k3s (Kind needs it)
266
+ shellExec(`docker pull valkey/valkey:latest`);
267
267
  shellExec(`sudo kind load docker-image valkey/valkey:latest`);
268
- else if (options.kubeadm || options.k3s)
268
+ } else if (options.kubeadm || options.k3s)
269
269
  // For kubeadm/k3s, ensure it's available for containerd
270
270
  shellExec(`sudo crictl pull valkey/valkey:latest`);
271
271
  }
@@ -279,12 +279,12 @@ class UnderpostCluster {
279
279
  shellExec(`kubectl delete statefulset mariadb-statefulset --ignore-not-found`);
280
280
 
281
281
  if (options.pullImage === true) {
282
- shellExec(`docker pull mariadb:latest`);
283
- shellExec(`sudo podman pull mariadb:latest`);
284
- if (!options.kubeadm && !options.k3s)
282
+ // shellExec(`sudo podman pull mariadb:latest`);
283
+ if (!options.kubeadm && !options.k3s) {
285
284
  // Only load if not kubeadm/k3s (Kind needs it)
285
+ shellExec(`docker pull mariadb:latest`);
286
286
  shellExec(`sudo kind load docker-image mariadb:latest`);
287
- else if (options.kubeadm || options.k3s)
287
+ } else if (options.kubeadm || options.k3s)
288
288
  // For kubeadm/k3s, ensure it's available for containerd
289
289
  shellExec(`sudo crictl pull mariadb:latest`);
290
290
  }
@@ -304,11 +304,11 @@ class UnderpostCluster {
304
304
  }
305
305
  if (options.full === true || options.postgresql === true) {
306
306
  if (options.pullImage === true) {
307
- shellExec(`docker pull postgres:latest`);
308
- if (!options.kubeadm && !options.k3s)
307
+ if (!options.kubeadm && !options.k3s) {
309
308
  // Only load if not kubeadm/k3s (Kind needs it)
309
+ shellExec(`docker pull postgres:latest`);
310
310
  shellExec(`sudo kind load docker-image postgres:latest`);
311
- else if (options.kubeadm || options.k3s)
311
+ } else if (options.kubeadm || options.k3s)
312
312
  // For kubeadm/k3s, ensure it's available for containerd
313
313
  shellExec(`sudo crictl pull postgres:latest`);
314
314
  }
@@ -319,11 +319,11 @@ class UnderpostCluster {
319
319
  }
320
320
  if (options.mongodb4 === true) {
321
321
  if (options.pullImage === true) {
322
- shellExec(`docker pull mongo:4.4`);
323
- if (!options.kubeadm && !options.k3s)
322
+ if (!options.kubeadm && !options.k3s) {
324
323
  // Only load if not kubeadm/k3s (Kind needs it)
324
+ shellExec(`docker pull mongo:4.4`);
325
325
  shellExec(`sudo kind load docker-image mongo:4.4`);
326
- else if (options.kubeadm || options.k3s)
326
+ } else if (options.kubeadm || options.k3s)
327
327
  // For kubeadm/k3s, ensure it's available for containerd
328
328
  shellExec(`sudo crictl pull mongo:4.4`);
329
329
  }
@@ -348,11 +348,11 @@ class UnderpostCluster {
348
348
  }
349
349
  } else if (options.full === true || options.mongodb === true) {
350
350
  if (options.pullImage === true) {
351
- shellExec(`docker pull mongo:latest`);
352
- if (!options.kubeadm && !options.k3s)
351
+ if (!options.kubeadm && !options.k3s) {
353
352
  // Only load if not kubeadm/k3s (Kind needs it)
353
+ shellExec(`docker pull mongo:latest`);
354
354
  shellExec(`sudo kind load docker-image mongo:latest`);
355
- else if (options.kubeadm || options.k3s)
355
+ } else if (options.kubeadm || options.k3s)
356
356
  // For kubeadm/k3s, ensure it's available for containerd
357
357
  shellExec(`sudo crictl pull mongo:latest`);
358
358
  }
@@ -425,7 +425,7 @@ class UnderpostCluster {
425
425
  * @param {string} underpostRoot - The root directory of the underpost project.
426
426
  */
427
427
  config(options = { underpostRoot: '.' }) {
428
- const underpostRoot = options;
428
+ const { underpostRoot } = options;
429
429
  console.log('Applying host configuration: SELinux, Docker, Containerd, and Sysctl settings.');
430
430
  // Disable SELinux (permissive mode)
431
431
  shellExec(`sudo setenforce 0`);
@@ -460,10 +460,13 @@ class UnderpostCluster {
460
460
  `/etc/sysctl.d/99-k8s-ipforward.conf`,
461
461
  `/etc/sysctl.d/99-k8s.conf`,
462
462
  ])
463
- shellExec(`echo 'net.bridge.bridge-nf-call-iptables = 1
463
+ shellExec(
464
+ `echo 'net.bridge.bridge-nf-call-iptables = 1
464
465
  net.bridge.bridge-nf-call-ip6tables = 1
465
466
  net.bridge.bridge-nf-call-arptables = 1
466
- net.ipv4.ip_forward = 1' | sudo tee ${iptableConfPath}`);
467
+ net.ipv4.ip_forward = 1' | sudo tee ${iptableConfPath}`,
468
+ { silent: true },
469
+ );
467
470
  // shellExec(`sudo sysctl --system`); // Apply sysctl changes immediately
468
471
  // Apply NAT iptables rules.
469
472
  shellExec(`${underpostRoot}/manifests/maas/nat-iptables.sh`, { silent: true });
@@ -519,7 +522,7 @@ net.ipv4.ip_forward = 1' | sudo tee ${iptableConfPath}`);
519
522
 
520
523
  try {
521
524
  // Phase 0: Truncate large logs under /var/log to free up immediate space
522
- logger.info('Phase 0/6: Truncating large log files under /var/log...');
525
+ logger.info('Phase 0/7: Truncating large log files under /var/log...');
523
526
  try {
524
527
  const cleanPath = `/var/log/`;
525
528
  const largeLogsFiles = shellExec(
@@ -540,7 +543,7 @@ net.ipv4.ip_forward = 1' | sudo tee ${iptableConfPath}`);
540
543
 
541
544
  // Phase 1: Clean up Persistent Volumes with hostPath
542
545
  // This targets data created by Kubernetes Persistent Volumes that use hostPath.
543
- logger.info('Phase 1/6: Cleaning Kubernetes hostPath volumes...');
546
+ logger.info('Phase 1/7: Cleaning Kubernetes hostPath volumes...');
544
547
  try {
545
548
  const pvListJson = shellExec(`kubectl get pv -o json || echo '{"items":[]}'`, { stdout: true, silent: true });
546
549
  const pvList = JSON.parse(pvListJson);
@@ -563,7 +566,7 @@ net.ipv4.ip_forward = 1' | sudo tee ${iptableConfPath}`);
563
566
  // Phase 2: Restore SELinux and stop services
564
567
  // This is critical for fixing the 'permission denied' error you experienced.
565
568
  // Enable SELinux permissive mode and restore file contexts.
566
- logger.info('Phase 2/6: Stopping services and fixing SELinux...');
569
+ logger.info('Phase 2/7: Stopping services and fixing SELinux...');
567
570
  logger.info(' -> Ensuring SELinux is in permissive mode...');
568
571
  shellExec(`sudo setenforce 0 || true`);
569
572
  shellExec(`sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config || true`);
@@ -580,7 +583,7 @@ net.ipv4.ip_forward = 1' | sudo tee ${iptableConfPath}`);
580
583
  shellExec('sudo umount -f /var/lib/kubelet/pods/*/* || true');
581
584
 
582
585
  // Phase 3: Execute official uninstallation commands
583
- logger.info('Phase 3/6: Executing official reset and uninstallation commands...');
586
+ logger.info('Phase 3/7: Executing official reset and uninstallation commands...');
584
587
  logger.info(' -> Executing kubeadm reset...');
585
588
  shellExec('sudo kubeadm reset --force || true');
586
589
  logger.info(' -> Executing K3s uninstallation script if it exists...');
@@ -589,7 +592,7 @@ net.ipv4.ip_forward = 1' | sudo tee ${iptableConfPath}`);
589
592
  shellExec('kind get clusters | xargs -r -t -n1 kind delete cluster || true');
590
593
 
591
594
  // Phase 4: File system cleanup
592
- logger.info('Phase 4/6: Cleaning up remaining file system artifacts...');
595
+ logger.info('Phase 4/7: Cleaning up remaining file system artifacts...');
593
596
  // Remove any leftover configurations and data.
594
597
  shellExec('sudo rm -rf /etc/kubernetes/* || true');
595
598
  shellExec('sudo rm -rf /etc/cni/net.d/* || true');
@@ -602,15 +605,21 @@ net.ipv4.ip_forward = 1' | sudo tee ${iptableConfPath}`);
602
605
  shellExec('rm -rf $HOME/.kube || true');
603
606
 
604
607
  // Phase 5: Host network cleanup
605
- logger.info('Phase 5/6: Cleaning up host network configurations...');
608
+ logger.info('Phase 5/7: Cleaning up host network configurations...');
606
609
  // Remove iptables rules and CNI network interfaces.
607
610
  shellExec('sudo iptables -F || true');
608
611
  shellExec('sudo iptables -t nat -F || true');
612
+ // Restore iptables rules
613
+ shellExec(`chmod +x ${options.underpostRoot}/manifests/maas/nat-iptables.sh`);
614
+ shellExec(`${options.underpostRoot}/manifests/maas/nat-iptables.sh`, { silent: true });
609
615
  shellExec('sudo ip link del cni0 || true');
610
616
  shellExec('sudo ip link del flannel.1 || true');
611
617
 
618
+ logger.info('Phase 6/7: Clean up images');
619
+ shellExec(`podman rmi $(podman images -qa) --force`);
620
+
612
621
  // Phase 6: Reload daemon and finalize
613
- logger.info('Phase 6/6: Reloading the system daemon and finalizing...');
622
+ logger.info('Phase 7/7: Reloading the system daemon and finalizing...');
614
623
  // shellExec('sudo systemctl daemon-reload');
615
624
  UnderpostCluster.API.config();
616
625
  logger.info('Safe and complete reset finished. The system is ready for a new cluster initialization.');
package/src/cli/deploy.js CHANGED
@@ -519,6 +519,15 @@ node bin/deploy build-full-client ${deployId}
519
519
  logger.error(error, error.stack);
520
520
  }
521
521
  },
522
+ existsContainerFile({ podName, path }) {
523
+ return JSON.parse(
524
+ shellExec(`kubectl exec ${podName} -- test -f ${path} && echo "true" || echo "false"`, {
525
+ stdout: true,
526
+ disableLog: true,
527
+ silent: true,
528
+ }).trim(),
529
+ );
530
+ },
522
531
  };
523
532
  }
524
533
 
package/src/cli/index.js CHANGED
@@ -324,7 +324,8 @@ program
324
324
  .option('--args <args-array>', 'Array of arguments to pass to the command.')
325
325
  .option('--dev', 'Sets the development context environment for the script.')
326
326
  .option('--pod-name <pod-name>', 'Optional: Specifies the pod name for test execution.')
327
- .option('--volume-name <volume-name>', 'Optional: Specifies the volume name for test execution.')
327
+ .option('--volume-host-path <volume-host-path>', 'Optional: Specifies the volume host path for test execution.')
328
+ .option('--volume-mount-path <volume-mount-path>', 'Optional: Specifies the volume mount path for test execution.')
328
329
  .option('--image-name <image-name>', 'Optional: Specifies the image name for test execution.')
329
330
  .option('--container-name <container-name>', 'Optional: Specifies the container name for test execution.')
330
331
  .option('--namespace <namespace>', 'Optional: Specifies the namespace for test execution.')
package/src/cli/run.js CHANGED
@@ -1,10 +1,12 @@
1
- import { getTerminalPid, openTerminal, pbcopy, shellCd, shellExec } from '../server/process.js';
1
+ import { daemonProcess, getTerminalPid, openTerminal, pbcopy, shellCd, shellExec } from '../server/process.js';
2
2
  import read from 'read';
3
3
  import { getNpmRootPath } from '../server/conf.js';
4
4
  import { loggerFactory } from '../server/logger.js';
5
5
  import UnderpostTest from './test.js';
6
6
  import fs from 'fs-extra';
7
- import { timer } from '../client/components/core/CommonJs.js';
7
+ import { range, setPad, timer } from '../client/components/core/CommonJs.js';
8
+ import UnderpostDeploy from './deploy.js';
9
+ import UnderpostRootEnv from './env.js';
8
10
 
9
11
  const logger = loggerFactory(import.meta);
10
12
 
@@ -12,7 +14,8 @@ class UnderpostRun {
12
14
  static DEFAULT_OPTION = {
13
15
  dev: false,
14
16
  podName: '',
15
- volumeName: '',
17
+ volumeHostPath: '',
18
+ volumeMountPath: '',
16
19
  imageName: '',
17
20
  containerName: '',
18
21
  namespace: '',
@@ -38,6 +41,19 @@ class UnderpostRun {
38
41
 
39
42
  shellCd('/home/dd/engine');
40
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
+ },
41
57
  'gpu-env': (path, options = UnderpostRun.DEFAULT_OPTION) => {
42
58
  shellExec(
43
59
  `node bin cluster --dev --reset && node bin cluster --dev --dedicated-gpu --kubeadm && kubectl get pods --all-namespaces -o wide -w`,
@@ -58,13 +74,7 @@ class UnderpostRun {
58
74
  logger.info('monitor pid', pid);
59
75
  const checkPath = '/await';
60
76
  const _monitor = async () => {
61
- const result = JSON.parse(
62
- shellExec(`kubectl exec ${path} -- test -f ${checkPath} && echo "true" || echo "false"`, {
63
- stdout: true,
64
- disableLog: true,
65
- silent: true,
66
- }).trim(),
67
- );
77
+ const result = UnderpostDeploy.API.existsContainerFile({ podName: path, path: checkPath });
68
78
  logger.info('monitor', result);
69
79
  if (result === true) {
70
80
  switch (path) {
@@ -74,21 +84,21 @@ class UnderpostRun {
74
84
  const podName = path;
75
85
  const basePath = '/home/dd';
76
86
  const scriptPath = '/site/en/tutorials/generative/cvae.py';
77
- shellExec(
78
- `sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${scriptPath} ${basePath}/lab/src/${scriptPath
79
- .split('/')
80
- .pop()}`,
81
- );
82
- const file = fs.readFileSync(`${basePath}/lab/src/${scriptPath.split('/').pop()}`, 'utf8');
83
- fs.writeFileSync(
84
- `${basePath}/lab/src/${scriptPath.split('/').pop()}`,
85
- file.replace(
86
- `import time`,
87
- `import time
88
- print('=== SCRIPT UPDATE TEST ===')`,
89
- ),
90
- 'utf8',
91
- );
87
+ // shellExec(
88
+ // `sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${scriptPath} ${basePath}/lab/src/${scriptPath
89
+ // .split('/')
90
+ // .pop()}`,
91
+ // );
92
+ // const file = fs.readFileSync(`${basePath}/lab/src/${scriptPath.split('/').pop()}`, 'utf8');
93
+ // fs.writeFileSync(
94
+ // `${basePath}/lab/src/${scriptPath.split('/').pop()}`,
95
+ // file.replace(
96
+ // `import time`,
97
+ // `import time
98
+ // print('=== SCRIPT UPDATE TEST ===')`,
99
+ // ),
100
+ // 'utf8',
101
+ // );
92
102
  shellExec(
93
103
  `sudo kubectl cp ${basePath}/lab/src/${scriptPath
94
104
  .split('/')
@@ -96,6 +106,28 @@ print('=== SCRIPT UPDATE TEST ===')`,
96
106
  );
97
107
  // shellExec(`sudo kubectl exec -i ${podName} -- sh -c "ipython ${basePath}/docs${scriptPath}"`);
98
108
  shellExec(`sudo kubectl exec -i ${podName} -- sh -c "rm -rf ${checkPath}"`);
109
+
110
+ {
111
+ const checkPath = `/latent_space_plot.png`;
112
+ const outsPaths = [];
113
+ logger.info('monitor', checkPath);
114
+ while (!UnderpostDeploy.API.existsContainerFile({ podName, path: `/home/dd/docs${checkPath}` }))
115
+ await timer(1000);
116
+
117
+ {
118
+ const toPath = `${basePath}/lab${checkPath}`;
119
+ outsPaths.push(toPath);
120
+ shellExec(`sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${checkPath} ${toPath}`);
121
+ }
122
+
123
+ for (let i of range(1, 10)) {
124
+ i = `/image_at_epoch_${setPad(i, '0', 4)}.png`;
125
+ const toPath = `${basePath}/lab/${i}`;
126
+ outsPaths.push(toPath);
127
+ shellExec(`sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${i} ${toPath}`);
128
+ }
129
+ openTerminal(`firefox ${outsPaths.join(' ')}`, { single: true });
130
+ }
99
131
  shellExec(`sudo kill -9 ${pid}`);
100
132
  }
101
133
  break;
@@ -115,6 +147,8 @@ print('=== SCRIPT UPDATE TEST ===')`,
115
147
  const podName = 'tf-vae-test';
116
148
  await UnderpostRun.RUNNERS['deploy-job']('', {
117
149
  podName,
150
+ // volumeMountPath: '/custom_images',
151
+ // volumeHostPath: '/home/dd/engine/src/client/public/cyberia/assets/skin',
118
152
  on: {
119
153
  init: async () => {
120
154
  openTerminal(`node bin run --dev monitor ${podName}`);
@@ -136,20 +170,29 @@ print('=== SCRIPT UPDATE TEST ===')`,
136
170
  `echo '' > /await`,
137
171
  `echo '=== WAITING SCRIPT LAUNCH ==='`,
138
172
  `while [ -f /await ]; do sleep 1; done`,
139
- `ipython site/en/tutorials/generative/cvae.py`,
140
173
  `echo '=== FINISHED ==='`,
174
+ daemonProcess(`ipython site/en/tutorials/generative/cvae.py`),
141
175
  ],
142
176
  });
143
177
  },
144
178
  'deploy-job': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
145
179
  const podName = options.podName || 'deploy-job';
146
- const volumeName = options.volumeName || `${podName}-volume`;
180
+ const volumeName = `${podName}-volume`;
147
181
  const args = (options.args ? options.args : path ? [`python ${path}`] : []).filter((c) => c.trim());
148
182
  const imageName = options.imageName || 'nvcr.io/nvidia/tensorflow:24.04-tf2-py3';
149
183
  const containerName = options.containerName || `${podName}-container`;
150
184
  const gpuEnable = imageName.match('nvidia');
151
185
  const runtimeClassName = gpuEnable ? 'nvidia' : '';
152
186
  const namespace = options.namespace || 'default';
187
+ const volumeMountPath = options.volumeMountPath || path;
188
+ const volumeHostPath = options.volumeHostPath || path;
189
+ const enableVolumeMount = volumeHostPath && volumeMountPath;
190
+
191
+ if (options.volumeType === 'dev') options.volumeType = 'FileOrCreate';
192
+ const volumeType =
193
+ options.volumeType || (enableVolumeMount && fs.statSync(volumeHostPath).isDirectory()) ? 'Directory' : 'File';
194
+
195
+ const envs = UnderpostRootEnv.API.list();
153
196
 
154
197
  const cmd = `kubectl apply -f - <<EOF
155
198
  apiVersion: v1
@@ -174,27 +217,30 @@ ${
174
217
  ${args.map((arg) => ` ${arg}`).join('\n')}`
175
218
  : ''
176
219
  }
177
- ${
220
+ ${`${
178
221
  gpuEnable
179
222
  ? ` resources:
180
223
  limits:
181
224
  nvidia.com/gpu: '1'
182
- env:
183
- - name: NVIDIA_VISIBLE_DEVICES
184
- value: all`
225
+ `
185
226
  : ''
186
- }
227
+ } env:
228
+ ${Object.keys(envs)
229
+ .map((key) => ({ key, value: typeof envs[key] === 'number' ? envs[key] : `"${envs[key]}"` }))
230
+ .concat(gpuEnable ? [{ key: 'NVIDIA_VISIBLE_DEVICES', value: 'all' }] : [])
231
+ .map((env) => ` - name: ${env.key}\n value: ${env.value}`)
232
+ .join('\n')}`}
187
233
  ${
188
- path
234
+ enableVolumeMount
189
235
  ? `
190
236
  volumeMounts:
191
237
  - name: ${volumeName}
192
- mountPath: ${path}
238
+ mountPath: ${volumeMountPath}
193
239
  volumes:
194
240
  - name: ${volumeName}
195
241
  hostPath:
196
- path: ${path}
197
- type: ${fs.statSync(path).isDirectory() ? 'Directory' : 'File'}`
242
+ path: ${volumeHostPath}
243
+ type: ${volumeType}`
198
244
  : ''
199
245
  }
200
246
  EOF`;
package/src/index.js CHANGED
@@ -34,7 +34,7 @@ class Underpost {
34
34
  * @type {String}
35
35
  * @memberof Underpost
36
36
  */
37
- static version = 'v2.8.838';
37
+ static version = 'v2.8.841';
38
38
  /**
39
39
  * Repository cli API
40
40
  * @static
@@ -1,43 +1,35 @@
1
1
  FROM rockylinux:9
2
2
 
3
- RUN dnf install -y --allowerasing bzip2
4
-
5
- RUN dnf update -y
6
- RUN dnf install -y epel-release
7
- RUN dnf install -y --allowerasing sudo
8
- RUN dnf install -y --allowerasing curl
9
- RUN dnf install -y --allowerasing net-tools
10
- RUN dnf install -y --allowerasing openssh-server
11
- RUN dnf install -y --allowerasing nano
12
- RUN dnf install -y --allowerasing vim-enhanced
13
- RUN dnf install -y --allowerasing less
14
- RUN dnf install -y --allowerasing openssl-devel
15
- RUN dnf install -y --allowerasing wget
16
- RUN dnf install -y --allowerasing git
17
- RUN dnf install -y --allowerasing gnupg2
18
- RUN dnf clean all
19
-
20
- # Install LAMPP (XAMPP)
21
- # Download the XAMPP installer for Linux
22
- RUN curl -Lo xampp-linux-installer.run https://sourceforge.net/projects/xampp/files/XAMPP%20Linux/7.4.33/xampp-linux-x64-7.4.33-0-installer.run?from_af=true
23
- RUN chmod +x xampp-linux-installer.run
24
- # Run the XAMPP installer in silent mode
25
- RUN bash -c './xampp-linux-installer.run --mode unattended'
26
- # Create a symbolic link for easy access to lampp command
27
- RUN ln -sf /opt/lampp/lampp /usr/bin/lampp
28
-
29
- # Configure XAMPP
30
- # Enable XAMPP web interface (remove security checks)
31
- RUN sed -i.bak 's/Require local/Require all granted/g' /opt/lampp/etc/extra/httpd-xampp.conf
32
- # Enable error display in php
33
- RUN sed -i.bak 's/display_errors=Off/display_errors=On/g' /opt/lampp/etc/php.ini
34
- # Enable includes of several configuration files for Apache
35
- RUN mkdir -p /opt/lampp/apache2/conf.d
36
- RUN echo "IncludeOptional /opt/lampp/apache2/conf.d/*.conf" >>/opt/lampp/etc/httpd.conf
37
- # Create a /www folder and a symbolic link to it in /opt/lampp/htdocs
38
- # This is convenient because it doesn't interfere with xampp, phpmyadmin or other tools
39
- RUN mkdir /www
40
- RUN ln -s /www /opt/lampp/htdocs
3
+ # --- Update and install required packages
4
+ RUN dnf -y update && \
5
+ dnf -y install epel-release && \
6
+ dnf -y install --allowerasing \
7
+ bzip2 \
8
+ sudo \
9
+ curl \
10
+ net-tools \
11
+ openssh-server \
12
+ nano \
13
+ vim-enhanced \
14
+ less \
15
+ openssl-devel \
16
+ wget \
17
+ git \
18
+ gnupg2 \
19
+ libnsl \
20
+ perl && \
21
+ dnf clean all
22
+
23
+ # --- Download and install XAMPP
24
+ RUN curl -L -o /tmp/xampp-linux-installer.run "https://sourceforge.net/projects/xampp/files/XAMPP%20Linux/7.4.33/xampp-linux-x64-7.4.33-0-installer.run" && \
25
+ chmod +x /tmp/xampp-linux-installer.run && \
26
+ bash -c "/tmp/xampp-linux-installer.run --mode unattended" && \
27
+ ln -sf /opt/lampp/lampp /usr/bin/lampp
28
+
29
+ # --- Create /xampp/htdocs (static root) and set permissions
30
+ RUN mkdir -p /opt/lampp/htdocs && \
31
+ chown -R root:root /opt/lampp/htdocs && \
32
+ chmod -R a+rX /opt/lampp/htdocs
41
33
 
42
34
  # Install Node.js
43
35
  RUN curl -fsSL https://rpm.nodesource.com/setup_23.x | bash -
@@ -51,7 +43,6 @@ RUN npm --version
51
43
  # Set working directory
52
44
  WORKDIR /home/dd
53
45
 
54
- # Expose necessary ports
55
46
  EXPOSE 22
56
47
  EXPOSE 80
57
48
  EXPOSE 443
@@ -10,7 +10,16 @@ const Lampp = {
10
10
  initService: async function (options = { daemon: false }) {
11
11
  let cmd;
12
12
  // linux
13
- fs.writeFileSync(`/opt/lampp/apache2/conf/httpd.conf`, this.router || '', 'utf8');
13
+ // /opt/lampp/apache2/conf/httpd.conf
14
+ fs.writeFileSync(`/opt/lampp/etc/extra/httpd-vhosts.conf`, this.router || '', 'utf8');
15
+ fs.writeFileSync(
16
+ `/opt/lampp/etc/httpd.conf`,
17
+ fs
18
+ .readFileSync(`/opt/lampp/etc/httpd.conf`, 'utf8')
19
+ .replace(`#Include etc/extra/httpd-vhosts.conf`, `Include etc/extra/httpd-vhosts.conf`),
20
+ 'utf8',
21
+ );
22
+
14
23
  cmd = `sudo /opt/lampp/lampp stop`;
15
24
  if (!fs.readFileSync(`/opt/lampp/etc/httpd.conf`, 'utf8').match(`# Listen 80`))
16
25
  fs.writeFileSync(
@@ -42,7 +51,7 @@ const Lampp = {
42
51
  if (this.router) fs.writeFileSync(`./tmp/lampp-router.conf`, this.router, 'utf-8');
43
52
  shellExec(cmd);
44
53
  },
45
- enabled: () => fs.existsSync(`/opt/lampp/apache2/conf/httpd.conf`),
54
+ enabled: () => fs.existsSync(`/opt/lampp/etc/httpd.conf`),
46
55
  appendRouter: function (render) {
47
56
  if (!this.router) {
48
57
  if (fs.existsSync(`./tmp/lampp-router.conf`))
@@ -61,11 +61,18 @@ const shellCd = (cd, options = { disableLog: false }) => {
61
61
  return shell.cd(cd);
62
62
  };
63
63
 
64
- const openTerminal = (cmd) =>
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
+ }
65
69
  shellExec(`gnome-terminal -- bash -c "${cmd}; exec bash" & disown`, {
66
70
  async: true,
67
71
  stdout: true,
68
72
  });
73
+ };
74
+
75
+ const daemonProcess = (cmd) => `exec bash -c '${cmd}; exec tail -f /dev/null'`;
69
76
 
70
77
  // list all terminals: pgrep gnome-terminal
71
78
  // list last terminal: pgrep -n gnome-terminal
@@ -76,4 +83,4 @@ function pbcopy(data) {
76
83
  logger.info(`copied to clipboard`, clipboard.readSync());
77
84
  }
78
85
 
79
- export { ProcessController, getRootDirectory, shellExec, shellCd, pbcopy, openTerminal, getTerminalPid };
86
+ export { ProcessController, getRootDirectory, shellExec, shellCd, pbcopy, openTerminal, getTerminalPid, daemonProcess };