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.
- package/.github/workflows/pwa-microservices-template-page.cd.yml +5 -4
- package/README.md +4 -5
- package/bin/build.js +6 -1
- package/bin/deploy.js +2 -69
- package/cli.md +99 -92
- package/manifests/deployment/dd-default-development/deployment.yaml +4 -4
- package/manifests/deployment/dd-test-development/deployment.yaml +2 -2
- package/package.json +1 -1
- package/scripts/disk-clean.sh +216 -0
- package/scripts/ssh-cluster-info.sh +4 -3
- package/src/cli/cluster.js +1 -1
- package/src/cli/db.js +71 -80
- package/src/cli/deploy.js +77 -13
- package/src/cli/image.js +198 -133
- package/src/cli/index.js +59 -81
- package/src/cli/lxd.js +73 -74
- package/src/cli/monitor.js +20 -9
- package/src/cli/repository.js +86 -3
- package/src/cli/run.js +167 -63
- package/src/cli/ssh.js +351 -134
- package/src/index.js +1 -1
- package/src/monitor.js +11 -1
- package/src/server/backup.js +1 -1
- package/src/server/conf.js +1 -1
- package/src/server/dns.js +88 -1
- package/src/server/process.js +6 -1
- package/scripts/snap-clean.sh +0 -26
- package/src/client/public/default/plantuml/client-conf.svg +0 -1
- package/src/client/public/default/plantuml/client-schema.svg +0 -1
- package/src/client/public/default/plantuml/cron-conf.svg +0 -1
- package/src/client/public/default/plantuml/cron-schema.svg +0 -1
- package/src/client/public/default/plantuml/server-conf.svg +0 -1
- package/src/client/public/default/plantuml/server-schema.svg +0 -1
- package/src/client/public/default/plantuml/ssr-conf.svg +0 -1
- 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 =
|
|
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
|
|
904
|
-
|
|
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(
|
|
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
|
|
986
|
+
`${iteratorTag} | Deployment in progress... | Delay number monitor iterations: ${checkStatusIteration}`,
|
|
929
987
|
);
|
|
930
988
|
}
|
|
931
|
-
logger.info(
|
|
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',
|
|
941
|
-
if (
|
|
1004
|
+
getCurrentLoadedImages(node = 'kind-worker', options = { spec: false, namespace: '' }) {
|
|
1005
|
+
if (options.spec) {
|
|
942
1006
|
const raw = shellExec(
|
|
943
|
-
`kubectl get pods
|
|
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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
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
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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
|
}
|