underpost 2.85.0 → 2.85.7

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.
@@ -111,8 +111,10 @@ class UnderpostRepository {
111
111
  ) {
112
112
  if (!repoPath) repoPath = '.';
113
113
  if (options.msg) {
114
- let key = Object.keys(commitData).find((k) => k && options.msg.toLocaleLowerCase().match(k));
115
- if (!key) key == 'chore';
114
+ options.msg = options.msg.replaceAll('"', '').replaceAll(`'`, '').replaceAll('`', '');
115
+ let key = Object.keys(commitData).find((k) => k && options.msg.toLocaleLowerCase().slice(0, 16).match(k));
116
+ if (!key) key = Object.keys(commitData).find((k) => k && options.msg.toLocaleLowerCase().match(k));
117
+ if (!key || key === undefined) key = 'chore';
116
118
  shellExec(
117
119
  `underpost cmt ${repoPath} ${key} ${options.deployId ? options.deployId : `''`} '${options.msg.replaceAll(`${key}(${key}`, '')}'`,
118
120
  );
@@ -211,60 +213,50 @@ class UnderpostRepository {
211
213
  },
212
214
 
213
215
  /**
214
- * Creates a new Underpost project, service, or configuration.
215
- * @param {string} repositoryName - The name of the new project or service, or a deployId.
216
- * @param {object} [options={ dev: false, deployId: false, cluster: false, subConf: '' }] - Creation options.
217
- * @param {boolean} [options.dev=false] - If true, sets up a development project.
218
- * @param {boolean} [options.deployId=false] - If true, creates deploy ID configuration files.
219
- * @param {boolean} [options.cluster=false] - If true, creates cluster configuration files.
220
- * @param {string} [options.subConf=''] - If provided, creates a sub-configuration for a deployId.
221
- * @returns {Promise<void>} A promise that resolves when the operation is complete.
216
+ * Initializes a new Underpost repository, optionally setting up a deploy ID or sub-configuration.
217
+ * @param {string} [projectName=''] - The name of the project to create.
218
+ * @param {object} [options={ deployId: '', subConf: '', cluster: false, dev: false }] - Initialization options.
219
+ * @param {string} [options.deployId=''] - The deployment ID to set up.
220
+ * @param {string} [options.subConf=''] - The sub-configuration to create.
221
+ * @param {boolean} [options.cluster=false] - If true, sets up a clustered configuration.
222
+ * @param {boolean} [options.dev=false] - If true, uses development settings.
223
+ * @returns {Promise<boolean>} A promise that resolves when the initialization is complete.
222
224
  * @memberof UnderpostRepository
223
225
  */
224
- new(repositoryName, options = { dev: false, deployId: false, cluster: false, subConf: '' }) {
226
+ new(projectName, options = { deployId: '', subConf: '', cluster: false, dev: false }) {
225
227
  return new Promise(async (resolve, reject) => {
226
228
  try {
227
229
  await logger.setUpInfo();
228
230
  actionInitLog();
229
- if (options.subConf && typeof options.subConf === 'string') {
230
- const deployId = repositoryName;
231
- logger.info('Creating sub conf', {
232
- deployId,
233
- subConf: options.subConf,
234
- });
235
- fs.copySync(
236
- `./engine-private/conf/${deployId}/conf.server.json`,
237
- `./engine-private/conf/${deployId}/conf.server.dev.${options.subConf}.json`,
238
- );
239
- return resolve();
231
+ if (options.deployId) {
232
+ Config.deployIdFactory(options.deployId, options);
233
+ return resolve(true);
240
234
  }
241
- if (repositoryName === 'service')
242
- return resolve(
243
- await UnderpostStartUp.API.listenPortController(UnderpostStartUp.API.listenServerFactory(), ':'),
244
- );
245
- if (options.deployId === true) return Config.deployIdFactory(repositoryName, options);
246
- const npmRoot = getNpmRootPath();
247
- const underpostRoot = options?.dev === true ? '.' : `${npmRoot}/underpost`;
248
- const destFolder = `./${repositoryName}`;
249
- logger.info('Note: This process may take several minutes to complete');
250
- logger.info('build app', { destFolder });
251
- if (fs.existsSync(destFolder)) fs.removeSync(destFolder);
252
- fs.mkdirSync(destFolder, { recursive: true });
253
- if (!options.dev) {
254
- fs.copySync(underpostRoot, destFolder);
255
- fs.writeFileSync(
256
- `${destFolder}/.gitignore`,
257
- fs.readFileSync(`${underpostRoot}/.dockerignore`, 'utf8'),
258
- 'utf8',
259
- );
260
- shellExec(`cd ${destFolder} && git init && git add . && git commit -m "Base template implementation"`);
235
+ if (projectName) {
236
+ const npmRoot = getNpmRootPath();
237
+ const underpostRoot = options?.dev === true ? '.' : `${npmRoot}/underpost`;
238
+ const destFolder = `./${projectName}`;
239
+ logger.info('Note: This process may take several minutes to complete');
240
+ logger.info('build app', { destFolder });
241
+ if (fs.existsSync(destFolder)) fs.removeSync(destFolder);
242
+ fs.mkdirSync(destFolder, { recursive: true });
243
+ if (!options.dev) {
244
+ fs.copySync(underpostRoot, destFolder);
245
+ fs.writeFileSync(
246
+ `${destFolder}/.gitignore`,
247
+ fs.readFileSync(`${underpostRoot}/.dockerignore`, 'utf8'),
248
+ 'utf8',
249
+ );
250
+ shellExec(`cd ${destFolder} && git init && git add . && git commit -m "Base template implementation"`);
251
+ }
252
+ shellExec(`cd ${destFolder} && npm run build`);
253
+ shellExec(`cd ${destFolder} && npm run dev`);
261
254
  }
262
- shellExec(`cd ${destFolder} && npm run build`);
263
- shellExec(`cd ${destFolder} && npm run dev`);
264
- return resolve();
255
+ return resolve(true);
265
256
  } catch (error) {
257
+ console.log(error);
266
258
  logger.error(error, error.stack);
267
- return reject(error.message);
259
+ return reject(false);
268
260
  }
269
261
  });
270
262
  },
package/src/cli/run.js CHANGED
@@ -5,7 +5,14 @@
5
5
  */
6
6
 
7
7
  import { daemonProcess, getTerminalPid, openTerminal, pbcopy, shellCd, shellExec } from '../server/process.js';
8
- import { getNpmRootPath, getUnderpostRootPath, isDeployRunnerContext } from '../server/conf.js';
8
+ import {
9
+ awaitDeployMonitor,
10
+ Config,
11
+ getNpmRootPath,
12
+ getUnderpostRootPath,
13
+ isDeployRunnerContext,
14
+ writeEnv,
15
+ } from '../server/conf.js';
9
16
  import { actionInitLog, loggerFactory } from '../server/logger.js';
10
17
  import UnderpostTest from './test.js';
11
18
  import fs from 'fs-extra';
@@ -15,6 +22,7 @@ import UnderpostRootEnv from './env.js';
15
22
  import UnderpostRepository from './repository.js';
16
23
  import os from 'os';
17
24
  import Underpost from '../index.js';
25
+ import dotenv from 'dotenv';
18
26
 
19
27
  const logger = loggerFactory(import.meta);
20
28
 
@@ -44,6 +52,12 @@ class UnderpostRun {
44
52
  * @property {boolean} k3s - Whether to run in k3s mode.
45
53
  * @property {boolean} kubeadm - Whether to run in kubeadm mode.
46
54
  * @property {boolean} force - Whether to force the operation.
55
+ * @property {boolean} reset - Whether to reset the operation.
56
+ * @property {boolean} tls - Whether to use TLS.
57
+ * @property {string} tty - The TTY option for the container.
58
+ * @property {string} stdin - The stdin option for the container.
59
+ * @property {string} restartPolicy - The restart policy for the container.
60
+ * @property {boolean} terminal - Whether to open a terminal.
47
61
  * @memberof UnderpostRun
48
62
  */
49
63
  static DEFAULT_OPTION = {
@@ -59,6 +73,13 @@ class UnderpostRun {
59
73
  k3s: false,
60
74
  kubeadm: false,
61
75
  force: false,
76
+ reset: false,
77
+ tls: false,
78
+ tty: '',
79
+ stdin: '',
80
+ restartPolicy: '',
81
+ terminal: false,
82
+ devProxyPortOffset: 0,
62
83
  };
63
84
  /**
64
85
  * @static
@@ -106,13 +127,21 @@ class UnderpostRun {
106
127
  },
107
128
  /**
108
129
  * @method kill
109
- * @description Kills the process running on the specified port by finding its PID using `lsof -t -i:${path}`.
130
+ * @description Kills processes listening on the specified port(s). If the `path` contains a `+`, it treats it as a range of ports to kill.
110
131
  * @param {string} path - The input value, identifier, or path for the operation (used as the port number).
111
132
  * @param {Object} options - The default underpost runner options for customizing workflow
112
133
  * @memberof UnderpostRun
113
134
  */
114
- kill: (path, options = UnderpostRun.DEFAULT_OPTION) => {
115
- shellExec(`sudo kill -9 $(lsof -t -i:${path})`);
135
+ kill: (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
136
+ for (const _path of path.split(',')) {
137
+ if (_path.split('+')[1]) {
138
+ let [port, sumPortOffSet] = _path.split('+');
139
+ port = parseInt(port);
140
+ sumPortOffSet = parseInt(sumPortOffSet);
141
+ for (const sumPort of range(0, sumPortOffSet))
142
+ shellExec(`sudo kill -9 $(lsof -t -i:${parseInt(port) + parseInt(sumPort)})`);
143
+ } else shellExec(`sudo kill -9 $(lsof -t -i:${_path})`);
144
+ }
116
145
  },
117
146
  /**
118
147
  * @method secret
@@ -274,7 +303,7 @@ class UnderpostRun {
274
303
  * @param {Object} options - The default underpost runner options for customizing workflow
275
304
  * @memberof UnderpostRun
276
305
  */
277
- 'template-deploy': (path, options = UnderpostRun.DEFAULT_OPTION) => {
306
+ 'template-deploy': (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
278
307
  const baseCommand = options.dev ? 'node bin' : 'underpost';
279
308
  shellExec(`${baseCommand} run clean`);
280
309
  shellExec(
@@ -314,16 +343,25 @@ class UnderpostRun {
314
343
  },
315
344
  /**
316
345
  * @method pull
317
- * @description Cleans the core repository and pulls the latest content for `engine` and `engine-private` repositories from the remote.
346
+ * @description Clones or pulls updates for the `engine` and `engine-private` repositories into `/home/dd/engine` and `/home/dd/engine/engine-private`.
318
347
  * @param {string} path - The input value, identifier, or path for the operation.
319
348
  * @param {Object} options - The default underpost runner options for customizing workflow
320
349
  * @memberof UnderpostRun
321
350
  */
322
351
  pull: (path, options = UnderpostRun.DEFAULT_OPTION) => {
323
- shellCd(`/home/dd/engine`);
324
- shellExec(`node bin/deploy clean-core-repo`);
325
- shellExec(`underpost pull . ${process.env.GITHUB_USERNAME}/engine`);
326
- shellExec(`underpost pull ./engine-private ${process.env.GITHUB_USERNAME}/engine-private`);
352
+ if (!fs.existsSync(`/home/dd`) || !fs.existsSync(`/home/dd/engine`)) {
353
+ fs.mkdirSync(`/home/dd`, { recursive: true });
354
+ shellExec(`cd /home/dd && underpost clone ${process.env.GITHUB_USERNAME}/engine`);
355
+ } else {
356
+ shellExec(`underpost run clean`);
357
+ shellExec(`cd /home/dd/engine && underpost pull . ${process.env.GITHUB_USERNAME}/engine`);
358
+ }
359
+ if (!fs.existsSync(`/home/dd/engine/engine-private`))
360
+ shellExec(`cd /home/dd/engine && underpost clone ${process.env.GITHUB_USERNAME}/engine-private`);
361
+ else
362
+ shellExec(
363
+ `cd /home/dd/engine/engine-private && underpost pull . ${process.env.GITHUB_USERNAME}/engine-private`,
364
+ );
327
365
  },
328
366
  /**
329
367
  * @method release-deploy
@@ -412,7 +450,7 @@ class UnderpostRun {
412
450
 
413
451
  shellExec(
414
452
  `${baseCommand} deploy --kubeadm --build-manifest --sync --info-router --replicas ${
415
- replicas ?? 1
453
+ replicas ? replicas : 1
416
454
  } --node ${node}${image ? ` --image ${image}` : ''}${versions ? ` --versions ${versions}` : ''} dd ${env}`,
417
455
  );
418
456
 
@@ -433,6 +471,16 @@ class UnderpostRun {
433
471
  'ls-deployments': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
434
472
  console.table(await UnderpostDeploy.API.get(path, 'deployments'));
435
473
  },
474
+ /**
475
+ * @method ls-images
476
+ * @description Retrieves and logs a table of currently loaded Docker images in the 'kind-worker' node using `UnderpostDeploy.API.getCurrentLoadedImages`.
477
+ * @param {string} path - The input value, identifier, or path for the operation.
478
+ * @param {Object} options - The default underpost runner options for customizing workflow
479
+ * @memberof UnderpostRun
480
+ */
481
+ 'ls-images': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
482
+ console.table(UnderpostDeploy.API.getCurrentLoadedImages('kind-worker', false));
483
+ },
436
484
 
437
485
  /**
438
486
  * @method host-update
@@ -447,6 +495,43 @@ class UnderpostRun {
447
495
  shellExec(`${options.underpostRoot}/scripts/rocky-setup.sh --yes${options.dev ? ' --install-dev' : ``}`);
448
496
  },
449
497
 
498
+ /**
499
+ * @method dev-container
500
+ * @description Runs a development container pod named `underpost-dev-container` with specified volume mounts and opens a terminal to follow its logs.
501
+ * @param {string} path - The input value, identifier, or path for the operation (used as an optional command to run inside the container).
502
+ * @param {Object} options - The default underpost runner options for customizing workflow
503
+ * @memberof UnderpostRun
504
+ */
505
+ 'dev-container': async (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
506
+ options.dev = true;
507
+ const baseCommand = options.dev ? 'node bin' : 'underpost';
508
+ const baseClusterCommand = options.dev ? ' --dev' : '';
509
+ const currentImage = UnderpostDeploy.API.getCurrentLoadedImages('kind-worker', false).find((o) =>
510
+ o.IMAGE.match('underpost'),
511
+ );
512
+ const podName = `underpost-dev-container`;
513
+ if (!UnderpostDeploy.API.existsContainerFile({ podName: 'kind-worker', path: '/home/dd/engine' })) {
514
+ shellExec(`docker exec -i kind-worker bash -c "mkdir -p /home/dd"`);
515
+ shellExec(`docker cp /home/dd/engine kind-worker:/home/dd/engine`);
516
+ shellExec(`docker exec -i kind-worker bash -c "chown -R 1000:1000 /home/dd || true; chmod -R 755 /home/dd"`);
517
+ }
518
+ if (!currentImage) shellExec(`${baseCommand} dockerfile-pull-base-images${baseClusterCommand} --kind-load`);
519
+ // shellExec(`kubectl delete pod ${podName} --ignore-not-found`);
520
+ await UnderpostRun.RUNNERS['deploy-job']('', {
521
+ dev: true,
522
+ podName,
523
+ imageName: currentImage ? currentImage.image : `localhost/rockylinux9-underpost:${Underpost.version}`,
524
+ volumeHostPath: '/home/dd',
525
+ volumeMountPath: '/home/dd',
526
+ on: {
527
+ init: async () => {
528
+ // openTerminal(`kubectl logs -f ${podName}`);
529
+ },
530
+ },
531
+ args: [daemonProcess(path ? path : `cd /home/dd/engine && npm run test`)],
532
+ });
533
+ },
534
+
450
535
  /**
451
536
  * @method monitor
452
537
  * @description Monitors a specific pod (identified by `path`) for the existence of a file (`/await`), and performs conditional actions (like file copying and opening Firefox) when the file is removed.
@@ -564,10 +649,16 @@ class UnderpostRun {
564
649
  * @memberof UnderpostRun
565
650
  */
566
651
  'git-conf': (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
567
- const defaultUsername = UnderpostRootEnv.API.get('GITHUB_USERNAME', '', { disableLog: true });
568
- const defaultEmail = UnderpostRootEnv.API.get('GITHUB_EMAIL', '', { disableLog: true });
569
- const [username, email] = path && path.split(',').length > 0 ? path.split(',') : [defaultUsername, defaultEmail];
570
-
652
+ const defaultUsername = UnderpostRootEnv.API.get('GITHUB_USERNAME');
653
+ const defaultEmail = UnderpostRootEnv.API.get('GITHUB_EMAIL');
654
+ const validPath = path && path.split(',').length;
655
+ const [username, email] = validPath ? path.split(',') : [defaultUsername, defaultEmail];
656
+ if (validPath) {
657
+ UnderpostRootEnv.API.set('GITHUB_USERNAME', username);
658
+ UnderpostRootEnv.API.set('GITHUB_EMAIL', email);
659
+ UnderpostRootEnv.API.get('GITHUB_USERNAME');
660
+ UnderpostRootEnv.API.get('GITHUB_EMAIL');
661
+ }
571
662
  shellExec(
572
663
  `git config --global credential.helper "" && ` +
573
664
  `git config credential.helper "" && ` +
@@ -706,6 +797,120 @@ class UnderpostRun {
706
797
  UnderpostDeploy.API.switchTraffic(deployId, env, targetTraffic);
707
798
  },
708
799
 
800
+ /**
801
+ * @method dev
802
+ * @description Starts development servers for client, API, and proxy based on provided parameters (deployId, host, path, clientHostPort).
803
+ * @param {string} path - The input value, identifier, or path for the operation (formatted as `deployId,subConf,host,path,clientHostPort`).
804
+ * @param {Object} options - The default underpost runner options for customizing workflow
805
+ * @memberof UnderpostRun
806
+ */
807
+ dev: async (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
808
+ let [deployId, subConf, host, _path, clientHostPort] = path.split(',');
809
+ if (!deployId) deployId = 'dd-default';
810
+ if (!host) host = 'default.net';
811
+ if (!_path) _path = '/';
812
+ if (!clientHostPort) clientHostPort = 'localhost:4004';
813
+ if (!subConf) subConf = 'local';
814
+ if (options.reset && fs.existsSync(`./engine-private/conf/${deployId}`))
815
+ fs.removeSync(`./engine-private/conf/${deployId}`);
816
+ if (!fs.existsSync(`./engine-private/conf/${deployId}`)) Config.deployIdFactory(deployId, { subConf });
817
+ if (options.devProxyPortOffset) {
818
+ const envPath = `./engine-private/conf/${deployId}/.env.development`;
819
+ const envObj = dotenv.parse(fs.readFileSync(envPath, 'utf8'));
820
+ envObj.DEV_PROXY_PORT_OFFSET = options.devProxyPortOffset;
821
+ writeEnv(envPath, envObj);
822
+ }
823
+ shellExec(`node bin run dev-cluster expose`);
824
+ {
825
+ const cmd = `npm run dev-api ${deployId} ${subConf} ${host} ${_path} ${clientHostPort}${options.tls ? ' tls' : ''}`;
826
+ options.terminal ? openTerminal(cmd) : shellExec(cmd, { async: true });
827
+ }
828
+ await awaitDeployMonitor(true);
829
+ {
830
+ const cmd = `npm run dev-client ${deployId} ${subConf} ${host} ${_path} proxy${options.tls ? ' tls' : ''}`;
831
+ options.terminal
832
+ ? openTerminal(cmd)
833
+ : shellExec(cmd, {
834
+ async: true,
835
+ });
836
+ }
837
+ await awaitDeployMonitor(true);
838
+ shellExec(`npm run dev-proxy ${deployId} ${subConf} ${host} ${_path}${options.tls ? ' tls' : ''}`);
839
+ },
840
+
841
+ /**
842
+ * @method service
843
+ * @description Deploys and exposes specific services (like `mongo-express-service`) on the cluster, updating deployment configurations and monitoring status.
844
+ * @param {string} path - The input value, identifier, or path for the operation (formatted as `deployId,serviceId,host,path,replicas,image,node`).
845
+ * @param {Object} options - The default underpost runner options for customizing workflow
846
+ * @memberof UnderpostRun
847
+ */
848
+ service: async (path = '', options = UnderpostRun.DEFAULT_OPTION) => {
849
+ const env = options.dev ? 'development' : 'production';
850
+ const baseCommand = options.dev ? 'node bin' : 'underpost';
851
+ // const baseClusterCommand = options.dev ? ' --dev' : '';
852
+ shellCd(`/home/dd/engine`);
853
+ let [deployId, serviceId, host, _path, replicas, image, node] = path.split(',');
854
+ const services = fs.existsSync(`./engine-private/deploy/${deployId}/conf.services.json`)
855
+ ? JSON.parse(fs.readFileSync(`./engine-private/deploy/${deployId}/conf.services.json`, 'utf8'))
856
+ : [];
857
+ switch (serviceId) {
858
+ case 'mongo-express-service': {
859
+ let serviceData = services.findIndex((s) => s.serviceId === serviceId);
860
+ const payload = {
861
+ serviceId,
862
+ path: _path,
863
+ port: 8081,
864
+ host,
865
+ };
866
+ if (serviceData == -1) {
867
+ services.push(payload);
868
+ } else {
869
+ services[serviceData] = payload;
870
+ }
871
+ fs.writeFileSync(
872
+ `./engine-private/conf/${deployId}/conf.services.json`,
873
+ JSON.stringify(services, null, 4),
874
+ 'utf8',
875
+ );
876
+ shellExec(`kubectl delete svc mongo-express-service --ignore-not-found`);
877
+ shellExec(`kubectl delete deployment mongo-express --ignore-not-found`);
878
+ shellExec(`kubectl apply -f manifests/deployment/mongo-express/deployment.yaml`);
879
+
880
+ const success = await UnderpostTest.API.statusMonitor('mongo-express');
881
+
882
+ if (success) {
883
+ const versions = UnderpostDeploy.API.getCurrentTraffic(deployId) || 'blue';
884
+ if (!node) node = os.hostname();
885
+ shellExec(
886
+ `${baseCommand} deploy --kubeadm --build-manifest --sync --info-router --replicas ${
887
+ replicas ? replicas : 1
888
+ } --node ${node}${image ? ` --image ${image}` : ''}${versions ? ` --versions ${versions}` : ''} dd ${env}`,
889
+ );
890
+ shellExec(
891
+ `${baseCommand} deploy --kubeadm --disable-update-deployment ${deployId} ${env} --versions ${versions}`,
892
+ );
893
+ } else logger.error('Mongo Express deployment failed');
894
+ break;
895
+ }
896
+ }
897
+ },
898
+
899
+ /**
900
+ * @method release-cmt
901
+ * @description Commits and pushes a new release for the `engine` repository with a message indicating the new version.
902
+ * @param {string} path - The input value, identifier, or path for the operation.
903
+ * @param {Object} options - The default underpost runner options for customizing workflow
904
+ * @memberof UnderpostRun
905
+ */
906
+ 'release-cmt': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
907
+ shellExec(`underpost run pull`);
908
+ shellExec(`underpost run secret`);
909
+ shellCd(`/home/dd/engine`);
910
+ shellExec(`underpost cmt --empty . ci engine ' New engine release $(underpost --version)'`);
911
+ shellExec(`underpost push . ${process.env.GITHUB_USERNAME}/engine`);
912
+ },
913
+
709
914
  /**
710
915
  * @method sync-replica
711
916
  * @description Syncs a replica for the dd.router
@@ -794,6 +999,9 @@ class UnderpostRun {
794
999
  const volumeMountPath = options.volumeMountPath || path;
795
1000
  const volumeHostPath = options.volumeHostPath || path;
796
1001
  const enableVolumeMount = volumeHostPath && volumeMountPath;
1002
+ const tty = options.tty ? 'true' : 'false';
1003
+ const stdin = options.stdin ? 'true' : 'false';
1004
+ const restartPolicy = options.restartPolicy || 'Never';
797
1005
 
798
1006
  if (options.volumeType === 'dev') options.volumeType = 'FileOrCreate';
799
1007
  const volumeType =
@@ -807,15 +1015,17 @@ kind: Pod
807
1015
  metadata:
808
1016
  name: ${podName}
809
1017
  namespace: ${namespace}
1018
+ labels:
1019
+ app: ${podName}
810
1020
  spec:
811
- restartPolicy: Never
1021
+ restartPolicy: ${restartPolicy}
812
1022
  ${runtimeClassName ? ` runtimeClassName: ${runtimeClassName}` : ''}
813
1023
  containers:
814
1024
  - name: ${containerName}
815
1025
  image: ${imageName}
816
1026
  imagePullPolicy: IfNotPresent
817
- tty: true
818
- stdin: true
1027
+ tty: ${tty}
1028
+ stdin: ${stdin}
819
1029
  command: ${JSON.stringify(options.command ? options.command : ['/bin/bash', '-c'])}
820
1030
  ${
821
1031
  args.length > 0
@@ -851,7 +1061,7 @@ ${
851
1061
  : ''
852
1062
  }
853
1063
  EOF`;
854
- shellExec(`kubectl delete pod ${podName}`);
1064
+ shellExec(`kubectl delete pod ${podName} --ignore-not-found`);
855
1065
  console.log(cmd);
856
1066
  shellExec(cmd, { disableLog: true });
857
1067
  const successInstance = await UnderpostTest.API.statusMonitor(podName);
@@ -101,6 +101,7 @@ const cap = (str) =>
101
101
 
102
102
  const capFirst = (str) => str.charAt(0).toUpperCase() + str.slice(1);
103
103
 
104
+ // Other option: Array.from(new Set(arr))
104
105
  const uniqueArray = (arr) => arr.filter((item, pos) => arr.indexOf(item) == pos);
105
106
 
106
107
  const orderArrayFromAttrInt = (arr, attr, type) =>
@@ -35,8 +35,12 @@ const SocketIo = {
35
35
  // forceNew: true,
36
36
  // reconnectionAttempts: 'Infinity',
37
37
  // timeout: 10000,
38
- // withCredentials: true,
39
38
  // autoConnect: 5000,
39
+ // Custom auth socket io credentials:
40
+ withCredentials: true,
41
+ extraHeaders: {
42
+ // "my-custom-header": "abcd"
43
+ },
40
44
  transports: ['websocket', 'polling', 'flashsocket'],
41
45
  };
42
46
  // logger.error(`connect options:`, JSON.stringify(connectOptions, null, 4));