underpost 2.89.37 → 2.89.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/bin/deploy.js +22 -15
- package/cli.md +89 -61
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +6 -2
- package/manifests/deployment/dd-test-development/proxy.yaml +2 -0
- package/manifests/deployment/kafka/deployment.yaml +0 -2
- package/manifests/deployment/spark/spark-pi-py.yaml +0 -1
- package/manifests/deployment/tensorflow/tf-gpu-test.yaml +0 -2
- package/manifests/envoy-service-nodeport.yaml +0 -1
- package/manifests/kubeadm-calico-config.yaml +10 -115
- package/manifests/letsencrypt-prod.yaml +0 -1
- package/manifests/mariadb/statefulset.yaml +1 -1
- package/manifests/mongodb/statefulset.yaml +11 -11
- package/manifests/mongodb-4.4/service-deployment.yaml +1 -3
- package/manifests/mysql/pv-pvc.yaml +1 -1
- package/manifests/mysql/statefulset.yaml +1 -1
- package/manifests/valkey/service.yaml +0 -1
- package/manifests/valkey/statefulset.yaml +2 -3
- package/package.json +1 -1
- package/scripts/device-scan.sh +43 -21
- package/scripts/rpmfusion-ffmpeg-setup.sh +1 -0
- package/src/cli/cluster.js +58 -57
- package/src/cli/deploy.js +51 -89
- package/src/cli/index.js +30 -3
- package/src/cli/monitor.js +12 -6
- package/src/cli/repository.js +1 -1
- package/src/cli/run.js +32 -19
- package/src/client/components/core/Logger.js +1 -1
- package/src/client/components/core/Modal.js +5 -0
- package/src/client/components/core/ObjectLayerEngineModal.js +334 -71
- package/src/client/components/core/ObjectLayerEngineViewer.js +170 -403
- package/src/client/components/core/Router.js +10 -1
- package/src/client/services/default/default.management.js +25 -5
- package/src/index.js +1 -1
- package/src/server/client-build.js +5 -4
- package/src/server/conf.js +1 -1
- package/manifests/kubelet-config.yaml +0 -65
- package/manifests/mongodb/backup-access.yaml +0 -16
- package/manifests/mongodb/backup-cronjob.yaml +0 -42
- package/manifests/mongodb/backup-pv-pvc.yaml +0 -22
- package/manifests/mongodb/configmap.yaml +0 -26
package/src/cli/deploy.js
CHANGED
|
@@ -129,10 +129,11 @@ class UnderpostDeploy {
|
|
|
129
129
|
* @param {object} resources - Resource configuration for the deployment.
|
|
130
130
|
* @param {number} replicas - Number of replicas for the deployment.
|
|
131
131
|
* @param {string} image - Docker image for the deployment.
|
|
132
|
+
* @param {string} namespace - Kubernetes namespace for the deployment.
|
|
132
133
|
* @returns {string} - YAML deployment configuration for the specified deployment.
|
|
133
134
|
* @memberof UnderpostDeploy
|
|
134
135
|
*/
|
|
135
|
-
deploymentYamlPartsFactory({ deployId, env, suffix, resources, replicas, image }) {
|
|
136
|
+
deploymentYamlPartsFactory({ deployId, env, suffix, resources, replicas, image, namespace }) {
|
|
136
137
|
const packageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
|
|
137
138
|
let volumes = [
|
|
138
139
|
{
|
|
@@ -149,6 +150,7 @@ class UnderpostDeploy {
|
|
|
149
150
|
kind: Deployment
|
|
150
151
|
metadata:
|
|
151
152
|
name: ${deployId}-${env}-${suffix}
|
|
153
|
+
namespace: ${namespace ? namespace : 'default'}
|
|
152
154
|
labels:
|
|
153
155
|
app: ${deployId}-${env}-${suffix}
|
|
154
156
|
spec:
|
|
@@ -188,6 +190,7 @@ apiVersion: v1
|
|
|
188
190
|
kind: Service
|
|
189
191
|
metadata:
|
|
190
192
|
name: ${deployId}-${env}-${suffix}-service
|
|
193
|
+
namespace: ${namespace}
|
|
191
194
|
spec:
|
|
192
195
|
selector:
|
|
193
196
|
app: ${deployId}-${env}-${suffix}
|
|
@@ -201,6 +204,7 @@ spec:
|
|
|
201
204
|
* @param {object} options - Options for the manifest build process.
|
|
202
205
|
* @param {string} options.replicas - Number of replicas for each deployment.
|
|
203
206
|
* @param {string} options.image - Docker image for the deployment.
|
|
207
|
+
* @param {string} options.namespace - Kubernetes namespace for the deployment.
|
|
204
208
|
* @returns {Promise<void>} - Promise that resolves when the manifest is built.
|
|
205
209
|
* @memberof UnderpostDeploy
|
|
206
210
|
*/
|
|
@@ -208,6 +212,7 @@ spec:
|
|
|
208
212
|
const resources = UnderpostDeploy.API.resourcesFactory();
|
|
209
213
|
const replicas = options.replicas;
|
|
210
214
|
const image = options.image;
|
|
215
|
+
if (!options.namespace) options.namespace = 'default';
|
|
211
216
|
|
|
212
217
|
for (const _deployId of deployList.split(',')) {
|
|
213
218
|
const deployId = _deployId.trim();
|
|
@@ -235,6 +240,7 @@ ${UnderpostDeploy.API.deploymentYamlPartsFactory({
|
|
|
235
240
|
resources,
|
|
236
241
|
replicas,
|
|
237
242
|
image,
|
|
243
|
+
namespace: options.namespace,
|
|
238
244
|
}).replace('{{ports}}', buildKindPorts(fromPort, toPort))}
|
|
239
245
|
`;
|
|
240
246
|
}
|
|
@@ -257,6 +263,7 @@ apiVersion: projectcontour.io/v1
|
|
|
257
263
|
kind: HTTPProxy
|
|
258
264
|
metadata:
|
|
259
265
|
name: ${host}
|
|
266
|
+
namespace: ${options.namespace}
|
|
260
267
|
spec:
|
|
261
268
|
virtualhost:
|
|
262
269
|
fqdn: ${host}${
|
|
@@ -316,16 +323,18 @@ spec:
|
|
|
316
323
|
/**
|
|
317
324
|
* Builds a Certificate resource for a host using cert-manager.
|
|
318
325
|
* @param {string} host - Hostname for which the certificate is being built.
|
|
326
|
+
* @param {string} namespace - Kubernetes namespace for the certificate.
|
|
319
327
|
* @returns {string} - Certificate resource YAML for the specified host.
|
|
320
328
|
* @memberof UnderpostDeploy
|
|
321
329
|
*/
|
|
322
|
-
buildCertManagerCertificate({ host }) {
|
|
330
|
+
buildCertManagerCertificate({ host, namespace }) {
|
|
323
331
|
return `
|
|
324
332
|
---
|
|
325
333
|
apiVersion: cert-manager.io/v1
|
|
326
334
|
kind: Certificate
|
|
327
335
|
metadata:
|
|
328
336
|
name: ${host}
|
|
337
|
+
namespace: ${namespace}
|
|
329
338
|
spec:
|
|
330
339
|
commonName: ${host}
|
|
331
340
|
dnsNames:
|
|
@@ -376,6 +385,7 @@ spec:
|
|
|
376
385
|
* @param {boolean} options.status - Whether to display deployment status.
|
|
377
386
|
* @param {boolean} options.etcHosts - Whether to display the /etc/hosts file.
|
|
378
387
|
* @param {boolean} options.disableUpdateUnderpostConfig - Whether to disable Underpost config updates.
|
|
388
|
+
* @param {string} [options.namespace] - Kubernetes namespace for the deployment.
|
|
379
389
|
* @returns {Promise<void>} - Promise that resolves when the deployment process is complete.
|
|
380
390
|
* @memberof UnderpostDeploy
|
|
381
391
|
*/
|
|
@@ -404,74 +414,14 @@ spec:
|
|
|
404
414
|
status: false,
|
|
405
415
|
etcHosts: false,
|
|
406
416
|
disableUpdateUnderpostConfig: false,
|
|
417
|
+
namespace: '',
|
|
407
418
|
},
|
|
408
419
|
) {
|
|
409
|
-
|
|
410
|
-
return logger.info(`
|
|
411
|
-
kubectl rollout restart deployment/deployment-name
|
|
412
|
-
kubectl rollout undo deployment/deployment-name
|
|
413
|
-
kubectl scale statefulsets <stateful-set-name> --replicas=<new-replicas>
|
|
414
|
-
kubectl get pods -w
|
|
415
|
-
kubectl patch statefulset valkey-service --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"valkey/valkey:latest"}]'
|
|
416
|
-
kubectl patch statefulset valkey-service -p '{"spec":{"template":{"spec":{"containers":[{"name":"valkey-service","imagePullPolicy":"Never"}]}}}}'
|
|
417
|
-
kubectl logs -f <pod-name>
|
|
418
|
-
kubectl describe pod <pod-name>
|
|
419
|
-
kubectl exec -it <pod-name> -- bash
|
|
420
|
-
kubectl exec -it <pod-name> -- sh
|
|
421
|
-
docker exec -it kind-control-plane bash
|
|
422
|
-
curl -4 -v google.com
|
|
423
|
-
kubectl taint nodes <node-name> node-role.kubernetes.io/control-plane:NoSchedule-
|
|
424
|
-
kubectl run test-pod --image=busybox:latest --restart=Never -- /bin/sh -c "while true; do sleep 30; done;"
|
|
425
|
-
kubectl run test-pod --image=alpine/curl:latest --restart=Never -- sh -c "sleep infinity"
|
|
426
|
-
kubectl get ippools -o yaml
|
|
427
|
-
kubectl get node <node-name> -o jsonpath='{.spec.podCIDR}'
|
|
428
|
-
kubectl patch ippool default-ipv4-ippool --type='json' -p='[{"op": "replace", "path": "/spec/cidr", "value": "10.244.0.0/16"}]'
|
|
429
|
-
kubectl patch ippool default-ipv4-ippool --type='json' -p='[{"op": "replace", "path": "/spec/cidr", "value": "192.168.0.0/24"}]'
|
|
430
|
-
sudo podman run --rm localhost/<image-name>:<image-version> <command>
|
|
431
|
-
kubectl get configmap kubelet-config -n kube-system -o yaml > kubelet-config.yaml
|
|
432
|
-
kubectl -n kube-system rollout restart daemonset kube-proxy
|
|
433
|
-
kubectl get EndpointSlice -o wide --all-namespaces -w
|
|
434
|
-
kubectl apply -k manifests/deployment/adminer/.
|
|
435
|
-
kubectl wait --for=condition=Ready pod/busybox1
|
|
436
|
-
kubectl wait --for=jsonpath='{.status.phase}'=Running pod/busybox1
|
|
437
|
-
kubectl wait --for='jsonpath={.status.conditions[?(@.type=="Ready")].status}=True' pod/busybox1
|
|
438
|
-
kubectl wait --for=delete pod/busybox1 --timeout=60s
|
|
439
|
-
|
|
440
|
-
fqdn: <service>.<namespace>.<kind(svc/pod)>.<cluster-domain(cluster.local)>
|
|
441
|
-
node bin run cluster-build
|
|
442
|
-
node bin run template-deploy
|
|
443
|
-
node bin run ssh-deploy (sync-)engine-core
|
|
444
|
-
node bin run cluster --dev 'express,dd-test+dd-core'
|
|
445
|
-
node bin run dd-container --dev
|
|
446
|
-
node bin run promote dd-default production
|
|
447
|
-
node bin dockerfile-pull-base-images --dev --path 'image-path' --kind-load
|
|
448
|
-
node bin/deploy update-default-conf <deploy-id>
|
|
449
|
-
|
|
450
|
-
kubectl run --rm -it test-dns --image=busybox:latest --restart=Never -- /bin/sh -c "
|
|
451
|
-
nslookup kubernetes.default.svc.cluster.local;
|
|
452
|
-
nslookup mongodb-service.default.svc.cluster.local;
|
|
453
|
-
nslookup valkey-service.default.svc.cluster.local;
|
|
454
|
-
nc -vz mongodb-service 27017;
|
|
455
|
-
nc -vz valkey-service 6379;
|
|
456
|
-
echo exit code: \\\$?
|
|
457
|
-
"
|
|
458
|
-
|
|
459
|
-
kubectl apply -f - <<EOF
|
|
460
|
-
apiVersion: apps/v1
|
|
461
|
-
kind: StatefulSet
|
|
462
|
-
metadata:
|
|
463
|
-
name: ...
|
|
464
|
-
EOF
|
|
465
|
-
|
|
466
|
-
https://org.ngc.nvidia.com/setup/api-keys
|
|
467
|
-
docker login nvcr.io
|
|
468
|
-
Username: $oauthtoken
|
|
469
|
-
Password: <Your Key>
|
|
470
|
-
`);
|
|
420
|
+
const namespace = options.namespace ? options.namespace : 'default';
|
|
471
421
|
if (!deployList && options.certHosts) {
|
|
472
422
|
for (const host of options.certHosts.split(',')) {
|
|
473
|
-
shellExec(`sudo kubectl apply -f - <<EOF
|
|
474
|
-
${UnderpostDeploy.API.buildCertManagerCertificate({ host })}
|
|
423
|
+
shellExec(`sudo kubectl apply -f - -n ${namespace} <<EOF
|
|
424
|
+
${UnderpostDeploy.API.buildCertManagerCertificate({ host, namespace })}
|
|
475
425
|
EOF`);
|
|
476
426
|
}
|
|
477
427
|
return;
|
|
@@ -540,8 +490,12 @@ EOF`);
|
|
|
540
490
|
|
|
541
491
|
if (!options.disableUpdateDeployment)
|
|
542
492
|
for (const version of options.versions.split(',')) {
|
|
543
|
-
shellExec(
|
|
544
|
-
|
|
493
|
+
shellExec(
|
|
494
|
+
`sudo kubectl delete svc ${deployId}-${env}-${version}-service -n ${namespace} --ignore-not-found`,
|
|
495
|
+
);
|
|
496
|
+
shellExec(
|
|
497
|
+
`sudo kubectl delete deployment ${deployId}-${env}-${version} -n ${namespace} --ignore-not-found`,
|
|
498
|
+
);
|
|
545
499
|
if (!options.disableUpdateVolume) {
|
|
546
500
|
for (const volume of confVolume) {
|
|
547
501
|
const pvcId = `${volume.claimName}-${deployId}-${env}-${version}`;
|
|
@@ -549,9 +503,9 @@ EOF`);
|
|
|
549
503
|
const rootVolumeHostPath = `/home/dd/engine/volume/${pvId}`;
|
|
550
504
|
if (!fs.existsSync(rootVolumeHostPath)) fs.mkdirSync(rootVolumeHostPath, { recursive: true });
|
|
551
505
|
fs.copySync(volume.volumeMountPath, rootVolumeHostPath);
|
|
552
|
-
shellExec(`kubectl delete pvc ${pvcId}`);
|
|
553
|
-
shellExec(`kubectl delete pv ${pvId}`);
|
|
554
|
-
shellExec(`kubectl apply -f - <<EOF
|
|
506
|
+
shellExec(`kubectl delete pvc ${pvcId} -n ${namespace} --ignore-not-found`);
|
|
507
|
+
shellExec(`kubectl delete pv ${pvId} --ignore-not-found`);
|
|
508
|
+
shellExec(`kubectl apply -f - -n ${namespace} <<EOF
|
|
555
509
|
${UnderpostDeploy.API.persistentVolumeFactory({
|
|
556
510
|
hostPath: rootVolumeHostPath,
|
|
557
511
|
pvcId,
|
|
@@ -564,9 +518,9 @@ EOF
|
|
|
564
518
|
|
|
565
519
|
for (const host of Object.keys(confServer)) {
|
|
566
520
|
if (!options.disableUpdateProxy) {
|
|
567
|
-
shellExec(`sudo kubectl delete HTTPProxy ${host}`);
|
|
521
|
+
shellExec(`sudo kubectl delete HTTPProxy ${host} -n ${namespace} --ignore-not-found`);
|
|
568
522
|
if (UnderpostDeploy.API.isValidTLSContext({ host, env, options }))
|
|
569
|
-
shellExec(`sudo kubectl delete Certificate ${host}`);
|
|
523
|
+
shellExec(`sudo kubectl delete Certificate ${host} -n ${namespace} --ignore-not-found`);
|
|
570
524
|
}
|
|
571
525
|
if (!options.remove) etcHosts.push(host);
|
|
572
526
|
}
|
|
@@ -577,11 +531,13 @@ EOF
|
|
|
577
531
|
: `manifests/deployment/${deployId}-${env}`;
|
|
578
532
|
|
|
579
533
|
if (!options.remove) {
|
|
580
|
-
if (!options.disableUpdateDeployment)
|
|
581
|
-
|
|
534
|
+
if (!options.disableUpdateDeployment)
|
|
535
|
+
shellExec(`sudo kubectl apply -f ./${manifestsPath}/deployment.yaml -n ${namespace}`);
|
|
536
|
+
if (!options.disableUpdateProxy)
|
|
537
|
+
shellExec(`sudo kubectl apply -f ./${manifestsPath}/proxy.yaml -n ${namespace}`);
|
|
582
538
|
|
|
583
539
|
if (UnderpostDeploy.API.isValidTLSContext({ host: Object.keys(confServer)[0], env, options }))
|
|
584
|
-
shellExec(`sudo kubectl apply -f ./${manifestsPath}/secret.yaml`);
|
|
540
|
+
shellExec(`sudo kubectl apply -f ./${manifestsPath}/secret.yaml -n ${namespace}`);
|
|
585
541
|
}
|
|
586
542
|
}
|
|
587
543
|
if (options.etcHosts === true) {
|
|
@@ -598,15 +554,19 @@ EOF
|
|
|
598
554
|
* Retrieves information about a deployment.
|
|
599
555
|
* @param {string} deployId - Deployment ID for which information is being retrieved.
|
|
600
556
|
* @param {string} kindType - Type of Kubernetes resource to retrieve information for (e.g. 'pods').
|
|
557
|
+
* @param {string} namespace - Kubernetes namespace to retrieve information from.
|
|
601
558
|
* @returns {Array<object>} - Array of objects containing information about the deployment.
|
|
602
559
|
* @memberof UnderpostDeploy
|
|
603
560
|
*/
|
|
604
|
-
get(deployId, kindType = 'pods') {
|
|
605
|
-
const raw = shellExec(
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
561
|
+
get(deployId, kindType = 'pods', namespace = '') {
|
|
562
|
+
const raw = shellExec(
|
|
563
|
+
`sudo kubectl get ${kindType}${namespace ? ` -n ${namespace}` : ` --all-namespaces`} -o wide`,
|
|
564
|
+
{
|
|
565
|
+
stdout: true,
|
|
566
|
+
disableLog: true,
|
|
567
|
+
silent: true,
|
|
568
|
+
},
|
|
569
|
+
);
|
|
610
570
|
|
|
611
571
|
const heads = raw
|
|
612
572
|
.split(`\n`)[0]
|
|
@@ -720,12 +680,13 @@ EOF
|
|
|
720
680
|
/**
|
|
721
681
|
* Creates a configmap for a deployment.
|
|
722
682
|
* @param {string} env - Environment for which the configmap is being created.
|
|
683
|
+
* @param {string} [namespace='default'] - Kubernetes namespace for the configmap.
|
|
723
684
|
* @memberof UnderpostDeploy
|
|
724
685
|
*/
|
|
725
|
-
configMap(env) {
|
|
726
|
-
shellExec(`kubectl delete configmap underpost-config`);
|
|
686
|
+
configMap(env, namespace = 'default') {
|
|
687
|
+
shellExec(`kubectl delete configmap underpost-config -n ${namespace} --ignore-not-found`);
|
|
727
688
|
shellExec(
|
|
728
|
-
`kubectl create configmap underpost-config --from-file=/home/dd/engine/engine-private/conf/dd-cron/.env.${env}`,
|
|
689
|
+
`kubectl create configmap underpost-config --from-file=/home/dd/engine/engine-private/conf/dd-cron/.env.${env} --dry-run=client -o yaml | kubectl apply -f - -n ${namespace}`,
|
|
729
690
|
);
|
|
730
691
|
},
|
|
731
692
|
/**
|
|
@@ -734,14 +695,15 @@ EOF
|
|
|
734
695
|
* @param {string} env - Environment for which the traffic is being switched.
|
|
735
696
|
* @param {string} targetTraffic - Target traffic status for the deployment.
|
|
736
697
|
* @param {number} replicas - Number of replicas for the deployment.
|
|
698
|
+
* @param {string} [namespace='default'] - Kubernetes namespace for the deployment.
|
|
737
699
|
* @memberof UnderpostDeploy
|
|
738
700
|
*/
|
|
739
|
-
switchTraffic(deployId, env, targetTraffic, replicas = 1) {
|
|
701
|
+
switchTraffic(deployId, env, targetTraffic, replicas = 1, namespace = 'default') {
|
|
740
702
|
UnderpostRootEnv.API.set(`${deployId}-${env}-traffic`, targetTraffic);
|
|
741
703
|
shellExec(
|
|
742
|
-
`node bin deploy --info-router --build-manifest --traffic ${targetTraffic} --replicas ${replicas} ${deployId} ${env}`,
|
|
704
|
+
`node bin deploy --info-router --build-manifest --traffic ${targetTraffic} --replicas ${replicas} --namespace ${namespace} ${deployId} ${env}`,
|
|
743
705
|
);
|
|
744
|
-
shellExec(`sudo kubectl apply -f ./engine-private/conf/${deployId}/build/${env}/proxy.yaml`);
|
|
706
|
+
shellExec(`sudo kubectl apply -f ./engine-private/conf/${deployId}/build/${env}/proxy.yaml -n ${namespace}`);
|
|
745
707
|
},
|
|
746
708
|
|
|
747
709
|
/**
|
|
@@ -909,7 +871,7 @@ ${renderHosts}`,
|
|
|
909
871
|
getCurrentLoadedImages(node = 'kind-worker', specContainers = false) {
|
|
910
872
|
if (specContainers) {
|
|
911
873
|
const raw = shellExec(
|
|
912
|
-
`kubectl get pods --all-namespaces -o=jsonpath='{range .items[*]}{"\\n"}{.metadata.name}{":\\t"}{range .spec.containers[*]}{.image}{", "}{end}{end}'`,
|
|
874
|
+
`kubectl get pods --all-namespaces -o=jsonpath='{range .items[*]}{"\\n"}{.metadata.namespace}{"/"}{.metadata.name}{":\\t"}{range .spec.containers[*]}{.image}{", "}{end}{end}'`,
|
|
913
875
|
{
|
|
914
876
|
stdout: true,
|
|
915
877
|
silent: true,
|
package/src/cli/index.js
CHANGED
|
@@ -7,6 +7,8 @@ import { commitData } from '../client/components/core/CommonJs.js';
|
|
|
7
7
|
import UnderpostLxd from './lxd.js';
|
|
8
8
|
import UnderpostBaremetal from './baremetal.js';
|
|
9
9
|
import UnderpostRun from './run.js';
|
|
10
|
+
import Dns from '../server/dns.js';
|
|
11
|
+
import { pbcopy } from '../server/process.js';
|
|
10
12
|
|
|
11
13
|
// Load environment variables from .env file
|
|
12
14
|
const underpostRootPath = getUnderpostRootPath();
|
|
@@ -129,6 +131,16 @@ program
|
|
|
129
131
|
.description('Displays the root path of the npm installation.')
|
|
130
132
|
.action(() => console.log(getNpmRootPath()));
|
|
131
133
|
|
|
134
|
+
program
|
|
135
|
+
.command('ip')
|
|
136
|
+
.option('--copy', 'Copies the IP addresses to the clipboard.')
|
|
137
|
+
.description('Displays the current public machine IP addresses.')
|
|
138
|
+
.action(async (options) => {
|
|
139
|
+
const ip = await Dns.getPublicIp();
|
|
140
|
+
if (options.copy) return pbcopy(ip);
|
|
141
|
+
return console.log(ip);
|
|
142
|
+
});
|
|
143
|
+
|
|
132
144
|
// 'cluster' command: Manage Kubernetes clusters
|
|
133
145
|
program
|
|
134
146
|
.command('cluster')
|
|
@@ -144,10 +156,20 @@ program
|
|
|
144
156
|
.option('--contour', 'Initializes the cluster with Project Contour base HTTPProxy and Envoy.')
|
|
145
157
|
.option('--cert-manager', "Initializes the cluster with a Let's Encrypt production ClusterIssuer.")
|
|
146
158
|
.option('--dedicated-gpu', 'Initializes the cluster with dedicated GPU base resources and environment settings.')
|
|
147
|
-
.option('--info', 'Retrieves information about all deployed Kubernetes objects.')
|
|
148
159
|
.option('--full', 'Initializes the cluster with all available statefulsets and services.')
|
|
149
|
-
.option(
|
|
160
|
+
.option(
|
|
161
|
+
'--ns-use <ns-name>',
|
|
162
|
+
"Switches the current Kubernetes context to the specified namespace (creates if it doesn't exist).",
|
|
163
|
+
)
|
|
150
164
|
.option('--kubeadm', 'Initializes the cluster using kubeadm for control plane management.')
|
|
165
|
+
.option(
|
|
166
|
+
'--pod-network-cidr <cidr>',
|
|
167
|
+
'Sets custom pod network CIDR for kubeadm cluster initialization (defaults to "192.168.0.0/16").',
|
|
168
|
+
)
|
|
169
|
+
.option(
|
|
170
|
+
'--control-plane-endpoint <endpoint>',
|
|
171
|
+
'Sets custom control plane endpoint for kubeadm cluster initialization (defaults to "localhost:6443").',
|
|
172
|
+
)
|
|
151
173
|
.option('--grafana', 'Initializes the cluster with a Grafana deployment.')
|
|
152
174
|
.option(
|
|
153
175
|
'--prom [hosts]',
|
|
@@ -166,6 +188,7 @@ program
|
|
|
166
188
|
.option('--k3s', 'Initializes the cluster using K3s (Lightweight Kubernetes).')
|
|
167
189
|
.option('--hosts <hosts>', 'A comma-separated list of cluster hostnames or IP addresses.')
|
|
168
190
|
.option('--remove-volume-host-paths', 'Removes specified volume host paths after execution.')
|
|
191
|
+
.option('--namespace <namespace>', 'Kubernetes namespace for cluster operations (defaults to "default").')
|
|
169
192
|
.action(Underpost.cluster.init)
|
|
170
193
|
.description('Manages Kubernetes clusters, defaulting to Kind cluster initialization.');
|
|
171
194
|
|
|
@@ -181,7 +204,6 @@ program
|
|
|
181
204
|
.option('--sync', 'Synchronizes deployment environment variables, ports, and replica counts.')
|
|
182
205
|
.option('--info-router', 'Displays the current router structure and configuration.')
|
|
183
206
|
.option('--expose', 'Exposes services matching the provided deployment ID list.')
|
|
184
|
-
.option('--info-util', 'Displays useful `kubectl` utility management commands.')
|
|
185
207
|
.option('--cert', 'Resets TLS/SSL certificate secrets for deployments.')
|
|
186
208
|
.option('--cert-hosts <hosts>', 'Resets TLS/SSL certificate secrets for specified hosts.')
|
|
187
209
|
.option('--node <node>', 'Sets optional node for deployment operations.')
|
|
@@ -205,6 +227,7 @@ program
|
|
|
205
227
|
.option('--etc-hosts', 'Enables the etc-hosts context for deployment operations.')
|
|
206
228
|
.option('--restore-hosts', 'Restores default `/etc/hosts` entries.')
|
|
207
229
|
.option('--disable-update-underpost-config', 'Disables updates to Underpost configuration during deployment.')
|
|
230
|
+
.option('--namespace <namespace>', 'Kubernetes namespace for deployment operations (defaults to "default").')
|
|
208
231
|
.description('Manages application deployments, defaulting to deploying development pods.')
|
|
209
232
|
.action(Underpost.deploy.callback);
|
|
210
233
|
|
|
@@ -402,6 +425,10 @@ program
|
|
|
402
425
|
.option('--runtime-class-name <name>', 'Sets the runtime class name for the job in deploy-job.')
|
|
403
426
|
.option('--image-pull-policy <policy>', 'Sets the image pull policy for the job in deploy-job.')
|
|
404
427
|
.option('--api-version <version>', 'Sets the API version for the job manifest in deploy-job.')
|
|
428
|
+
.option(
|
|
429
|
+
'--labels <labels>',
|
|
430
|
+
'Optional: Specifies a comma-separated list of key-value pairs for labels (e.g., "app=my-app,env=prod").',
|
|
431
|
+
)
|
|
405
432
|
.option('--claim-name <name>', 'Optional: Specifies the claim name for volume mounting in deploy-job.')
|
|
406
433
|
.option('--kind <kind-type>', 'Specifies the kind of Kubernetes resource (e.g., Job, Deployment) for deploy-job.')
|
|
407
434
|
.option('--kubeadm', 'Flag to indicate Kubeadm cluster type context')
|
package/src/cli/monitor.js
CHANGED
|
@@ -39,6 +39,7 @@ class UnderpostMonitor {
|
|
|
39
39
|
* @param {string} [options.type=''] - Type of deployment (e.g., 'blue-green', 'remote').
|
|
40
40
|
* @param {string} [options.replicas=''] - Number of replicas for the deployment.
|
|
41
41
|
* @param {boolean} [options.sync=false] - Synchronize traffic switching with the deployment.
|
|
42
|
+
* @param {string} [options.namespace=''] - Kubernetes namespace for the deployment.
|
|
42
43
|
* @param {object} [commanderOptions] - Options passed from the command line interface.
|
|
43
44
|
* @param {object} [auxRouter] - Optional router configuration for the deployment.
|
|
44
45
|
* @memberof UnderpostMonitor
|
|
@@ -46,10 +47,11 @@ class UnderpostMonitor {
|
|
|
46
47
|
async callback(
|
|
47
48
|
deployId,
|
|
48
49
|
env = 'development',
|
|
49
|
-
options = { now: false, single: false, msInterval: '', type: '', replicas: '', sync: false },
|
|
50
|
+
options = { now: false, single: false, msInterval: '', type: '', replicas: '', sync: false, namespace: '' },
|
|
50
51
|
commanderOptions,
|
|
51
52
|
auxRouter,
|
|
52
53
|
) {
|
|
54
|
+
if (!options.namespace) options.namespace = 'default';
|
|
53
55
|
if (deployId === 'dd' && fs.existsSync(`./engine-private/deploy/dd.router`)) {
|
|
54
56
|
for (const _deployId of fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8').split(','))
|
|
55
57
|
UnderpostMonitor.API.callback(
|
|
@@ -95,12 +97,13 @@ class UnderpostMonitor {
|
|
|
95
97
|
if (traffic === 'blue') traffic = 'green';
|
|
96
98
|
else traffic = 'blue';
|
|
97
99
|
UnderpostRootEnv.API.set(`${deployId}-${env}-traffic`, traffic);
|
|
100
|
+
const namespace = options.namespace || 'default';
|
|
98
101
|
shellExec(
|
|
99
102
|
`node bin deploy --info-router --build-manifest --traffic ${traffic} --replicas ${
|
|
100
103
|
options.replicas ? options.replicas : 1
|
|
101
|
-
} ${deployId} ${env}`,
|
|
104
|
+
} --namespace ${namespace} ${deployId} ${env}`,
|
|
102
105
|
);
|
|
103
|
-
shellExec(`sudo kubectl apply -f ./engine-private/conf/${deployId}/build/${env}/proxy.yaml`);
|
|
106
|
+
shellExec(`sudo kubectl apply -f ./engine-private/conf/${deployId}/build/${env}/proxy.yaml -n ${namespace}`);
|
|
104
107
|
};
|
|
105
108
|
|
|
106
109
|
const monitor = async (reject) => {
|
|
@@ -152,12 +155,15 @@ class UnderpostMonitor {
|
|
|
152
155
|
fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'),
|
|
153
156
|
);
|
|
154
157
|
|
|
155
|
-
|
|
158
|
+
const namespace = options.namespace || 'default';
|
|
159
|
+
UnderpostDeploy.API.configMap(env, namespace);
|
|
156
160
|
|
|
157
161
|
for (const host of Object.keys(confServer)) {
|
|
158
|
-
shellExec(`sudo kubectl delete HTTPProxy ${host}`);
|
|
162
|
+
shellExec(`sudo kubectl delete HTTPProxy ${host} -n ${namespace} --ignore-not-found`);
|
|
159
163
|
}
|
|
160
|
-
shellExec(
|
|
164
|
+
shellExec(
|
|
165
|
+
`sudo kubectl rollout restart deployment/${deployId}-${env}-${traffic} -n ${namespace}`,
|
|
166
|
+
);
|
|
161
167
|
|
|
162
168
|
switchTraffic();
|
|
163
169
|
}
|
package/src/cli/repository.js
CHANGED
|
@@ -179,7 +179,7 @@ class UnderpostRepository {
|
|
|
179
179
|
return;
|
|
180
180
|
}
|
|
181
181
|
if (options.info) return logger.info('', commitData);
|
|
182
|
-
const _message = `${commitType}${subModule ? `(${subModule})` : ''}
|
|
182
|
+
const _message = `${commitType}${subModule ? `(${subModule})` : ''}: ${
|
|
183
183
|
commitData[commitType].emoji
|
|
184
184
|
} ${message ? message : commitData[commitType].description}`;
|
|
185
185
|
if (options.copy) return pbcopy(_message);
|
package/src/cli/run.js
CHANGED
|
@@ -81,7 +81,7 @@ class UnderpostRun {
|
|
|
81
81
|
volumeMountPath: '',
|
|
82
82
|
imageName: '',
|
|
83
83
|
containerName: '',
|
|
84
|
-
namespace: '',
|
|
84
|
+
namespace: 'default',
|
|
85
85
|
build: false,
|
|
86
86
|
replicas: 1,
|
|
87
87
|
k3s: false,
|
|
@@ -209,10 +209,10 @@ class UnderpostRun {
|
|
|
209
209
|
* @memberof UnderpostRun
|
|
210
210
|
*/
|
|
211
211
|
'tf-gpu-test': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
212
|
-
const { underpostRoot } = options;
|
|
213
|
-
shellExec(`kubectl delete configmap tf-gpu-test-script`);
|
|
214
|
-
shellExec(`kubectl delete pod tf-gpu-test-pod`);
|
|
215
|
-
shellExec(`kubectl apply -f ${underpostRoot}/manifests/deployment/tensorflow/tf-gpu-test.yaml`);
|
|
212
|
+
const { underpostRoot, namespace } = options;
|
|
213
|
+
shellExec(`kubectl delete configmap tf-gpu-test-script -n ${namespace} --ignore-not-found`);
|
|
214
|
+
shellExec(`kubectl delete pod tf-gpu-test-pod -n ${namespace} --ignore-not-found`);
|
|
215
|
+
shellExec(`kubectl apply -f ${underpostRoot}/manifests/deployment/tensorflow/tf-gpu-test.yaml -n ${namespace}`);
|
|
216
216
|
},
|
|
217
217
|
/**
|
|
218
218
|
* @method dev-cluster
|
|
@@ -493,7 +493,7 @@ class UnderpostRun {
|
|
|
493
493
|
versions = versions ? versions.replaceAll('+', ',') : defaultPath[2];
|
|
494
494
|
image = image ? image : defaultPath[3];
|
|
495
495
|
node = node ? node : defaultPath[4];
|
|
496
|
-
|
|
496
|
+
shellExec(`${baseCommand} cluster --ns-use ${options.namespace}`);
|
|
497
497
|
if (isDeployRunnerContext(path, options)) {
|
|
498
498
|
const { validVersion } = UnderpostRepository.API.privateConfUpdate(deployId);
|
|
499
499
|
if (!validVersion) throw new Error('Version mismatch');
|
|
@@ -510,11 +510,13 @@ class UnderpostRun {
|
|
|
510
510
|
shellExec(
|
|
511
511
|
`${baseCommand} deploy --kubeadm --build-manifest --sync --info-router --replicas ${
|
|
512
512
|
replicas ? replicas : 1
|
|
513
|
-
} --node ${node}${image ? ` --image ${image}` : ''}${versions ? ` --versions ${versions}` : ''} dd ${env}`,
|
|
513
|
+
} --node ${node}${image ? ` --image ${image}` : ''}${versions ? ` --versions ${versions}` : ''}${options.namespace ? ` --namespace ${options.namespace}` : ''} dd ${env}`,
|
|
514
514
|
);
|
|
515
515
|
|
|
516
516
|
if (isDeployRunnerContext(path, options)) {
|
|
517
|
-
shellExec(
|
|
517
|
+
shellExec(
|
|
518
|
+
`${baseCommand} deploy --kubeadm --disable-update-proxy ${deployId} ${env} --versions ${versions}${options.namespace ? ` --namespace ${options.namespace}` : ''}`,
|
|
519
|
+
);
|
|
518
520
|
if (!targetTraffic) targetTraffic = UnderpostDeploy.API.getCurrentTraffic(deployId);
|
|
519
521
|
await UnderpostDeploy.API.monitorReadyRunner(deployId, env, targetTraffic);
|
|
520
522
|
UnderpostDeploy.API.switchTraffic(deployId, env, targetTraffic);
|
|
@@ -619,7 +621,7 @@ class UnderpostRun {
|
|
|
619
621
|
`docker exec -i kind-worker bash -c "chown -R 1000:1000 ${volumeHostPath} || true; chmod -R 755 ${volumeHostPath}"`,
|
|
620
622
|
);
|
|
621
623
|
} else {
|
|
622
|
-
shellExec(`kubectl apply -f ${options.underpostRoot}/manifests/pv-pvc-dd.yaml`);
|
|
624
|
+
shellExec(`kubectl apply -f ${options.underpostRoot}/manifests/pv-pvc-dd.yaml -n ${options.namespace}`);
|
|
623
625
|
}
|
|
624
626
|
|
|
625
627
|
if (!currentImage)
|
|
@@ -682,7 +684,7 @@ class UnderpostRun {
|
|
|
682
684
|
switch (path) {
|
|
683
685
|
case 'tf-vae-test':
|
|
684
686
|
{
|
|
685
|
-
const nameSpace = 'default';
|
|
687
|
+
const nameSpace = options.namespace || 'default';
|
|
686
688
|
const podName = path;
|
|
687
689
|
const basePath = '/home/dd';
|
|
688
690
|
const scriptPath = '/site/en/tutorials/generative/cvae.py';
|
|
@@ -764,8 +766,8 @@ class UnderpostRun {
|
|
|
764
766
|
// For kubeadm/k3s, ensure it's available for containerd
|
|
765
767
|
shellExec(`sudo crictl pull ${image}`);
|
|
766
768
|
|
|
767
|
-
shellExec(`kubectl delete deployment adminer`);
|
|
768
|
-
shellExec(`kubectl apply -k ${underpostRoot}/manifests/deployment/adminer
|
|
769
|
+
shellExec(`kubectl delete deployment adminer -n ${options.namespace} --ignore-not-found`);
|
|
770
|
+
shellExec(`kubectl apply -k ${underpostRoot}/manifests/deployment/adminer/. -n ${options.namespace}`);
|
|
769
771
|
const successInstance = await UnderpostTest.API.statusMonitor('adminer', 'Running', 'pods', 1000, 60 * 10);
|
|
770
772
|
|
|
771
773
|
if (successInstance) {
|
|
@@ -922,7 +924,7 @@ class UnderpostRun {
|
|
|
922
924
|
const env = 'production';
|
|
923
925
|
const ignorePods = UnderpostDeploy.API.get(`${deployId}-${env}-${targetTraffic}`).map((p) => p.NAME);
|
|
924
926
|
|
|
925
|
-
shellExec(`sudo kubectl rollout restart deployment/${deployId}-${env}-${targetTraffic}`);
|
|
927
|
+
shellExec(`sudo kubectl rollout restart deployment/${deployId}-${env}-${targetTraffic} -n ${options.namespace}`);
|
|
926
928
|
|
|
927
929
|
await UnderpostDeploy.API.monitorReadyRunner(deployId, env, targetTraffic, ignorePods);
|
|
928
930
|
|
|
@@ -1043,9 +1045,9 @@ class UnderpostRun {
|
|
|
1043
1045
|
);
|
|
1044
1046
|
switch (serviceId) {
|
|
1045
1047
|
case 'mongo-express-service': {
|
|
1046
|
-
shellExec(`kubectl delete svc mongo-express-service --ignore-not-found`);
|
|
1047
|
-
shellExec(`kubectl delete deployment mongo-express --ignore-not-found`);
|
|
1048
|
-
shellExec(`kubectl apply -f manifests/deployment/mongo-express/deployment.yaml`);
|
|
1048
|
+
shellExec(`kubectl delete svc mongo-express-service -n ${options.namespace} --ignore-not-found`);
|
|
1049
|
+
shellExec(`kubectl delete deployment mongo-express -n ${options.namespace} --ignore-not-found`);
|
|
1050
|
+
shellExec(`kubectl apply -f manifests/deployment/mongo-express/deployment.yaml -n ${options.namespace}`);
|
|
1049
1051
|
podToMonitor = 'mongo-express';
|
|
1050
1052
|
break;
|
|
1051
1053
|
}
|
|
@@ -1225,6 +1227,16 @@ class UnderpostRun {
|
|
|
1225
1227
|
const imagePullPolicy = options.imagePullPolicy || 'IfNotPresent';
|
|
1226
1228
|
const hostNetwork = options.hostNetwork ? options.hostNetwork : '';
|
|
1227
1229
|
const apiVersion = options.apiVersion || 'v1';
|
|
1230
|
+
const labels = options.labels
|
|
1231
|
+
? options.labels
|
|
1232
|
+
.split(',')
|
|
1233
|
+
.map((keyValue) => {
|
|
1234
|
+
const [key, value] = keyValue.split('=');
|
|
1235
|
+
return ` ${key}: ${value}
|
|
1236
|
+
`;
|
|
1237
|
+
})
|
|
1238
|
+
.join('')
|
|
1239
|
+
: ` app: ${podName}`;
|
|
1228
1240
|
if (options.volumeType === 'dev') options.volumeType = 'FileOrCreate';
|
|
1229
1241
|
const volumeType =
|
|
1230
1242
|
options.volumeType || (enableVolumeMount && volumeHostPath && fs.statSync(volumeHostPath).isDirectory())
|
|
@@ -1240,7 +1252,7 @@ metadata:
|
|
|
1240
1252
|
name: ${podName}
|
|
1241
1253
|
namespace: ${namespace}
|
|
1242
1254
|
labels:
|
|
1243
|
-
|
|
1255
|
+
${labels}
|
|
1244
1256
|
spec:
|
|
1245
1257
|
restartPolicy: ${restartPolicy}
|
|
1246
1258
|
${runtimeClassName ? ` runtimeClassName: ${runtimeClassName}` : ''}
|
|
@@ -1278,13 +1290,13 @@ ${
|
|
|
1278
1290
|
: ''
|
|
1279
1291
|
}
|
|
1280
1292
|
EOF`;
|
|
1281
|
-
shellExec(`kubectl delete pod ${podName} --ignore-not-found`);
|
|
1293
|
+
shellExec(`kubectl delete pod ${podName} -n ${namespace} --ignore-not-found`);
|
|
1282
1294
|
console.log(cmd);
|
|
1283
1295
|
shellExec(cmd, { disableLog: true });
|
|
1284
1296
|
const successInstance = await UnderpostTest.API.statusMonitor(podName);
|
|
1285
1297
|
if (successInstance) {
|
|
1286
1298
|
options.on?.init ? await options.on.init() : null;
|
|
1287
|
-
shellExec(`kubectl logs -f ${podName}`);
|
|
1299
|
+
shellExec(`kubectl logs -f ${podName} -n ${namespace}`);
|
|
1288
1300
|
}
|
|
1289
1301
|
},
|
|
1290
1302
|
};
|
|
@@ -1306,6 +1318,7 @@ EOF`;
|
|
|
1306
1318
|
if (options.command) options.command = options.command.split(',');
|
|
1307
1319
|
if (options.args) options.args = options.args.split(',');
|
|
1308
1320
|
if (!options.underpostRoot) options.underpostRoot = underpostRoot;
|
|
1321
|
+
if (!options.namespace) options.namespace = 'default';
|
|
1309
1322
|
options.npmRoot = npmRoot;
|
|
1310
1323
|
logger.info('callback', { path, options });
|
|
1311
1324
|
if (!(runner in UnderpostRun.RUNNERS)) throw new Error(`Runner not found: ${runner}`);
|
|
@@ -6,7 +6,7 @@ const loggerFactory = (meta, options = { trace: false }) => {
|
|
|
6
6
|
const logger = {
|
|
7
7
|
log: function (type, args) {
|
|
8
8
|
if (!window.renderPayload.dev) return;
|
|
9
|
-
if (options.trace === true) args.push(getCurrentTrace().split('Logger.js
|
|
9
|
+
if (options.trace === true) args.push(getCurrentTrace().split('Logger.js')[1]);
|
|
10
10
|
return console[type](`[${meta}] ${new Date().toISOString()} ${type}:`, ...args);
|
|
11
11
|
},
|
|
12
12
|
};
|
|
@@ -87,6 +87,7 @@ const Modal = {
|
|
|
87
87
|
onExpandUiListener: {},
|
|
88
88
|
onBarUiOpen: {},
|
|
89
89
|
onBarUiClose: {},
|
|
90
|
+
onReloadModalListener: {},
|
|
90
91
|
onHome: {},
|
|
91
92
|
homeModals: options.homeModals ? options.homeModals : [],
|
|
92
93
|
query: options.query ? `${window.location.search}` : undefined,
|
|
@@ -121,6 +122,7 @@ const Modal = {
|
|
|
121
122
|
top = `${windowGetH() / 2 - height / 2}px`;
|
|
122
123
|
left = `${windowGetW() / 2 - width / 2}px`;
|
|
123
124
|
},
|
|
125
|
+
...this.Data[idModal],
|
|
124
126
|
};
|
|
125
127
|
|
|
126
128
|
if (options && 'mode' in options) {
|
|
@@ -1387,6 +1389,9 @@ const Modal = {
|
|
|
1387
1389
|
if (options.zIndexSync) this.zIndexSync({ idModal });
|
|
1388
1390
|
|
|
1389
1391
|
if (s(`.${idModal}`)) {
|
|
1392
|
+
for (const event of Object.keys(Modal.Data[idModal].onReloadModalListener))
|
|
1393
|
+
await Modal.Data[idModal].onReloadModalListener[event]();
|
|
1394
|
+
|
|
1390
1395
|
s(`.btn-maximize-${idModal}`).click();
|
|
1391
1396
|
return;
|
|
1392
1397
|
}
|