underpost 2.8.7 → 2.8.8

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.
Files changed (47) hide show
  1. package/.vscode/extensions.json +34 -2
  2. package/README.md +7 -5
  3. package/bin/db.js +1 -0
  4. package/bin/deploy.js +259 -74
  5. package/cli.md +88 -9
  6. package/conf.js +4 -0
  7. package/docker-compose.yml +1 -1
  8. package/manifests/deployment/adminer/service.yaml +1 -1
  9. package/manifests/deployment/dd-template-development/deployment.yaml +167 -0
  10. package/manifests/deployment/dd-template-development/proxy.yaml +46 -0
  11. package/manifests/deployment/fastapi/initial_data.sh +56 -0
  12. package/manifests/deployment/spark/spark-pi-py.yaml +21 -0
  13. package/manifests/envoy-service-nodeport.yaml +23 -0
  14. package/manifests/kubelet-config.yaml +65 -0
  15. package/manifests/lxd/lxd-admin-profile.yaml +17 -0
  16. package/manifests/lxd/lxd-preseed.yaml +30 -0
  17. package/manifests/lxd/underpost-setup.sh +163 -0
  18. package/manifests/maas/lxd-preseed.yaml +32 -0
  19. package/manifests/maas/maas-setup.sh +82 -0
  20. package/manifests/mariadb/statefulset.yaml +2 -1
  21. package/manifests/mariadb/storage-class.yaml +10 -0
  22. package/manifests/mongodb/kustomization.yaml +1 -1
  23. package/manifests/mongodb/statefulset.yaml +12 -11
  24. package/manifests/mongodb/storage-class.yaml +9 -0
  25. package/manifests/mongodb-4.4/service-deployment.yaml +2 -2
  26. package/manifests/mysql/kustomization.yaml +7 -0
  27. package/manifests/mysql/pv-pvc.yaml +27 -0
  28. package/manifests/mysql/statefulset.yaml +55 -0
  29. package/manifests/postgresql/statefulset.yaml +1 -1
  30. package/manifests/valkey/service.yaml +3 -9
  31. package/manifests/valkey/statefulset.yaml +12 -15
  32. package/package.json +1 -1
  33. package/src/cli/baremetal.js +60 -0
  34. package/src/cli/cluster.js +506 -207
  35. package/src/cli/deploy.js +47 -14
  36. package/src/cli/env.js +2 -2
  37. package/src/cli/image.js +83 -9
  38. package/src/cli/index.js +68 -61
  39. package/src/cli/lxd.js +395 -0
  40. package/src/cli/repository.js +9 -6
  41. package/src/index.js +17 -1
  42. package/src/runtime/lampp/Dockerfile +1 -1
  43. package/src/server/conf.js +58 -0
  44. package/src/server/logger.js +3 -3
  45. package/src/server/runtime.js +1 -1
  46. package/src/server/valkey.js +3 -3
  47. package/manifests/calico-custom-resources.yaml +0 -25
@@ -5,15 +5,47 @@
5
5
  "codeium.codeium",
6
6
  "eamodio.gitlens",
7
7
  "esbenp.prettier-vscode",
8
+ "formulahendry.code-runner",
8
9
  "foxundermoon.shell-format",
10
+ "github.codespaces",
9
11
  "github.vscode-github-actions",
10
12
  "golang.go",
11
- "google.geminicodeassist",
13
+ "gruntfuggly.todo-tree",
14
+ "mechatroner.rainbow-csv",
15
+ "mindaro-dev.file-downloader",
16
+ "ms-azuretools.vscode-containers",
17
+ "ms-azuretools.vscode-docker",
18
+ "ms-kubernetes-tools.vscode-kubernetes-tools",
12
19
  "ms-python.black-formatter",
13
20
  "ms-python.debugpy",
14
21
  "ms-python.python",
15
22
  "ms-python.vscode-pylance",
23
+ "ms-vscode-remote.remote-containers",
24
+ "oderwat.indent-rainbow",
25
+ "pleiades.java-extension-pack-jdk",
26
+ "ravioshankar.scala-gurus",
27
+ "redhat.java",
28
+ "redhat.vscode-xml",
29
+ "redhat.vscode-yaml",
30
+ "ritwickdey.liveserver",
31
+ "scala-lang.scala",
32
+ "scala-lang.scala-snippets",
33
+ "scalameta.metals",
34
+ "shardulm94.trailing-spaces",
16
35
  "streetsidesoftware.code-spell-checker",
17
- "tobermory.es6-string-html"
36
+ "tamasfe.even-better-toml",
37
+ "tobermory.es6-string-html",
38
+ "visualstudioexptteam.intellicode-api-usage-examples",
39
+ "visualstudioexptteam.vscodeintellicode",
40
+ "vmware.vscode-boot-dev-pack",
41
+ "vmware.vscode-spring-boot",
42
+ "vscjava.vscode-gradle",
43
+ "vscjava.vscode-java-debug",
44
+ "vscjava.vscode-java-dependency",
45
+ "vscjava.vscode-java-pack",
46
+ "vscjava.vscode-java-test",
47
+ "vscjava.vscode-maven",
48
+ "vscjava.vscode-spring-boot-dashboard",
49
+ "vscjava.vscode-spring-initializr"
18
50
  ]
19
51
  }
package/README.md CHANGED
@@ -68,7 +68,7 @@ Run dev client server
68
68
  npm run dev
69
69
  ```
70
70
  <!-- -->
71
- ## underpost ci/cd cli v2.8.7
71
+ ## underpost ci/cd cli v2.8.8
72
72
 
73
73
  ### Usage: `underpost [options] [command]`
74
74
  ```
@@ -80,17 +80,17 @@ Commands:
80
80
  new <app-name> Create a new project
81
81
  start [options] <deploy-id> [env] Start up server, build pipelines, or services
82
82
  clone [options] <uri> Clone github repository
83
- pull <path> <uri> Pull github repository
83
+ pull [options] <path> <uri> Pull github repository
84
84
  cmt [options] <path> <commit-type> [module-tag] [message] Commit github repository
85
85
  push [options] <path> <uri> Push github repository
86
86
  env <deploy-id> [env] Set environment variables files and conf related to <deploy-id>
87
- config <operator> [key] [value] Manage configuration, operators
87
+ config [options] <operator> [key] [value] Manage configuration, operators
88
88
  root Get npm root path
89
89
  cluster [options] [pod-name] Manage cluster, for default initialization base kind cluster
90
- deploy [options] <deploy-list> [env] Manage deployment, for default deploy development pods
90
+ deploy [options] [deploy-list] [env] Manage deployment, for default deploy development pods
91
91
  secret [options] <platform> Manage secrets
92
92
  dockerfile-image-build [options] Build image from Dockerfile
93
- dockerfile-pull-base-images Pull underpost dockerfile images requirements
93
+ dockerfile-pull-base-images [options] Pull underpost dockerfile images requirements
94
94
  install Fast import underpost npm dependencies
95
95
  db [options] <deploy-list> Manage databases
96
96
  script [options] <operator> <script-name> [script-value] Supports a number of built-in underpost global scripts and their preset life cycle events as well as arbitrary scripts
@@ -98,6 +98,8 @@ Commands:
98
98
  fs [options] [path] File storage management, for default upload file
99
99
  test [options] [deploy-list] Manage Test, for default run current underpost default test
100
100
  monitor [options] <deploy-id> [env] Monitor health server management
101
+ lxd [options] Lxd management
102
+ baremetal [options] Baremetal management
101
103
  help [command] display help for command
102
104
 
103
105
  ```
package/bin/db.js CHANGED
@@ -161,6 +161,7 @@ try {
161
161
  }
162
162
  break;
163
163
  case 'show-all':
164
+ // show dbs
164
165
  break;
165
166
  case 'show':
166
167
  break;
package/bin/deploy.js CHANGED
@@ -27,6 +27,7 @@ import {
27
27
  setUpProxyMaintenanceServer,
28
28
  writeEnv,
29
29
  getUnderpostRootPath,
30
+ buildCliDoc,
30
31
  } from '../src/server/conf.js';
31
32
  import { buildClient } from '../src/server/client-build.js';
32
33
  import { range, s4, setPad, timer, uniqueArray } from '../src/client/components/core/CommonJs.js';
@@ -37,10 +38,10 @@ import { JSONweb } from '../src/server/client-formatted.js';
37
38
 
38
39
  import { Xampp } from '../src/runtime/xampp/Xampp.js';
39
40
  import { ejs } from '../src/server/json-schema.js';
40
- import { buildCliDoc } from '../src/cli/index.js';
41
41
  import { getLocalIPv4Address, ip } from '../src/server/dns.js';
42
42
  import { Downloader } from '../src/server/downloader.js';
43
43
  import colors from 'colors';
44
+ import { program } from '../src/cli/index.js';
44
45
 
45
46
  colors.enable();
46
47
 
@@ -797,6 +798,13 @@ try {
797
798
  .replaceAll(`engine.version: '${version}'`, `engine.version: '${newVersion}'`),
798
799
  'utf8',
799
800
  );
801
+ fs.writeFileSync(
802
+ `./manifests/deployment/dd-template-development/deployment.yaml`,
803
+ fs
804
+ .readFileSync(`./manifests/deployment/dd-template-development/deployment.yaml`, 'utf8')
805
+ .replaceAll(`underpost:v${version}`, `underpost:v${newVersion}`),
806
+ 'utf8',
807
+ );
800
808
 
801
809
  if (fs.existsSync(`./.github/workflows/docker-image.yml`))
802
810
  fs.writeFileSync(
@@ -816,12 +824,15 @@ try {
816
824
  shellExec(`node bin/deploy update-dependencies`);
817
825
  shellExec(`auto-changelog`);
818
826
  shellExec(`node bin/build dd`);
819
- shellExec(`node bin deploy --build-manifest --sync --info-router --replicas 1 dd`);
820
- shellExec(`node bin deploy --build-manifest --sync --info-router --replicas 1 dd production`);
827
+ shellExec(`node bin deploy --kubeadm --build-manifest --sync --info-router --replicas 1 dd`);
828
+ shellExec(`node bin deploy --kubeadm --build-manifest --sync --info-router --replicas 1 dd production`);
821
829
  break;
822
830
  }
823
831
 
824
832
  case 'version-deploy': {
833
+ shellExec(
834
+ `underpost secret underpost --create-from-file /home/dd/engine/engine-private/conf/dd-cron/.env.production`,
835
+ );
825
836
  shellExec(`node bin/build dd conf`);
826
837
  shellExec(`git add . && cd ./engine-private && git add .`);
827
838
  shellExec(`node bin cmt . ci package-pwa-microservices-template`);
@@ -918,6 +929,16 @@ ${shellExec(`git log | grep Author: | sort -u`, { stdout: true }).split(`\n`).jo
918
929
  };
919
930
  DefaultConf.server[host][path].apiBaseProxyPath = '/';
920
931
  DefaultConf.server[host][path].apiBaseHost = 'www.nexodev.org';
932
+ } else if (confName === 'template') {
933
+ const host = 'default.net';
934
+ const path = '/';
935
+ DefaultConf.server[host][path].valkey = {
936
+ port: 6379,
937
+ host: 'valkey-service.default.svc.cluster.local',
938
+ };
939
+ // mongodb-0.mongodb-service
940
+ DefaultConf.server[host][path].db.host = 'mongodb://mongodb-service:27017';
941
+ confName = '';
921
942
  } else if (confName) {
922
943
  DefaultConf.client = JSON.parse(fs.readFileSync(`./engine-private/conf/${confName}/conf.client.json`, 'utf8'));
923
944
  DefaultConf.server = JSON.parse(fs.readFileSync(`./engine-private/conf/${confName}/conf.server.json`, 'utf8'));
@@ -1000,6 +1021,8 @@ EOF`);
1000
1021
  shellExec(`sudo chmod 700 ~/.ssh/`);
1001
1022
  shellExec(`sudo chmod 600 ~/.ssh/authorized_keys`);
1002
1023
  shellExec(`sudo chmod 644 ~/.ssh/known_hosts`);
1024
+ shellExec(`sudo chmod 600 ~/.ssh/id_rsa`);
1025
+ shellExec(`sudo chmod 600 /etc/ssh/ssh_host_ed25519_key`);
1003
1026
  shellExec(`chown -R ${user}:${user} ~/.ssh`);
1004
1027
 
1005
1028
  shellExec(`ufw allow ${port}/tcp`);
@@ -1136,7 +1159,7 @@ EOF`);
1136
1159
  }
1137
1160
 
1138
1161
  case 'cli-docs': {
1139
- buildCliDoc();
1162
+ buildCliDoc(program);
1140
1163
  break;
1141
1164
  }
1142
1165
 
@@ -1189,6 +1212,18 @@ EOF`);
1189
1212
  }
1190
1213
 
1191
1214
  case 'postgresql-14': {
1215
+ if (process.argv.includes('install')) {
1216
+ shellExec(`sudo dnf module reset postgresql -y`);
1217
+ shellExec(`sudo dnf -qy module disable postgresql`);
1218
+
1219
+ shellExec(`sudo systemctl stop postgresql-14`);
1220
+ shellExec(`sudo systemctl disable postgresql-14`);
1221
+
1222
+ shellExec(`sudo dnf remove -y postgresql14 postgresql14-server postgresql14-contrib`);
1223
+ shellExec(`sudo rm -rf /var/lib/pgsql`);
1224
+
1225
+ shellExec(`sudo dnf install postgresql14 postgresql14-server postgresql14-contrib -y`);
1226
+ }
1192
1227
  shellExec(`sudo /usr/pgsql-14/bin/postgresql-14-setup initdb`);
1193
1228
  shellExec(`sudo systemctl start postgresql-14`);
1194
1229
  shellExec(`sudo systemctl enable postgresql-14`);
@@ -1238,22 +1273,6 @@ EOF`);
1238
1273
  const netmask = process.env.NETMASK;
1239
1274
  const gatewayip = process.env.GATEWAY_IP;
1240
1275
 
1241
- let resources;
1242
- try {
1243
- resources = JSON.parse(
1244
- shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} boot-resources read`, {
1245
- silent: true,
1246
- stdout: true,
1247
- }),
1248
- ).map((o) => ({
1249
- id: o.id,
1250
- name: o.name,
1251
- architecture: o.architecture,
1252
- }));
1253
- } catch (error) {
1254
- logger.error(error);
1255
- }
1256
-
1257
1276
  const machineFactory = (m) => ({
1258
1277
  system_id: m.interface_set[0].system_id,
1259
1278
  mac_address: m.interface_set[0].mac_address,
@@ -1261,18 +1280,6 @@ EOF`);
1261
1280
  status_name: m.status_name,
1262
1281
  });
1263
1282
 
1264
- let machines;
1265
- try {
1266
- machines = JSON.parse(
1267
- shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} machines read`, {
1268
- stdout: true,
1269
- silent: true,
1270
- }),
1271
- ).map((m) => machineFactory(m));
1272
- } catch (error) {
1273
- logger.error(error);
1274
- }
1275
-
1276
1283
  if (process.argv.includes('db')) {
1277
1284
  // DROP, ALTER, CREATE, WITH ENCRYPTED
1278
1285
  // sudo -u <user> -h <host> psql <db-name>
@@ -1293,6 +1300,7 @@ EOF`);
1293
1300
  shellExec(`sudo -i -u postgres createdb -O "$DB_PG_MAAS_USER" "$DB_PG_MAAS_NAME"`);
1294
1301
 
1295
1302
  shellExec(`sudo -i -u postgres psql -c "\\l"`);
1303
+ process.exit(0);
1296
1304
  }
1297
1305
 
1298
1306
  if (process.argv.includes('ls')) {
@@ -1377,6 +1385,23 @@ EOF`);
1377
1385
 
1378
1386
  process.exit(0);
1379
1387
  }
1388
+
1389
+ if (process.argv.includes('restart')) {
1390
+ shellExec(`sudo snap restart maas.pebble`);
1391
+ let secs = 0;
1392
+ while (
1393
+ !(
1394
+ shellExec(`maas status`, { silent: true, disableLog: true, stdout: true })
1395
+ .split(' ')
1396
+ .filter((l) => l.match('inactive')).length === 1
1397
+ )
1398
+ ) {
1399
+ await timer(1000);
1400
+ console.log(`Waiting... (${++secs}s)`);
1401
+ }
1402
+ process.exit(0);
1403
+ }
1404
+
1380
1405
  // shellExec(`MAAS_ADMIN_USERNAME=${process.env.MAAS_ADMIN_USERNAME}`);
1381
1406
  // shellExec(`MAAS_ADMIN_EMAIL=${process.env.MAAS_ADMIN_EMAIL}`);
1382
1407
  // shellExec(`maas createadmin --username $MAAS_ADMIN_USERNAME --email $MAAS_ADMIN_EMAIL`);
@@ -1469,6 +1494,34 @@ EOF`);
1469
1494
  // ip link show
1470
1495
  // nmcli con show
1471
1496
 
1497
+ let resources;
1498
+ try {
1499
+ resources = JSON.parse(
1500
+ shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} boot-resources read`, {
1501
+ silent: true,
1502
+ stdout: true,
1503
+ }),
1504
+ ).map((o) => ({
1505
+ id: o.id,
1506
+ name: o.name,
1507
+ architecture: o.architecture,
1508
+ }));
1509
+ } catch (error) {
1510
+ logger.error(error);
1511
+ }
1512
+
1513
+ let machines;
1514
+ try {
1515
+ machines = JSON.parse(
1516
+ shellExec(`maas ${process.env.MAAS_ADMIN_USERNAME} machines read`, {
1517
+ stdout: true,
1518
+ silent: true,
1519
+ }),
1520
+ ).map((m) => machineFactory(m));
1521
+ } catch (error) {
1522
+ logger.error(error);
1523
+ }
1524
+
1472
1525
  let firmwarePath,
1473
1526
  tftpSubDir,
1474
1527
  kernelFilesPaths,
@@ -1613,21 +1666,6 @@ BOOT_ORDER=0x21`;
1613
1666
 
1614
1667
  shellExec(`node bin/deploy nfs`);
1615
1668
 
1616
- if (process.argv.includes('restart')) {
1617
- shellExec(`sudo snap restart maas.pebble`);
1618
- let secs = 0;
1619
- while (
1620
- !(
1621
- shellExec(`maas status`, { silent: true, disableLog: true, stdout: true })
1622
- .split(' ')
1623
- .filter((l) => l.match('inactive')).length === 1
1624
- )
1625
- ) {
1626
- await timer(1000);
1627
- console.log(`Waiting... (${++secs}s)`);
1628
- }
1629
- }
1630
-
1631
1669
  switch (process.argv[3]) {
1632
1670
  case 'rpi4mb':
1633
1671
  {
@@ -2140,38 +2178,76 @@ EOF`);
2140
2178
  break;
2141
2179
  }
2142
2180
 
2143
- default:
2181
+ case 'fastapi-models': {
2182
+ shellExec(`chmod +x ../full-stack-fastapi-template/backend/initial_data.sh`);
2183
+ shellExec(`../full-stack-fastapi-template/backend/initial_data.sh`);
2184
+ shellExec(`../full-stack-fastapi-template/backend/initial_data.sh`);
2144
2185
  break;
2186
+ }
2145
2187
 
2146
2188
  case 'fastapi': {
2189
+ // node bin/deploy fastapi reset
2190
+ // node bin/deploy fastapi reset build-back build-front secret run-back run-front
2147
2191
  // https://github.com/NonsoEchendu/full-stack-fastapi-project
2148
2192
  // https://github.com/fastapi/full-stack-fastapi-template
2149
2193
  const path = `../full-stack-fastapi-template`;
2150
- if (process.argv.includes('env')) {
2151
- const password = fs.readFileSync(`/home/dd/engine/engine-private/postgresql-password`, 'utf8');
2194
+ const VITE_API_URL = `http://localhost:8000`;
2152
2195
 
2153
- fs.writeFileSync(
2154
- `${path}/.env`,
2155
- fs
2156
- .readFileSync(`${path}/.env`, 'utf8')
2157
- .replace(`FIRST_SUPERUSER=admin@example.com`, `FIRST_SUPERUSER=development@underpost.net`)
2158
- .replace(`FIRST_SUPERUSER_PASSWORD=changethis`, `FIRST_SUPERUSER_PASSWORD=${password}`)
2159
- .replace(`SECRET_KEY=changethis`, `SECRET_KEY=${password}`)
2160
- .replace(`POSTGRES_DB=app`, `POSTGRES_DB=postgresdb`)
2161
- .replace(`POSTGRES_USER=postgres`, `POSTGRES_USER=admin`)
2162
- .replace(`POSTGRES_PASSWORD=changethis`, `POSTGRES_PASSWORD=${password}`),
2163
- 'utf8',
2164
- );
2165
- fs.writeFileSync(
2166
- `${path}/backend/app/core/db.py`,
2167
- fs
2168
- .readFileSync(`${path}/backend/app/core/db.py`, 'utf8')
2169
- .replace(` # from sqlmodel import SQLModel`, ` from sqlmodel import SQLModel`)
2170
- .replace(` # SQLModel.metadata.create_all(engine)`, ` SQLModel.metadata.create_all(engine)`),
2196
+ if (process.argv.includes('reset')) shellExec(`sudo rm -rf ${path}`);
2171
2197
 
2172
- 'utf8',
2173
- );
2198
+ if (!fs.existsSync(path))
2199
+ shellExec(`cd .. && git clone https://github.com/fastapi/full-stack-fastapi-template.git`);
2200
+
2201
+ shellExec(`cd ${path} && git checkout . && git clean -f -d`);
2202
+ const password = fs.readFileSync(`/home/dd/engine/engine-private/postgresql-password`, 'utf8');
2203
+
2204
+ fs.writeFileSync(
2205
+ `${path}/.env`,
2206
+ fs
2207
+ .readFileSync(`${path}/.env`, 'utf8')
2208
+ .replace(`FIRST_SUPERUSER=admin@example.com`, `FIRST_SUPERUSER=development@underpost.net`)
2209
+ .replace(`FIRST_SUPERUSER_PASSWORD=changethis`, `FIRST_SUPERUSER_PASSWORD=${password}`)
2210
+ .replace(`SECRET_KEY=changethis`, `SECRET_KEY=${password}`)
2211
+ .replace(`POSTGRES_DB=app`, `POSTGRES_DB=postgresdb`)
2212
+ .replace(`POSTGRES_USER=postgres`, `POSTGRES_USER=admin`)
2213
+ .replace(`POSTGRES_PASSWORD=changethis`, `POSTGRES_PASSWORD=${password}`),
2214
+ 'utf8',
2215
+ );
2216
+ fs.writeFileSync(
2217
+ `${path}/backend/app/core/db.py`,
2218
+ fs
2219
+ .readFileSync(`${path}/backend/app/core/db.py`, 'utf8')
2220
+ .replace(` # from sqlmodel import SQLModel`, ` from sqlmodel import SQLModel`)
2221
+ .replace(` # SQLModel.metadata.create_all(engine)`, ` SQLModel.metadata.create_all(engine)`),
2222
+
2223
+ 'utf8',
2224
+ );
2225
+
2226
+ fs.copySync(`./manifests/deployment/fastapi/initial_data.sh`, `${path}/backend/initial_data.sh`);
2227
+
2228
+ fs.writeFileSync(
2229
+ `${path}/frontend/Dockerfile`,
2230
+ fs
2231
+ .readFileSync(`${path}/frontend/Dockerfile`, 'utf8')
2232
+ .replace('ARG VITE_API_URL=${VITE_API_URL}', `ARG VITE_API_URL='${VITE_API_URL}'`),
2233
+ 'utf8',
2234
+ );
2235
+
2236
+ fs.writeFileSync(
2237
+ `${path}/frontend/.env`,
2238
+ fs
2239
+ .readFileSync(`${path}/frontend/.env`, 'utf8')
2240
+ .replace(`VITE_API_URL=http://localhost:8000`, `VITE_API_URL=${VITE_API_URL}`)
2241
+ .replace(`MAILCATCHER_HOST=http://localhost:1080`, `MAILCATCHER_HOST=http://localhost:1081`),
2242
+
2243
+ 'utf8',
2244
+ );
2245
+
2246
+ if (process.argv.includes('models')) {
2247
+ shellExec(`node bin/deploy fastapi-models`);
2248
+ break;
2174
2249
  }
2250
+
2175
2251
  if (process.argv.includes('build-back')) {
2176
2252
  const imageName = `fastapi-backend:latest`;
2177
2253
  shellExec(`sudo podman pull docker.io/library/python:3.10`);
@@ -2180,7 +2256,7 @@ EOF`);
2180
2256
  const args = [
2181
2257
  `node bin dockerfile-image-build --path ${path}/backend/`,
2182
2258
  `--image-name=${imageName} --image-path=${path}`,
2183
- `--podman-save --kind-load --no-cache`,
2259
+ `--podman-save --${process.argv.includes('kubeadm') ? 'kubeadm' : 'kind'}-load --reset`,
2184
2260
  ];
2185
2261
  shellExec(args.join(' '));
2186
2262
  }
@@ -2192,11 +2268,11 @@ EOF`);
2192
2268
  const args = [
2193
2269
  `node bin dockerfile-image-build --path ${path}/frontend/`,
2194
2270
  `--image-name=${imageName} --image-path=${path}`,
2195
- `--podman-save --kind-load --no-cache`,
2271
+ `--podman-save --${process.argv.includes('kubeadm') ? 'kubeadm' : 'kind'}-load --reset`,
2196
2272
  ];
2197
2273
  shellExec(args.join(' '));
2198
2274
  }
2199
- if (process.argv.includes('build') || process.argv.includes('secret')) {
2275
+ if (process.argv.includes('secret')) {
2200
2276
  {
2201
2277
  const secretSelector = `fastapi-postgres-credentials`;
2202
2278
  shellExec(`sudo kubectl delete secret ${secretSelector}`);
@@ -2230,6 +2306,10 @@ EOF`);
2230
2306
  }
2231
2307
 
2232
2308
  case 'conda': {
2309
+ // set -e
2310
+ // ENV_NAME="${1:-cuda_env}"
2311
+ // eval "$(conda shell.bash hook)"
2312
+ // conda activate "${ENV_NAME}"
2233
2313
  shellExec(
2234
2314
  `export PATH="/root/miniconda3/bin:$PATH" && conda init && conda config --set auto_activate_base false`,
2235
2315
  );
@@ -2241,7 +2321,10 @@ EOF`);
2241
2321
  // https://medium.com/@martin.hodges/deploying-kafka-on-a-kind-kubernetes-cluster-for-development-and-testing-purposes-ed7adefe03cb
2242
2322
  const imageName = `doughgle/kafka-kraft`;
2243
2323
  shellExec(`docker pull ${imageName}`);
2244
- shellExec(`kind load docker-image ${imageName}`);
2324
+ if (!process.argv.includes('kubeadm'))
2325
+ shellExec(
2326
+ `${process.argv.includes('kubeadm') ? `ctr -n k8s.io images import` : `kind load docker-image`} ${imageName}`,
2327
+ );
2245
2328
  shellExec(`kubectl create namespace kafka`);
2246
2329
  shellExec(`kubectl apply -f ./manifests/deployment/kafka/deployment.yaml`);
2247
2330
  // kubectl logs kafka-0 -n kafka | grep STARTED
@@ -2256,6 +2339,108 @@ EOF`);
2256
2339
  // kafka-console-consumer.sh --bootstrap-server kafka-svc:9092 --topic my-topic
2257
2340
  break;
2258
2341
  }
2342
+
2343
+ case 'nvidia-gpu-operator': {
2344
+ // https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html
2345
+ shellExec(`curl -s -L https://nvidia.github.io/libnvidia-container/stable/rpm/nvidia-container-toolkit.repo | \
2346
+ sudo tee /etc/yum.repos.d/nvidia-container-toolkit.repo`);
2347
+
2348
+ const NVIDIA_CONTAINER_TOOLKIT_VERSION = '1.17.8-1';
2349
+
2350
+ shellExec(`sudo dnf install -y \
2351
+ nvidia-container-toolkit-${NVIDIA_CONTAINER_TOOLKIT_VERSION} \
2352
+ nvidia-container-toolkit-base-${NVIDIA_CONTAINER_TOOLKIT_VERSION} \
2353
+ libnvidia-container-tools-${NVIDIA_CONTAINER_TOOLKIT_VERSION} \
2354
+ libnvidia-container1-${NVIDIA_CONTAINER_TOOLKIT_VERSION}`);
2355
+
2356
+ // https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/getting-started.html
2357
+
2358
+ shellExec(`kubectl create ns gpu-operator`);
2359
+ shellExec(`kubectl label --overwrite ns gpu-operator pod-security.kubernetes.io/enforce=privileged`);
2360
+
2361
+ shellExec(`helm repo add nvidia https://helm.ngc.nvidia.com/nvidia \
2362
+ && helm repo update`);
2363
+
2364
+ // shellExec(`helm install --wait --generate-name \
2365
+ // -n gpu-operator --create-namespace \
2366
+ // nvidia/gpu-operator \
2367
+ // --version=v25.3.1 \
2368
+ // --set toolkit.version=v1.16.1-ubi8`);
2369
+
2370
+ shellExec(`helm install --wait --generate-name \
2371
+ -n gpu-operator --create-namespace \
2372
+ nvidia/gpu-operator \
2373
+ --version=v25.3.1 \
2374
+ --set driver.enabled=false \
2375
+ --set driver.repository=nvcr.io/nvidia \
2376
+ --set cdi.enabled=true \
2377
+ --set cdi.default=true \
2378
+ --set toolkit.env[0].name=CONTAINERD_CONFIG \
2379
+ --set toolkit.env[0].value=/etc/containerd/config.toml \
2380
+ --set toolkit.env[1].name=CONTAINERD_SOCKET \
2381
+ --set toolkit.env[1].value=/run/containerd/containerd.sock \
2382
+ --set toolkit.env[2].name=CONTAINERD_RUNTIME_CLASS \
2383
+ --set toolkit.env[2].value=nvidia \
2384
+ --set-string toolkit.env[3].name=CONTAINERD_SET_AS_DEFAULT \
2385
+ --set-string toolkit.env[3].value=true`);
2386
+
2387
+ // Check gpu drivers
2388
+ shellExec(
2389
+ `break;kubectl get nodes -o json | jq '.items[].metadata.labels | keys | any(startswith("feature.node.kubernetes.io"))'`,
2390
+ );
2391
+ break;
2392
+ }
2393
+
2394
+ case 'kubeflow-spark-operator': {
2395
+ // Use case:
2396
+ // Data Processing Pipelines: Used for ETL tasks where Spark can handle large data volumes efficiently.
2397
+ // Real-Time Analytics: Processing data from streaming sources (e.g., Kafka) for real-time analytics.
2398
+ // Machine Learning and Data Science: Training and deploying machine learning models at scale using Spark MLlib.
2399
+
2400
+ shellExec(`helm repo add spark-operator https://kubeflow.github.io/spark-operator`);
2401
+ shellExec(`helm install spark-operator spark-operator/spark-operator \
2402
+ --namespace spark-operator \
2403
+ --create-namespace \
2404
+ --wait`);
2405
+
2406
+ const image = `spark:3.5.5`;
2407
+ shellExec(`sudo docker pull ${image}`);
2408
+ if (!process.argv.includes('kubeadm'))
2409
+ shellExec(
2410
+ `sudo ${
2411
+ process.argv.includes('kubeadm') ? `ctr -n k8s.io images import` : `kind load docker-image`
2412
+ } ${image}`,
2413
+ );
2414
+ shellExec(`kubectl apply -f ./manifests/deployment/spark/spark-pi-py.yaml`);
2415
+
2416
+ // Check the status of the Spark job:
2417
+ // kubectl get sparkapplications.sparkoperator.k8s.io -n default
2418
+ // kubectl get sparkapplication
2419
+
2420
+ // Check case log:
2421
+ // kubectl logs -f spark-pi-python-driver
2422
+ // kubectl logs -f spark-pi-python-driver | grep Pi
2423
+ // kubectl describe sparkapplication spark-gpu-test
2424
+
2425
+ // Uninstall:
2426
+ // kubectl delete sparkapplications.sparkoperator.k8s.io spark-pi-python -n default
2427
+ // helm delete spark-operator -n spark-operator
2428
+
2429
+ // Gpu plugins:
2430
+ // https://github.com/NVIDIA/spark-rapids
2431
+ // RAPIDS Accelerator
2432
+ break;
2433
+ }
2434
+
2435
+ case 'sbt': {
2436
+ // https://www.scala-sbt.org/1.x/docs/Installing-sbt-on-Linux.html
2437
+
2438
+ // sudo rm -f /etc/yum.repos.d/bintray-rpm.repo
2439
+ // curl -L https://www.scala-sbt.org/sbt-rpm.repo > sbt-rpm.repo
2440
+ // sudo mv sbt-rpm.repo /etc/yum.repos.d/
2441
+ // sudo yum install sbt
2442
+ break;
2443
+ }
2259
2444
  }
2260
2445
  } catch (error) {
2261
2446
  logger.error(error, error.stack);