underpost 2.92.0 → 2.95.1

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 (35) hide show
  1. package/.github/workflows/pwa-microservices-template-page.cd.yml +5 -4
  2. package/README.md +4 -5
  3. package/bin/build.js +6 -1
  4. package/bin/deploy.js +2 -69
  5. package/cli.md +99 -92
  6. package/manifests/deployment/dd-default-development/deployment.yaml +4 -4
  7. package/manifests/deployment/dd-test-development/deployment.yaml +2 -2
  8. package/package.json +1 -1
  9. package/scripts/disk-clean.sh +216 -0
  10. package/scripts/ssh-cluster-info.sh +4 -3
  11. package/src/cli/cluster.js +1 -1
  12. package/src/cli/db.js +71 -80
  13. package/src/cli/deploy.js +77 -13
  14. package/src/cli/image.js +198 -133
  15. package/src/cli/index.js +59 -81
  16. package/src/cli/lxd.js +73 -74
  17. package/src/cli/monitor.js +20 -9
  18. package/src/cli/repository.js +86 -3
  19. package/src/cli/run.js +167 -63
  20. package/src/cli/ssh.js +351 -134
  21. package/src/index.js +1 -1
  22. package/src/monitor.js +11 -1
  23. package/src/server/backup.js +1 -1
  24. package/src/server/conf.js +1 -1
  25. package/src/server/dns.js +88 -1
  26. package/src/server/process.js +6 -1
  27. package/scripts/snap-clean.sh +0 -26
  28. package/src/client/public/default/plantuml/client-conf.svg +0 -1
  29. package/src/client/public/default/plantuml/client-schema.svg +0 -1
  30. package/src/client/public/default/plantuml/cron-conf.svg +0 -1
  31. package/src/client/public/default/plantuml/cron-schema.svg +0 -1
  32. package/src/client/public/default/plantuml/server-conf.svg +0 -1
  33. package/src/client/public/default/plantuml/server-schema.svg +0 -1
  34. package/src/client/public/default/plantuml/ssr-conf.svg +0 -1
  35. package/src/client/public/default/plantuml/ssr-schema.svg +0 -1
package/src/cli/deploy.js CHANGED
@@ -657,18 +657,28 @@ EOF`);
657
657
  * @param {string} env - Environment for which the status is being checked.
658
658
  * @param {string} traffic - Current traffic status for the deployment.
659
659
  * @param {Array<string>} ignoresNames - List of pod names to ignore.
660
+ * @param {string} [namespace='default'] - Kubernetes namespace for the deployment.
660
661
  * @returns {object} - Object containing the status of the deployment.
661
662
  * @memberof UnderpostDeploy
662
663
  */
663
- checkDeploymentReadyStatus(deployId, env, traffic, ignoresNames = []) {
664
+ async checkDeploymentReadyStatus(deployId, env, traffic, ignoresNames = [], namespace = 'default') {
664
665
  const cmd = `underpost config get container-status`;
665
- const pods = UnderpostDeploy.API.get(`${deployId}-${env}-${traffic}`);
666
+ const pods = UnderpostDeploy.API.get(`${deployId}-${env}-${traffic}`, 'pods', namespace);
666
667
  const readyPods = [];
667
668
  const notReadyPods = [];
668
669
  for (const pod of pods) {
669
670
  const { NAME } = pod;
670
671
  if (ignoresNames && ignoresNames.find((t) => NAME.trim().toLowerCase().match(t.trim().toLowerCase()))) continue;
671
- const out = shellExec(`sudo kubectl exec -i ${NAME} -- sh -c "${cmd}"`, { stdout: true, silent: true });
672
+ const out = await new Promise((resolve) => {
673
+ shellExec(`sudo kubectl exec -i ${NAME} -n ${namespace} -- sh -c "${cmd}"`, {
674
+ silent: true,
675
+ disableLog: true,
676
+ callback: function (code, stdout, stderr) {
677
+ return resolve(JSON.stringify({ code, stdout, stderr }));
678
+ },
679
+ });
680
+ });
681
+ pod.out = out;
672
682
  const ready = out.match(`${deployId}-${env}-running-deployment`);
673
683
  ready ? readyPods.push(pod) : notReadyPods.push(pod);
674
684
  }
@@ -893,15 +903,18 @@ ${renderHosts}`,
893
903
  * @param {string} env - Environment for which the ready status is being monitored.
894
904
  * @param {string} targetTraffic - Target traffic status for the deployment.
895
905
  * @param {Array<string>} ignorePods - List of pod names to ignore.
906
+ * @param {string} [namespace='default'] - Kubernetes namespace for the deployment.
907
+ * @param {string} [outLogType=''] - Type of log output.
896
908
  * @returns {object} - Object containing the ready status of the deployment.
897
909
  * @memberof UnderpostDeploy
898
910
  */
899
- async monitorReadyRunner(deployId, env, targetTraffic, ignorePods = []) {
911
+ async monitorReadyRunner(deployId, env, targetTraffic, ignorePods = [], namespace = 'default', outLogType = '') {
900
912
  let checkStatusIteration = 0;
901
913
  const checkStatusIterationMsDelay = 1000;
902
914
  const maxIterations = 500;
903
- const iteratorTag = `[${deployId}-${env}-${targetTraffic}]`;
904
- logger.info('Deployment init', { deployId, env, targetTraffic, checkStatusIterationMsDelay });
915
+ const deploymentId = `${deployId}-${env}-${targetTraffic}`;
916
+ const iteratorTag = `[${deploymentId}]`;
917
+ logger.info('Deployment init', { deployId, env, targetTraffic, checkStatusIterationMsDelay, namespace });
905
918
  const minReadyOk = 3;
906
919
  let readyOk = 0;
907
920
  let result = {
@@ -909,7 +922,7 @@ ${renderHosts}`,
909
922
  notReadyPods: [],
910
923
  readyPods: [],
911
924
  };
912
-
925
+ let lastMsg = {};
913
926
  while (readyOk < minReadyOk) {
914
927
  if (checkStatusIteration >= maxIterations) {
915
928
  logger.error(
@@ -917,30 +930,81 @@ ${renderHosts}`,
917
930
  );
918
931
  break;
919
932
  }
920
- result = UnderpostDeploy.API.checkDeploymentReadyStatus(deployId, env, targetTraffic, ignorePods);
933
+ result = await UnderpostDeploy.API.checkDeploymentReadyStatus(
934
+ deployId,
935
+ env,
936
+ targetTraffic,
937
+ ignorePods,
938
+ namespace,
939
+ );
921
940
  if (result.ready === true) {
922
941
  readyOk++;
923
942
  logger.info(`${iteratorTag} | Deployment ready. Verification number: ${readyOk}`);
943
+ for (const pod of result.readyPods) {
944
+ const { NAME } = pod;
945
+ lastMsg[NAME] = 'Deployment ready';
946
+ console.log(
947
+ 'Target pod:',
948
+ NAME[NAME.match('green') ? 'bgGreen' : 'bgBlue'].bold.black,
949
+ '| Status:',
950
+ lastMsg[NAME].bold.magenta,
951
+ );
952
+ }
953
+ }
954
+
955
+ switch (outLogType) {
956
+ case 'underpost': {
957
+ let indexOf = -1;
958
+ for (const pod of result.notReadyPods) {
959
+ indexOf++;
960
+ const { NAME, out } = pod;
961
+
962
+ if (out.match('not') && out.match('found') && checkStatusIteration <= 20 && out.match(deploymentId))
963
+ lastMsg[NAME] = 'Starting deployment';
964
+ else if (out.match('not') && out.match('found') && checkStatusIteration <= 20 && out.match('underpost'))
965
+ lastMsg[NAME] = 'Installing underpost cli';
966
+ else if (out.match('not') && out.match('found') && checkStatusIteration <= 20 && out.match('task'))
967
+ lastMsg[NAME] = 'Initializing setup task';
968
+ else if (out.match('Empty environment variables')) lastMsg[NAME] = 'Setup environment';
969
+ else if (out.match(`${deployId}-${env}-build-deployment`)) lastMsg[NAME] = 'Building apps/services';
970
+ else if (out.match(`${deployId}-${env}-initializing-deployment`))
971
+ lastMsg[NAME] = 'Initializing apps/services';
972
+ else if (!lastMsg[NAME]) lastMsg[NAME] = `Waiting for status`;
973
+
974
+ console.log(
975
+ 'Target pod:',
976
+ NAME[NAME.match('green') ? 'bgGreen' : 'bgBlue'].bold.black,
977
+ '| Status:',
978
+ lastMsg[NAME].bold.magenta,
979
+ );
980
+ }
981
+ }
924
982
  }
925
983
  await timer(checkStatusIterationMsDelay);
926
984
  checkStatusIteration++;
927
985
  logger.info(
928
- `${iteratorTag} | Deployment in progress... | Delay number check iterations: ${checkStatusIteration}`,
986
+ `${iteratorTag} | Deployment in progress... | Delay number monitor iterations: ${checkStatusIteration}`,
929
987
  );
930
988
  }
931
- logger.info(`${iteratorTag} | Deployment ready. | Total delay number check iterations: ${checkStatusIteration}`);
989
+ logger.info(
990
+ `${iteratorTag} | Deployment ready. | Total delay number monitor iterations: ${checkStatusIteration}`,
991
+ );
932
992
  return result;
933
993
  },
934
994
 
935
995
  /**
936
996
  * Retrieves the currently loaded images in the Kubernetes cluster.
997
+ * @param {string} [node='kind-worker'] - Node name to check for loaded images.
998
+ * @param {object} options - Options for the image retrieval.
999
+ * @param {boolean} options.spec - Whether to retrieve images from the pod specifications.
1000
+ * @param {string} options.namespace - Kubernetes namespace to filter pods.
937
1001
  * @returns {Array<object>} - Array of objects containing pod names and their corresponding images.
938
1002
  * @memberof UnderpostDeploy
939
1003
  */
940
- getCurrentLoadedImages(node = 'kind-worker', specContainers = false) {
941
- if (specContainers) {
1004
+ getCurrentLoadedImages(node = 'kind-worker', options = { spec: false, namespace: '' }) {
1005
+ if (options.spec) {
942
1006
  const raw = shellExec(
943
- `kubectl get pods --all-namespaces -o=jsonpath='{range .items[*]}{"\\n"}{.metadata.namespace}{"/"}{.metadata.name}{":\\t"}{range .spec.containers[*]}{.image}{", "}{end}{end}'`,
1007
+ `kubectl get pods ${options.namespace ? `--namespace ${options.namespace}` : `--all-namespaces`} -o=jsonpath='{range .items[*]}{"\\n"}{.metadata.namespace}{"/"}{.metadata.name}{":\\t"}{range .spec.containers[*]}{.image}{", "}{end}{end}'`,
944
1008
  {
945
1009
  stdout: true,
946
1010
  silent: true,
package/src/cli/image.js CHANGED
@@ -24,143 +24,208 @@ const logger = loggerFactory(import.meta);
24
24
  */
25
25
  class UnderpostImage {
26
26
  static API = {
27
- dockerfile: {
28
- /**
29
- * @method pullBaseImages
30
- * @description Pulls base images and builds a 'rockylinux9-underpost' image,
31
- * then loads it into the specified Kubernetes cluster type (Kind, Kubeadm, or K3s).
32
- * @param {object} options - Options for pulling and loading images.
33
- * @param {boolean} [options.kindLoad=false] - If true, load image into Kind cluster.
34
- * @param {boolean} [options.kubeadmLoad=false] - If true, load image into Kubeadm cluster.
35
- * @param {boolean} [options.k3sLoad=false] - If true, load image into K3s cluster.
36
- * @param {string} [options.path=false] - Path to the Dockerfile context.
37
- * @param {boolean} [options.dev=false] - If true, use development mode.
38
- * @param {string} [options.version=''] - Version tag for the image.
39
- * @memberof UnderpostImage
40
- */
41
- pullBaseImages(
42
- options = {
43
- kindLoad: false,
44
- kubeadmLoad: false,
45
- k3sLoad: false,
46
- path: false,
47
- dev: false,
48
- version: '',
49
- },
50
- ) {
51
- // shellExec(`sudo podman pull docker.io/library/debian:buster`);
52
- shellExec(`sudo podman pull docker.io/library/rockylinux:9`);
53
- const baseCommand = options.dev ? 'node bin' : 'underpost';
54
- const baseCommandOption = options.dev ? ' --dev' : '';
55
- const IMAGE_NAME = `rockylinux9-underpost`;
56
- const IMAGE_NAME_FULL = `${IMAGE_NAME}:${options.version ? options.version : Underpost.version}`;
57
- let LOAD_TYPE = '';
58
- if (options.kindLoad === true) {
59
- LOAD_TYPE = `--kind-load`;
60
- } else if (options.kubeadmLoad === true) {
61
- LOAD_TYPE = `--kubeadm-load`;
62
- } else if (options.k3sLoad === true) {
63
- // Handle K3s load type
64
- LOAD_TYPE = `--k3s-load`;
27
+ /**
28
+ * @method pullBaseImages
29
+ * @description Pulls base images and builds a 'rockylinux9-underpost' image,
30
+ * then loads it into the specified Kubernetes cluster type (Kind, Kubeadm, or K3s).
31
+ * @param {object} options - Options for pulling and loading images.
32
+ * @param {boolean} [options.kind=false] - If true, load image into Kind cluster.
33
+ * @param {boolean} [options.kubeadm=false] - If true, load image into Kubeadm cluster.
34
+ * @param {boolean} [options.k3s=false] - If true, load image into K3s cluster.
35
+ * @param {string} [options.path=false] - Path to the Dockerfile context.
36
+ * @param {boolean} [options.dev=false] - If true, use development mode.
37
+ * @param {string} [options.version=''] - Version tag for the image.
38
+ * @param {string} [options.imageName=''] - Custom name for the image.
39
+ * @memberof UnderpostImage
40
+ */
41
+ pullBaseImages(
42
+ options = {
43
+ kind: false,
44
+ kubeadm: false,
45
+ k3s: false,
46
+ path: false,
47
+ dev: false,
48
+ version: '',
49
+ imageName: '',
50
+ },
51
+ ) {
52
+ shellExec(`sudo podman pull docker.io/library/rockylinux:9`);
53
+ const baseCommand = options.dev ? 'node bin' : 'underpost';
54
+ const baseCommandOption = options.dev ? ' --dev' : '';
55
+ const IMAGE_NAME = options.imageName
56
+ ? `options.imageName${options.version ? `:${options.version}` : ''}`
57
+ : `rockylinux9-underpost:${options.version ? options.version : Underpost.version}`;
58
+ let LOAD_TYPE = '';
59
+ if (options.kind === true) LOAD_TYPE = `--kind`;
60
+ else if (options.kubeadm === true) LOAD_TYPE = `--kubeadm`;
61
+ else if (options.k3s === true) LOAD_TYPE = `--k3s`;
62
+ shellExec(
63
+ `${baseCommand} image${baseCommandOption} --build --podman-save --reset --image-path=. --path ${
64
+ options.path ? options.path : getUnderpostRootPath()
65
+ } --image-name=${IMAGE_NAME} ${LOAD_TYPE}`,
66
+ );
67
+ },
68
+ /**
69
+ * @method build
70
+ * @description Builds a Docker image using Podman, optionally saves it as a tar archive,
71
+ * and loads it into a specified Kubernetes cluster (Kind, Kubeadm, or K3s).
72
+ * @param {object} options - Options for building and loading images.
73
+ * @param {string} [options.path=''] - The path to the directory containing the Dockerfile.
74
+ * @param {string} [options.imageName=''] - The name and tag for the image (e.g., 'my-app:latest').
75
+ * @param {string} [options.version=''] - Version tag for the image.
76
+ * @param {string} [options.imagePath=''] - Directory to save the image tar file.
77
+ * @param {string} [options.dockerfileName=''] - Name of the Dockerfile (defaults to 'Dockerfile').
78
+ * @param {boolean} [options.podmanSave=false] - If true, save the image as a tar archive using Podman.
79
+ * @param {boolean} [options.kind=false] - If true, load the image archive into a Kind cluster.
80
+ * @param {boolean} [options.kubeadm=false] - If true, load the image archive into a Kubeadm cluster (uses 'ctr').
81
+ * @param {boolean} [options.k3s=false] - If true, load the image archive into a K3s cluster (uses 'k3s ctr').
82
+ * @param {boolean} [options.secrets=false] - If true, load secrets from the .env file for the build.
83
+ * @param {string} [options.secretsPath=''] - Custom path to the .env file for secrets.
84
+ * @param {boolean} [options.reset=false] - If true, perform a no-cache build.
85
+ * @param {boolean} [options.dev=false] - If true, use development mode.
86
+ * @memberof UnderpostImage
87
+ */
88
+ build(
89
+ options = {
90
+ path: '',
91
+ imageName: '',
92
+ version: '',
93
+ imagePath: '',
94
+ dockerfileName: '',
95
+ podmanSave: false,
96
+ kind: false,
97
+ kubeadm: false,
98
+ k3s: false,
99
+ secrets: false,
100
+ secretsPath: '',
101
+ reset: false,
102
+ dev: false,
103
+ },
104
+ ) {
105
+ let {
106
+ path,
107
+ imageName,
108
+ version,
109
+ imagePath,
110
+ dockerfileName,
111
+ podmanSave,
112
+ secrets,
113
+ secretsPath,
114
+ kind,
115
+ kubeadm,
116
+ k3s,
117
+ reset,
118
+ dev,
119
+ } = options;
120
+ if (!path) path = '.';
121
+ if (!imageName) imageName = `rockylinux9-underpost:${Underpost.version}`;
122
+ if (!version) version = 'latest';
123
+ version = imageName && imageName.match(':') ? '' : `:${version}`;
124
+ const podManImg = `localhost/${imageName}${version}`;
125
+ if (imagePath && typeof imagePath === 'string' && !fs.existsSync(imagePath))
126
+ fs.mkdirSync(imagePath, { recursive: true });
127
+ const tarFile = `${imagePath}/${imageName.replace(':', '_')}.tar`;
128
+ let secretsInput = ' ';
129
+ let secretDockerInput = '';
130
+ let cache = '';
131
+ if (secrets === true) {
132
+ const envObj = dotenv.parse(
133
+ fs.readFileSync(
134
+ secretsPath && typeof secretsPath === 'string' ? secretsPath : `${getNpmRootPath()}/underpost/.env`,
135
+ 'utf8',
136
+ ),
137
+ );
138
+ for (const key of Object.keys(envObj)) {
139
+ secretsInput += ` && export ${key}="${envObj[key]}" `; // Example: $(cat gitlab-token.txt)
140
+ secretDockerInput += ` --secret id=${key},env=${key} \ `;
65
141
  }
66
-
142
+ }
143
+ if (reset === true) cache += ' --rm --no-cache';
144
+ if (path && typeof path === 'string')
67
145
  shellExec(
68
- `${baseCommand} dockerfile-image-build${baseCommandOption} --podman-save --reset --image-path=. --path ${
69
- options.path ?? getUnderpostRootPath()
70
- } --image-name=${IMAGE_NAME_FULL} ${LOAD_TYPE}`,
146
+ `cd ${path}${secretsInput}&& sudo podman build -f ./${
147
+ dockerfileName && typeof dockerfileName === 'string' ? dockerfileName : 'Dockerfile'
148
+ } -t ${imageName} --pull=never --cap-add=CAP_AUDIT_WRITE${cache}${secretDockerInput} --network host`,
71
149
  );
72
- },
73
- /**
74
- * @method build
75
- * @description Builds a Docker image using Podman, optionally saves it as a tar archive,
76
- * and loads it into a specified Kubernetes cluster (Kind, Kubeadm, or K3s).
77
- * @param {object} options - Options for building and loading images.
78
- * @param {string} [options.path=''] - The path to the directory containing the Dockerfile.
79
- * @param {string} [options.imageName=''] - The name and tag for the image (e.g., 'my-app:latest').
80
- * @param {string} [options.imagePath=''] - Directory to save the image tar file.
81
- * @param {string} [options.dockerfileName=''] - Name of the Dockerfile (defaults to 'Dockerfile').
82
- * @param {boolean} [options.podmanSave=false] - If true, save the image as a tar archive using Podman.
83
- * @param {boolean} [options.kindLoad=false] - If true, load the image archive into a Kind cluster.
84
- * @param {boolean} [options.kubeadmLoad=false] - If true, load the image archive into a Kubeadm cluster (uses 'ctr').
85
- * @param {boolean} [options.k3sLoad=false] - If true, load the image archive into a K3s cluster (uses 'k3s ctr').
86
- * @param {boolean} [options.secrets=false] - If true, load secrets from the .env file for the build.
87
- * @param {string} [options.secretsPath=''] - Custom path to the .env file for secrets.
88
- * @param {boolean} [options.reset=false] - If true, perform a no-cache build.
89
- * @param {boolean} [options.dev=false] - If true, use development mode.
90
- * @memberof UnderpostImage
91
- */
92
- build(
93
- options = {
94
- path: '',
95
- imageName: '',
96
- imagePath: '',
97
- dockerfileName: '',
98
- podmanSave: false,
99
- kindLoad: false,
100
- kubeadmLoad: false,
101
- k3sLoad: false,
102
- secrets: false,
103
- secretsPath: '',
104
- reset: false,
105
- dev: false,
106
- },
107
- ) {
108
- let {
109
- path,
110
- imageName,
111
- imagePath,
112
- dockerfileName,
113
- podmanSave,
114
- secrets,
115
- secretsPath,
116
- kindLoad,
117
- kubeadmLoad,
118
- k3sLoad,
119
- reset,
120
- dev,
121
- } = options;
122
- if (!path) path = '.';
123
- const podManImg = `localhost/${imageName}`;
124
- if (imagePath && typeof imagePath === 'string' && !fs.existsSync(imagePath))
125
- fs.mkdirSync(imagePath, { recursive: true });
126
- const tarFile = `${imagePath}/${imageName.replace(':', '_')}.tar`;
127
- let secretsInput = ' ';
128
- let secretDockerInput = '';
129
- let cache = '';
130
- if (secrets === true) {
131
- const envObj = dotenv.parse(
132
- fs.readFileSync(
133
- secretsPath && typeof secretsPath === 'string' ? secretsPath : `${getNpmRootPath()}/underpost/.env`,
134
- 'utf8',
135
- ),
136
- );
137
- for (const key of Object.keys(envObj)) {
138
- secretsInput += ` && export ${key}="${envObj[key]}" `; // Example: $(cat gitlab-token.txt)
139
- secretDockerInput += ` --secret id=${key},env=${key} \ `;
140
- }
141
- }
142
- if (reset === true) cache += ' --rm --no-cache';
143
- if (path && typeof path === 'string')
144
- shellExec(
145
- `cd ${path}${secretsInput}&& sudo podman build -f ./${
146
- dockerfileName && typeof dockerfileName === 'string' ? dockerfileName : 'Dockerfile'
147
- } -t ${imageName} --pull=never --cap-add=CAP_AUDIT_WRITE${cache}${secretDockerInput} --network host`,
148
- );
149
150
 
150
- if (podmanSave === true) {
151
- if (fs.existsSync(tarFile)) fs.removeSync(tarFile);
152
- shellExec(`podman save -o ${tarFile} ${podManImg}`);
153
- }
154
- if (kindLoad === true) shellExec(`sudo kind load image-archive ${tarFile}`);
155
- if (kubeadmLoad === true) {
156
- // Use 'ctr' for Kubeadm
157
- shellExec(`sudo ctr -n k8s.io images import ${tarFile}`);
158
- }
159
- if (k3sLoad === true) {
160
- // Use 'k3s ctr' for K3s
161
- shellExec(`sudo k3s ctr images import ${tarFile}`);
162
- }
163
- },
151
+ if (podmanSave === true) {
152
+ if (fs.existsSync(tarFile)) fs.removeSync(tarFile);
153
+ shellExec(`podman save -o ${tarFile} ${podManImg}`);
154
+ }
155
+ if (kind === true) shellExec(`sudo kind load image-archive ${tarFile}`);
156
+ else if (kubeadm === true) shellExec(`sudo ctr -n k8s.io images import ${tarFile}`);
157
+ else if (k3s === true) shellExec(`sudo k3s ctr images import ${tarFile}`);
158
+ },
159
+ /**
160
+ * @method list
161
+ * @description Lists currently loaded Docker images in the specified Kubernetes cluster node.
162
+ * @param {object} options - Options for listing loaded images.
163
+ * @param {string} [options.nodeName='kind-worker'] - The name of the node to query.
164
+ * @param {string} [options.namespace=''] - The namespace to filter images (if applicable).
165
+ * @param {boolean} [options.spec=false] - If true, include detailed specifications of each image.
166
+ * @param {boolean} [options.log=false] - If true, log the list of images to the console.
167
+ * @param {boolean} [options.k3s=false] - If true, list images from a K3s cluster.
168
+ * @param {boolean} [options.kubeadm=false] - If true, list images from a Kubeadm cluster.
169
+ * @param {boolean} [options.kind=false] - If true, list images from a Kind cluster.
170
+ * @returns {Array} - An array of loaded images information.
171
+ * @memberof UnderpostImage
172
+ */
173
+ list(options = { nodeName: '', namespace: '', spec: false, log: false, k3s: false, kubeadm: false, kind: false }) {
174
+ if ((options.kubeadm === true || options.k3s === true) && !options.nodeName)
175
+ options.nodeName = shellExec('echo $HOSTNAME', { stdout: true, silent: true }).trim();
176
+ const list = Underpost.deploy.getCurrentLoadedImages(
177
+ options.nodeName ? options.nodeName : 'kind-worker',
178
+ options,
179
+ );
180
+ if (options.log) console.table(list);
181
+ return list;
182
+ },
183
+ /**
184
+ * @method rm
185
+ * @description Removes a specified Docker image from the specified Kubernetes cluster type (Kind, Kubeadm, or K3s).
186
+ * @param {object} options - Options for removing the image.
187
+ * @param {string} [options.imageName=''] - The name and tag of the image to be removed.
188
+ * @param {boolean} [options.k3s=false] - If true, remove the image from a K3s cluster.
189
+ * @param {boolean} [options.kubeadm=false] - If true, remove the image from a Kubeadm cluster.
190
+ * @param {boolean} [options.kind=false] - If true, remove the image from a Kind cluster.
191
+ * @memberof UnderpostImage
192
+ */
193
+ rm(options = { imageName: '', k3s: false, kubeadm: false, kind: false }) {
194
+ let { imageName, k3s, kubeadm, kind } = options;
195
+ if (kind === true) {
196
+ shellExec(`docker exec -i kind-control-plane crictl rmi ${imageName}`);
197
+ shellExec(`docker exec -i kind-worker crictl rmi ${imageName}`);
198
+ } else if (kubeadm === true) {
199
+ shellExec(`crictl rmi ${imageName}`);
200
+ } else if (k3s === true) {
201
+ shellExec(`sudo k3s ctr images rm ${imageName}`);
202
+ }
203
+ },
204
+ /**
205
+ * @method pullDockerHubImage
206
+ * @description Pulls a Docker image from Docker Hub and loads it into the specified Kubernetes cluster type (Kind, Kubeadm, or K3s).
207
+ * @param {object} options - Options for pulling and loading the image.
208
+ * @param {boolean} [options.k3s=false] - If true, load the image into a K3s cluster.
209
+ * @param {boolean} [options.kubeadm=false] - If true, load the image into a Kubeadm cluster.
210
+ * @param {boolean} [options.kind=false] - If true, load the image into a Kind cluster.
211
+ * @param {string} [options.dockerhubImage=''] - The name of the Docker Hub image to be pulled.
212
+ * @param {string} [options.version=''] - The version tag of the image to be pulled.
213
+ * @memberof UnderpostImage
214
+ */
215
+ pullDockerHubImage(options = { k3s: false, kubeadm: false, kind: false, dockerhubImage: '', version: '' }) {
216
+ if (options.dockerhubImage === 'underpost') {
217
+ options.dockerhubImage = 'underpost/underpost-engine';
218
+ if (!options.version) options.version = Underpost.version;
219
+ }
220
+ if (!options.version) options.version = 'latest';
221
+ const version = options.dockerhubImage && options.dockerhubImage.match(':') ? '' : `:${options.version}`;
222
+ const image = `${options.dockerhubImage}${version}`;
223
+ if (options.kind === true) {
224
+ shellExec(`docker pull ${image}`);
225
+ shellExec(`sudo kind load docker-image ${image}`);
226
+ } else {
227
+ shellExec(`sudo crictl pull ${image}`);
228
+ }
164
229
  },
165
230
  };
166
231
  }