underpost 2.89.35 → 2.89.44
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 +4 -2
- package/bin/deploy.js +22 -15
- package/cli.md +23 -2
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +10 -6
- 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/api/user/user.model.js +10 -1
- package/src/cli/cluster.js +51 -26
- package/src/cli/deploy.js +73 -39
- package/src/cli/index.js +22 -1
- package/src/cli/monitor.js +9 -5
- package/src/cli/repository.js +1 -1
- package/src/cli/run.js +38 -21
- 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/src/server/start.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/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')
|
|
@@ -146,7 +158,10 @@ program
|
|
|
146
158
|
.option('--dedicated-gpu', 'Initializes the cluster with dedicated GPU base resources and environment settings.')
|
|
147
159
|
.option('--info', 'Retrieves information about all deployed Kubernetes objects.')
|
|
148
160
|
.option('--full', 'Initializes the cluster with all available statefulsets and services.')
|
|
149
|
-
.option(
|
|
161
|
+
.option(
|
|
162
|
+
'--ns-use <ns-name>',
|
|
163
|
+
"Switches the current Kubernetes context to the specified namespace (creates if it doesn't exist).",
|
|
164
|
+
)
|
|
150
165
|
.option('--kubeadm', 'Initializes the cluster using kubeadm for control plane management.')
|
|
151
166
|
.option('--grafana', 'Initializes the cluster with a Grafana deployment.')
|
|
152
167
|
.option(
|
|
@@ -166,6 +181,7 @@ program
|
|
|
166
181
|
.option('--k3s', 'Initializes the cluster using K3s (Lightweight Kubernetes).')
|
|
167
182
|
.option('--hosts <hosts>', 'A comma-separated list of cluster hostnames or IP addresses.')
|
|
168
183
|
.option('--remove-volume-host-paths', 'Removes specified volume host paths after execution.')
|
|
184
|
+
.option('--namespace <namespace>', 'Kubernetes namespace for cluster operations (defaults to "default").')
|
|
169
185
|
.action(Underpost.cluster.init)
|
|
170
186
|
.description('Manages Kubernetes clusters, defaulting to Kind cluster initialization.');
|
|
171
187
|
|
|
@@ -205,6 +221,7 @@ program
|
|
|
205
221
|
.option('--etc-hosts', 'Enables the etc-hosts context for deployment operations.')
|
|
206
222
|
.option('--restore-hosts', 'Restores default `/etc/hosts` entries.')
|
|
207
223
|
.option('--disable-update-underpost-config', 'Disables updates to Underpost configuration during deployment.')
|
|
224
|
+
.option('--namespace <namespace>', 'Kubernetes namespace for deployment operations (defaults to "default").')
|
|
208
225
|
.description('Manages application deployments, defaulting to deploying development pods.')
|
|
209
226
|
.action(Underpost.deploy.callback);
|
|
210
227
|
|
|
@@ -402,6 +419,10 @@ program
|
|
|
402
419
|
.option('--runtime-class-name <name>', 'Sets the runtime class name for the job in deploy-job.')
|
|
403
420
|
.option('--image-pull-policy <policy>', 'Sets the image pull policy for the job in deploy-job.')
|
|
404
421
|
.option('--api-version <version>', 'Sets the API version for the job manifest in deploy-job.')
|
|
422
|
+
.option(
|
|
423
|
+
'--labels <labels>',
|
|
424
|
+
'Optional: Specifies a comma-separated list of key-value pairs for labels (e.g., "app=my-app,env=prod").',
|
|
425
|
+
)
|
|
405
426
|
.option('--claim-name <name>', 'Optional: Specifies the claim name for volume mounting in deploy-job.')
|
|
406
427
|
.option('--kind <kind-type>', 'Specifies the kind of Kubernetes resource (e.g., Job, Deployment) for deploy-job.')
|
|
407
428
|
.option('--kubeadm', 'Flag to indicate Kubeadm cluster type context')
|
package/src/cli/monitor.js
CHANGED
|
@@ -95,12 +95,13 @@ class UnderpostMonitor {
|
|
|
95
95
|
if (traffic === 'blue') traffic = 'green';
|
|
96
96
|
else traffic = 'blue';
|
|
97
97
|
UnderpostRootEnv.API.set(`${deployId}-${env}-traffic`, traffic);
|
|
98
|
+
const namespace = options.namespace || 'default';
|
|
98
99
|
shellExec(
|
|
99
100
|
`node bin deploy --info-router --build-manifest --traffic ${traffic} --replicas ${
|
|
100
101
|
options.replicas ? options.replicas : 1
|
|
101
|
-
} ${deployId} ${env}`,
|
|
102
|
+
} --namespace ${namespace} ${deployId} ${env}`,
|
|
102
103
|
);
|
|
103
|
-
shellExec(`sudo kubectl apply -f ./engine-private/conf/${deployId}/build/${env}/proxy.yaml`);
|
|
104
|
+
shellExec(`sudo kubectl apply -f ./engine-private/conf/${deployId}/build/${env}/proxy.yaml -n ${namespace}`);
|
|
104
105
|
};
|
|
105
106
|
|
|
106
107
|
const monitor = async (reject) => {
|
|
@@ -152,12 +153,15 @@ class UnderpostMonitor {
|
|
|
152
153
|
fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'),
|
|
153
154
|
);
|
|
154
155
|
|
|
155
|
-
|
|
156
|
+
const namespace = options.namespace || 'default';
|
|
157
|
+
UnderpostDeploy.API.configMap(env, namespace);
|
|
156
158
|
|
|
157
159
|
for (const host of Object.keys(confServer)) {
|
|
158
|
-
shellExec(`sudo kubectl delete HTTPProxy ${host}`);
|
|
160
|
+
shellExec(`sudo kubectl delete HTTPProxy ${host} -n ${namespace} --ignore-not-found`);
|
|
159
161
|
}
|
|
160
|
-
shellExec(
|
|
162
|
+
shellExec(
|
|
163
|
+
`sudo kubectl rollout restart deployment/${deployId}-${env}-${traffic} -n ${namespace}`,
|
|
164
|
+
);
|
|
161
165
|
|
|
162
166
|
switchTraffic();
|
|
163
167
|
}
|
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
|
|
@@ -340,9 +340,10 @@ class UnderpostRun {
|
|
|
340
340
|
* @memberof UnderpostRun
|
|
341
341
|
*/
|
|
342
342
|
'cluster-build': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
343
|
+
const nodeOptions = options.nodeName ? ` --node-name ${options.nodeName}` : '';
|
|
343
344
|
shellExec(`node bin run clean`);
|
|
344
|
-
shellExec(`node bin run --dev sync-replica template-deploy`);
|
|
345
|
-
shellExec(`node bin run sync-replica template-deploy`);
|
|
345
|
+
shellExec(`node bin run --dev sync-replica template-deploy${nodeOptions}`);
|
|
346
|
+
shellExec(`node bin run sync-replica template-deploy${nodeOptions}`);
|
|
346
347
|
shellExec(`node bin env clean`);
|
|
347
348
|
for (const deployId of fs.readFileSync('./engine-private/deploy/dd.router', 'utf8').split(','))
|
|
348
349
|
shellExec(`node bin/deploy update-default-conf ${deployId.trim()}`);
|
|
@@ -509,11 +510,13 @@ class UnderpostRun {
|
|
|
509
510
|
shellExec(
|
|
510
511
|
`${baseCommand} deploy --kubeadm --build-manifest --sync --info-router --replicas ${
|
|
511
512
|
replicas ? replicas : 1
|
|
512
|
-
} --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}`,
|
|
513
514
|
);
|
|
514
515
|
|
|
515
516
|
if (isDeployRunnerContext(path, options)) {
|
|
516
|
-
shellExec(
|
|
517
|
+
shellExec(
|
|
518
|
+
`${baseCommand} deploy --kubeadm --disable-update-proxy ${deployId} ${env} --versions ${versions}${options.namespace ? ` --namespace ${options.namespace}` : ''}`,
|
|
519
|
+
);
|
|
517
520
|
if (!targetTraffic) targetTraffic = UnderpostDeploy.API.getCurrentTraffic(deployId);
|
|
518
521
|
await UnderpostDeploy.API.monitorReadyRunner(deployId, env, targetTraffic);
|
|
519
522
|
UnderpostDeploy.API.switchTraffic(deployId, env, targetTraffic);
|
|
@@ -618,7 +621,7 @@ class UnderpostRun {
|
|
|
618
621
|
`docker exec -i kind-worker bash -c "chown -R 1000:1000 ${volumeHostPath} || true; chmod -R 755 ${volumeHostPath}"`,
|
|
619
622
|
);
|
|
620
623
|
} else {
|
|
621
|
-
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}`);
|
|
622
625
|
}
|
|
623
626
|
|
|
624
627
|
if (!currentImage)
|
|
@@ -681,7 +684,7 @@ class UnderpostRun {
|
|
|
681
684
|
switch (path) {
|
|
682
685
|
case 'tf-vae-test':
|
|
683
686
|
{
|
|
684
|
-
const nameSpace = 'default';
|
|
687
|
+
const nameSpace = options.namespace || 'default';
|
|
685
688
|
const podName = path;
|
|
686
689
|
const basePath = '/home/dd';
|
|
687
690
|
const scriptPath = '/site/en/tutorials/generative/cvae.py';
|
|
@@ -763,8 +766,8 @@ class UnderpostRun {
|
|
|
763
766
|
// For kubeadm/k3s, ensure it's available for containerd
|
|
764
767
|
shellExec(`sudo crictl pull ${image}`);
|
|
765
768
|
|
|
766
|
-
shellExec(`kubectl delete deployment adminer`);
|
|
767
|
-
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}`);
|
|
768
771
|
const successInstance = await UnderpostTest.API.statusMonitor('adminer', 'Running', 'pods', 1000, 60 * 10);
|
|
769
772
|
|
|
770
773
|
if (successInstance) {
|
|
@@ -921,7 +924,7 @@ class UnderpostRun {
|
|
|
921
924
|
const env = 'production';
|
|
922
925
|
const ignorePods = UnderpostDeploy.API.get(`${deployId}-${env}-${targetTraffic}`).map((p) => p.NAME);
|
|
923
926
|
|
|
924
|
-
shellExec(`sudo kubectl rollout restart deployment/${deployId}-${env}-${targetTraffic}`);
|
|
927
|
+
shellExec(`sudo kubectl rollout restart deployment/${deployId}-${env}-${targetTraffic} -n ${options.namespace}`);
|
|
925
928
|
|
|
926
929
|
await UnderpostDeploy.API.monitorReadyRunner(deployId, env, targetTraffic, ignorePods);
|
|
927
930
|
|
|
@@ -1042,9 +1045,9 @@ class UnderpostRun {
|
|
|
1042
1045
|
);
|
|
1043
1046
|
switch (serviceId) {
|
|
1044
1047
|
case 'mongo-express-service': {
|
|
1045
|
-
shellExec(`kubectl delete svc mongo-express-service --ignore-not-found`);
|
|
1046
|
-
shellExec(`kubectl delete deployment mongo-express --ignore-not-found`);
|
|
1047
|
-
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}`);
|
|
1048
1051
|
podToMonitor = 'mongo-express';
|
|
1049
1052
|
break;
|
|
1050
1053
|
}
|
|
@@ -1143,7 +1146,11 @@ class UnderpostRun {
|
|
|
1143
1146
|
shellExec(`${baseCommand} env ${deployId} ${env}`);
|
|
1144
1147
|
for (const host of Object.keys(confServer))
|
|
1145
1148
|
if (_path in confServer[host]) shellExec(`node bin/deploy build-single-replica ${deployId} ${host} ${_path}`);
|
|
1146
|
-
const node = options.
|
|
1149
|
+
const node = options.nodeName
|
|
1150
|
+
? options.nodeName
|
|
1151
|
+
: options.dev || !isDeployRunnerContext(path, options)
|
|
1152
|
+
? 'kind-control-plane'
|
|
1153
|
+
: os.hostname();
|
|
1147
1154
|
// deployId, replicas, versions, image, node
|
|
1148
1155
|
let defaultPath = [deployId, 1, ``, ``, node];
|
|
1149
1156
|
shellExec(`${baseCommand} run${options.dev === true ? ' --dev' : ''} --build sync ${defaultPath}`);
|
|
@@ -1220,6 +1227,16 @@ class UnderpostRun {
|
|
|
1220
1227
|
const imagePullPolicy = options.imagePullPolicy || 'IfNotPresent';
|
|
1221
1228
|
const hostNetwork = options.hostNetwork ? options.hostNetwork : '';
|
|
1222
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}`;
|
|
1223
1240
|
if (options.volumeType === 'dev') options.volumeType = 'FileOrCreate';
|
|
1224
1241
|
const volumeType =
|
|
1225
1242
|
options.volumeType || (enableVolumeMount && volumeHostPath && fs.statSync(volumeHostPath).isDirectory())
|
|
@@ -1235,7 +1252,7 @@ metadata:
|
|
|
1235
1252
|
name: ${podName}
|
|
1236
1253
|
namespace: ${namespace}
|
|
1237
1254
|
labels:
|
|
1238
|
-
|
|
1255
|
+
${labels}
|
|
1239
1256
|
spec:
|
|
1240
1257
|
restartPolicy: ${restartPolicy}
|
|
1241
1258
|
${runtimeClassName ? ` runtimeClassName: ${runtimeClassName}` : ''}
|
|
@@ -1273,13 +1290,13 @@ ${
|
|
|
1273
1290
|
: ''
|
|
1274
1291
|
}
|
|
1275
1292
|
EOF`;
|
|
1276
|
-
shellExec(`kubectl delete pod ${podName} --ignore-not-found`);
|
|
1293
|
+
shellExec(`kubectl delete pod ${podName} -n ${namespace} --ignore-not-found`);
|
|
1277
1294
|
console.log(cmd);
|
|
1278
1295
|
shellExec(cmd, { disableLog: true });
|
|
1279
1296
|
const successInstance = await UnderpostTest.API.statusMonitor(podName);
|
|
1280
1297
|
if (successInstance) {
|
|
1281
1298
|
options.on?.init ? await options.on.init() : null;
|
|
1282
|
-
shellExec(`kubectl logs -f ${podName}`);
|
|
1299
|
+
shellExec(`kubectl logs -f ${podName} -n ${namespace}`);
|
|
1283
1300
|
}
|
|
1284
1301
|
},
|
|
1285
1302
|
};
|
|
@@ -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
|
}
|