underpost 2.8.6 → 2.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/extensions.json +3 -2
- package/.vscode/settings.json +2 -0
- package/CHANGELOG.md +24 -4
- package/Dockerfile +9 -10
- package/README.md +39 -2
- package/bin/build.js +2 -2
- package/bin/deploy.js +1337 -131
- package/bin/file.js +8 -0
- package/bin/index.js +1 -218
- package/cli.md +451 -0
- package/docker-compose.yml +1 -1
- package/jsdoc.json +1 -1
- package/manifests/calico-custom-resources.yaml +25 -0
- package/manifests/deployment/adminer/deployment.yaml +32 -0
- package/manifests/deployment/adminer/kustomization.yaml +7 -0
- package/manifests/deployment/adminer/service.yaml +13 -0
- package/manifests/deployment/fastapi/backend-deployment.yml +120 -0
- package/manifests/deployment/fastapi/backend-service.yml +19 -0
- package/manifests/deployment/fastapi/frontend-deployment.yml +54 -0
- package/manifests/deployment/fastapi/frontend-service.yml +15 -0
- package/manifests/deployment/kafka/deployment.yaml +69 -0
- package/manifests/kubeadm-calico-config.yaml +119 -0
- package/manifests/mongodb-4.4/service-deployment.yaml +1 -1
- package/manifests/postgresql/configmap.yaml +9 -0
- package/manifests/postgresql/kustomization.yaml +10 -0
- package/manifests/postgresql/pv.yaml +15 -0
- package/manifests/postgresql/pvc.yaml +13 -0
- package/manifests/postgresql/service.yaml +10 -0
- package/manifests/postgresql/statefulset.yaml +37 -0
- package/manifests/valkey/statefulset.yaml +6 -4
- package/package.json +3 -9
- package/src/api/default/default.service.js +1 -1
- package/src/api/user/user.service.js +14 -11
- package/src/cli/cluster.js +207 -20
- package/src/cli/cron.js +39 -8
- package/src/cli/db.js +20 -10
- package/src/cli/deploy.js +254 -85
- package/src/cli/env.js +9 -3
- package/src/cli/fs.js +21 -9
- package/src/cli/image.js +42 -124
- package/src/cli/index.js +312 -0
- package/src/cli/monitor.js +236 -0
- package/src/cli/repository.js +5 -2
- package/src/client/components/core/Account.js +28 -24
- package/src/client/components/core/Blockchain.js +1 -1
- package/src/client/components/core/CalendarCore.js +14 -84
- package/src/client/components/core/CommonJs.js +2 -1
- package/src/client/components/core/Css.js +0 -1
- package/src/client/components/core/CssCore.js +10 -2
- package/src/client/components/core/Docs.js +1 -1
- package/src/client/components/core/EventsUI.js +3 -3
- package/src/client/components/core/FileExplorer.js +86 -78
- package/src/client/components/core/JoyStick.js +2 -2
- package/src/client/components/core/LoadingAnimation.js +1 -17
- package/src/client/components/core/LogIn.js +3 -3
- package/src/client/components/core/LogOut.js +1 -1
- package/src/client/components/core/Modal.js +14 -8
- package/src/client/components/core/Panel.js +19 -61
- package/src/client/components/core/PanelForm.js +13 -22
- package/src/client/components/core/Recover.js +3 -3
- package/src/client/components/core/RichText.js +1 -11
- package/src/client/components/core/Router.js +3 -1
- package/src/client/components/core/SignUp.js +2 -2
- package/src/client/components/default/RoutesDefault.js +3 -2
- package/src/client/services/default/default.management.js +45 -38
- package/src/client/ssr/Render.js +2 -0
- package/src/index.js +18 -2
- package/src/mailer/MailerProvider.js +3 -0
- package/src/runtime/lampp/Dockerfile +65 -0
- package/src/server/client-build.js +13 -0
- package/src/server/conf.js +93 -1
- package/src/server/dns.js +56 -18
- package/src/server/json-schema.js +77 -0
- package/src/server/network.js +7 -122
- package/src/server/peer.js +2 -2
- package/src/server/proxy.js +4 -4
- package/src/server/runtime.js +24 -11
- package/src/server/start.js +122 -0
- package/src/server/valkey.js +25 -11
package/src/cli/deploy.js
CHANGED
|
@@ -3,22 +3,41 @@ import {
|
|
|
3
3
|
buildPortProxyRouter,
|
|
4
4
|
buildProxyRouter,
|
|
5
5
|
Config,
|
|
6
|
+
deployRangePortFactory,
|
|
6
7
|
getDataDeploy,
|
|
7
8
|
loadReplicas,
|
|
9
|
+
pathPortAssignmentFactory,
|
|
8
10
|
} from '../server/conf.js';
|
|
9
11
|
import { loggerFactory } from '../server/logger.js';
|
|
10
12
|
import { shellExec } from '../server/process.js';
|
|
11
13
|
import fs from 'fs-extra';
|
|
12
14
|
import dotenv from 'dotenv';
|
|
13
|
-
import
|
|
15
|
+
import { DataBaseProvider } from '../db/DataBaseProvider.js';
|
|
16
|
+
import UnderpostRootEnv from './env.js';
|
|
17
|
+
import UnderpostCluster from './cluster.js';
|
|
14
18
|
|
|
15
19
|
const logger = loggerFactory(import.meta);
|
|
16
20
|
|
|
17
21
|
class UnderpostDeploy {
|
|
22
|
+
static NETWORK = {};
|
|
18
23
|
static API = {
|
|
19
|
-
sync(deployList) {
|
|
20
|
-
const deployGroupId = 'dd.
|
|
24
|
+
sync(deployList, { versions, replicas }) {
|
|
25
|
+
const deployGroupId = 'dd.router';
|
|
21
26
|
fs.writeFileSync(`./engine-private/deploy/${deployGroupId}`, deployList, 'utf8');
|
|
27
|
+
const totalPods = deployList.split(',').length * versions.split(',').length * parseInt(replicas);
|
|
28
|
+
const limitFactor = 0.8;
|
|
29
|
+
const reserveFactor = 0.05;
|
|
30
|
+
const resources = UnderpostCluster.API.getResourcesCapacity();
|
|
31
|
+
const memory = parseInt(resources.memory.value / totalPods);
|
|
32
|
+
const cpu = parseInt(resources.cpu.value / totalPods);
|
|
33
|
+
UnderpostRootEnv.API.set(
|
|
34
|
+
'resources.requests.memory',
|
|
35
|
+
`${parseInt(memory * reserveFactor)}${resources.memory.unit}`,
|
|
36
|
+
);
|
|
37
|
+
UnderpostRootEnv.API.set('resources.requests.cpu', `${parseInt(cpu * reserveFactor)}${resources.cpu.unit}`);
|
|
38
|
+
UnderpostRootEnv.API.set('resources.limits.memory', `${parseInt(memory * limitFactor)}${resources.memory.unit}`);
|
|
39
|
+
UnderpostRootEnv.API.set('resources.limits.cpu', `${parseInt(cpu * limitFactor)}${resources.cpu.unit}`);
|
|
40
|
+
UnderpostRootEnv.API.set('total-pods', totalPods);
|
|
22
41
|
return getDataDeploy({
|
|
23
42
|
buildSingleReplica: true,
|
|
24
43
|
deployGroupId,
|
|
@@ -32,75 +51,102 @@ class UnderpostDeploy {
|
|
|
32
51
|
await Config.build(undefined, 'proxy', deployList);
|
|
33
52
|
return buildPortProxyRouter(env === 'development' ? 80 : 443, buildProxyRouter());
|
|
34
53
|
},
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
fs.mkdirSync(`./engine-private/conf/${deployId}/build/${env}`, { recursive: true });
|
|
50
|
-
if (env === 'development') fs.mkdirSync(`./manifests/deployment/${deployId}-${env}`, { recursive: true });
|
|
51
|
-
|
|
52
|
-
logger.info('port range', { deployId, fromPort, toPort });
|
|
53
|
-
|
|
54
|
-
const deploymentYamlParts = `apiVersion: apps/v1
|
|
54
|
+
deploymentYamlServiceFactory({ deployId, env, port, deploymentVersions }) {
|
|
55
|
+
return deploymentVersions
|
|
56
|
+
.map(
|
|
57
|
+
(version, i) => ` - name: ${deployId}-${env}-${version}-service
|
|
58
|
+
port: ${port}
|
|
59
|
+
weight: ${i === 0 ? 100 : 0}
|
|
60
|
+
`,
|
|
61
|
+
)
|
|
62
|
+
.join('');
|
|
63
|
+
},
|
|
64
|
+
deploymentYamlPartsFactory({ deployId, env, suffix, resources, replicas }) {
|
|
65
|
+
return `apiVersion: apps/v1
|
|
55
66
|
kind: Deployment
|
|
56
67
|
metadata:
|
|
57
|
-
name: ${deployId}-${env}
|
|
68
|
+
name: ${deployId}-${env}-${suffix}
|
|
58
69
|
labels:
|
|
59
|
-
app: ${deployId}-${env}
|
|
70
|
+
app: ${deployId}-${env}-${suffix}
|
|
60
71
|
spec:
|
|
61
|
-
replicas:
|
|
72
|
+
replicas: ${replicas}
|
|
62
73
|
selector:
|
|
63
74
|
matchLabels:
|
|
64
|
-
app: ${deployId}-${env}
|
|
75
|
+
app: ${deployId}-${env}-${suffix}
|
|
65
76
|
template:
|
|
66
77
|
metadata:
|
|
67
78
|
labels:
|
|
68
|
-
app: ${deployId}-${env}
|
|
79
|
+
app: ${deployId}-${env}-${suffix}
|
|
69
80
|
spec:
|
|
70
81
|
containers:
|
|
71
|
-
- name: ${deployId}-${env}
|
|
72
|
-
image: localhost/underpost
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
82
|
+
- name: ${deployId}-${env}-${suffix}
|
|
83
|
+
image: localhost/debian:underpost
|
|
84
|
+
resources:
|
|
85
|
+
requests:
|
|
86
|
+
memory: "${resources.requests.memory}"
|
|
87
|
+
cpu: "${resources.requests.cpu}"
|
|
88
|
+
limits:
|
|
89
|
+
memory: "${resources.limits.memory}"
|
|
90
|
+
cpu: "${resources.limits.cpu}"
|
|
91
|
+
command:
|
|
92
|
+
- /bin/sh
|
|
93
|
+
- -c
|
|
94
|
+
- >
|
|
95
|
+
npm install -g npm@11.2.0 &&
|
|
96
|
+
npm install -g underpost &&
|
|
97
|
+
underpost secret underpost --create-from-file /etc/config/.env.${env} &&
|
|
98
|
+
underpost start --build --run ${deployId} ${env}
|
|
99
|
+
volumeMounts:
|
|
100
|
+
- name: config-volume
|
|
101
|
+
mountPath: /etc/config
|
|
102
|
+
volumes:
|
|
103
|
+
- name: config-volume
|
|
104
|
+
configMap:
|
|
105
|
+
name: underpost-config
|
|
84
106
|
---
|
|
85
107
|
apiVersion: v1
|
|
86
108
|
kind: Service
|
|
87
109
|
metadata:
|
|
88
|
-
name: ${deployId}-${env}-service
|
|
110
|
+
name: ${deployId}-${env}-${suffix}-service
|
|
89
111
|
spec:
|
|
90
112
|
selector:
|
|
91
|
-
app: ${deployId}-${env}
|
|
113
|
+
app: ${deployId}-${env}-${suffix}
|
|
92
114
|
ports:
|
|
93
|
-
type: LoadBalancer
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
115
|
+
{{ports}} type: LoadBalancer`;
|
|
116
|
+
},
|
|
117
|
+
async buildManifest(deployList, env, options) {
|
|
118
|
+
const resources = UnderpostDeploy.API.resourcesFactory();
|
|
119
|
+
const replicas = options.replicas;
|
|
98
120
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
121
|
+
for (const _deployId of deployList.split(',')) {
|
|
122
|
+
const deployId = _deployId.trim();
|
|
123
|
+
if (!deployId) continue;
|
|
124
|
+
const confServer = loadReplicas(
|
|
125
|
+
JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8')),
|
|
126
|
+
'proxy',
|
|
103
127
|
);
|
|
128
|
+
const router = await UnderpostDeploy.API.routerFactory(deployId, env);
|
|
129
|
+
const pathPortAssignmentData = pathPortAssignmentFactory(router, confServer);
|
|
130
|
+
const { fromPort, toPort } = deployRangePortFactory(router);
|
|
131
|
+
const deploymentVersions = options.versions.split(',');
|
|
132
|
+
fs.mkdirSync(`./engine-private/conf/${deployId}/build/${env}`, { recursive: true });
|
|
133
|
+
if (env === 'development') fs.mkdirSync(`./manifests/deployment/${deployId}-${env}`, { recursive: true });
|
|
134
|
+
|
|
135
|
+
logger.info('port range', { deployId, fromPort, toPort });
|
|
136
|
+
|
|
137
|
+
let deploymentYamlParts = '';
|
|
138
|
+
for (const deploymentVersion of deploymentVersions) {
|
|
139
|
+
deploymentYamlParts += `---
|
|
140
|
+
${UnderpostDeploy.API.deploymentYamlPartsFactory({
|
|
141
|
+
deployId,
|
|
142
|
+
env,
|
|
143
|
+
suffix: deploymentVersion,
|
|
144
|
+
resources,
|
|
145
|
+
replicas,
|
|
146
|
+
}).replace('{{ports}}', buildKindPorts(fromPort, toPort))}
|
|
147
|
+
`;
|
|
148
|
+
}
|
|
149
|
+
fs.writeFileSync(`./engine-private/conf/${deployId}/build/${env}/deployment.yaml`, deploymentYamlParts, 'utf8');
|
|
104
150
|
|
|
105
151
|
let proxyYaml = '';
|
|
106
152
|
let secretYaml = '';
|
|
@@ -122,27 +168,8 @@ spec:
|
|
|
122
168
|
kind: ClusterIssuer
|
|
123
169
|
secretName: ${host}`;
|
|
124
170
|
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
const { peer } = confServer[host][path];
|
|
128
|
-
if (!router[`${host}${path === '/' ? '' : path}`]) continue;
|
|
129
|
-
const port = parseInt(router[`${host}${path === '/' ? '' : path}`].split(':')[2]);
|
|
130
|
-
// logger.info('', { host, port, path });
|
|
131
|
-
pathPortConditions.push({
|
|
132
|
-
port,
|
|
133
|
-
path,
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
if (peer) {
|
|
137
|
-
// logger.info('', { host, port: port + 1, path: '/peer' });
|
|
138
|
-
pathPortConditions.push({
|
|
139
|
-
port: port + 1,
|
|
140
|
-
path: '/peer',
|
|
141
|
-
});
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// logger.info('', { host, pathPortConditions });
|
|
171
|
+
const pathPortAssignment = pathPortAssignmentData[host];
|
|
172
|
+
// logger.info('', { host, pathPortAssignment });
|
|
146
173
|
proxyYaml += `
|
|
147
174
|
---
|
|
148
175
|
apiVersion: projectcontour.io/v1
|
|
@@ -159,15 +186,20 @@ spec:
|
|
|
159
186
|
secretName: ${host}`
|
|
160
187
|
}
|
|
161
188
|
routes:`;
|
|
162
|
-
for (const conditionObj of
|
|
189
|
+
for (const conditionObj of pathPortAssignment) {
|
|
163
190
|
const { path, port } = conditionObj;
|
|
164
191
|
proxyYaml += `
|
|
165
192
|
- conditions:
|
|
166
193
|
- prefix: ${path}
|
|
167
194
|
enableWebsockets: true
|
|
168
195
|
services:
|
|
169
|
-
|
|
170
|
-
|
|
196
|
+
${UnderpostDeploy.API.deploymentYamlServiceFactory({
|
|
197
|
+
deployId,
|
|
198
|
+
env,
|
|
199
|
+
port,
|
|
200
|
+
deploymentVersions:
|
|
201
|
+
options.traffic && typeof options.traffic === 'string' ? options.traffic.split(',') : ['blue'],
|
|
202
|
+
})}`;
|
|
171
203
|
}
|
|
172
204
|
}
|
|
173
205
|
const yamlPath = `./engine-private/conf/${deployId}/build/${env}/proxy.yaml`;
|
|
@@ -188,6 +220,14 @@ spec:
|
|
|
188
220
|
}
|
|
189
221
|
}
|
|
190
222
|
},
|
|
223
|
+
getCurrentTraffic(deployId) {
|
|
224
|
+
// kubectl get deploy,sts,svc,configmap,secret -n default -o yaml --export > default.yaml
|
|
225
|
+
const hostTest = Object.keys(
|
|
226
|
+
JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8')),
|
|
227
|
+
)[0];
|
|
228
|
+
const info = shellExec(`sudo kubectl get HTTPProxy/${hostTest} -o yaml`, { silent: true, stdout: true });
|
|
229
|
+
return info.match('blue') ? 'blue' : info.match('green') ? 'green' : null;
|
|
230
|
+
},
|
|
191
231
|
async callback(
|
|
192
232
|
deployList = 'default',
|
|
193
233
|
env = 'development',
|
|
@@ -199,7 +239,13 @@ spec:
|
|
|
199
239
|
infoUtil: false,
|
|
200
240
|
expose: false,
|
|
201
241
|
cert: false,
|
|
202
|
-
|
|
242
|
+
versions: '',
|
|
243
|
+
traffic: '',
|
|
244
|
+
dashboardUpdate: false,
|
|
245
|
+
replicas: '',
|
|
246
|
+
disableUpdateDeployment: false,
|
|
247
|
+
infoTraffic: false,
|
|
248
|
+
rebuildClientsBundle: false,
|
|
203
249
|
},
|
|
204
250
|
) {
|
|
205
251
|
if (options.infoUtil === true)
|
|
@@ -207,13 +253,48 @@ spec:
|
|
|
207
253
|
kubectl rollout restart deployment/deployment-name
|
|
208
254
|
kubectl rollout undo deployment/deployment-name
|
|
209
255
|
kubectl scale statefulsets <stateful-set-name> --replicas=<new-replicas>
|
|
210
|
-
|
|
256
|
+
kubectl get pods -w
|
|
257
|
+
kubectl patch statefulset service-valkey --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"valkey/valkey:latest"}]'
|
|
258
|
+
kubectl patch statefulset service-valkey -p '{"spec":{"template":{"spec":{"containers":[{"name":"service-valkey","imagePullPolicy":"Never"}]}}}}'
|
|
259
|
+
kubectl logs -f <pod-name>
|
|
260
|
+
kubectl describe pod <pod-name>
|
|
261
|
+
kubectl exec -it <pod-name> -- bash
|
|
262
|
+
kubectl exec -it <pod-name> -- sh
|
|
263
|
+
docker exec -it kind-control-plane bash
|
|
264
|
+
curl -4 -v google.com
|
|
265
|
+
kubectl taint nodes <node-name> node-role.kubernetes.io/control-plane:NoSchedule-
|
|
266
|
+
kubectl run test-pod --image=busybox:latest --restart=Never -- /bin/sh -c "while true; do sleep 30; done;"
|
|
267
|
+
kubectl run test-pod --image=alpine/curl:latest --restart=Never -- sh -c "sleep infinity"
|
|
268
|
+
kubectl get ippools -o yaml
|
|
269
|
+
kubectl get node <node-name> -o jsonpath='{.spec.podCIDR}'
|
|
270
|
+
kubectl patch ippool default-ipv4-ippool --type='json' -p='[{"op": "replace", "path": "/spec/cidr", "value": "10.244.0.0/16"}]'
|
|
271
|
+
kubectl patch ippool default-ipv4-ippool --type='json' -p='[{"op": "replace", "path": "/spec/cidr", "value": "192.168.0.0/24"}]'
|
|
272
|
+
`);
|
|
211
273
|
if (deployList === 'dd' && fs.existsSync(`./engine-private/deploy/dd.router`))
|
|
212
274
|
deployList = fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8');
|
|
213
|
-
if (options.
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
275
|
+
if (options.infoTraffic === true) {
|
|
276
|
+
for (const _deployId of deployList.split(',')) {
|
|
277
|
+
const deployId = _deployId.trim();
|
|
278
|
+
logger.info('', {
|
|
279
|
+
deployId,
|
|
280
|
+
env,
|
|
281
|
+
traffic: UnderpostDeploy.API.getCurrentTraffic(deployId),
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
if (options.rebuildClientsBundle === true) await UnderpostDeploy.API.rebuildClientsBundle(deployList);
|
|
287
|
+
if (!(options.versions && typeof options.versions === 'string')) options.versions = 'blue,green';
|
|
288
|
+
if (!options.replicas) options.replicas = 1;
|
|
289
|
+
if (options.sync) UnderpostDeploy.API.sync(deployList, options);
|
|
290
|
+
if (options.buildManifest === true) await UnderpostDeploy.API.buildManifest(deployList, env, options);
|
|
291
|
+
if (options.infoRouter === true) logger.info('router', await UnderpostDeploy.API.routerFactory(deployList, env));
|
|
292
|
+
if (options.dashboardUpdate === true) await UnderpostDeploy.API.updateDashboardData(deployList, env, options);
|
|
293
|
+
if (options.infoRouter === true) return;
|
|
294
|
+
shellExec(`kubectl delete configmap underpost-config`);
|
|
295
|
+
shellExec(
|
|
296
|
+
`kubectl create configmap underpost-config --from-file=/home/dd/engine/engine-private/conf/dd-cron/.env.${env}`,
|
|
297
|
+
);
|
|
217
298
|
const etcHost = (
|
|
218
299
|
concat,
|
|
219
300
|
) => `127.0.0.1 ${concat} localhost localhost.localdomain localhost4 localhost4.localdomain4
|
|
@@ -233,8 +314,12 @@ kubectl scale statefulsets <stateful-set-name> --replicas=<new-replicas>
|
|
|
233
314
|
shellExec(`sudo kubectl port-forward -n default svc/${svc.NAME} ${port}:${port}`, { async: true });
|
|
234
315
|
continue;
|
|
235
316
|
}
|
|
236
|
-
|
|
237
|
-
|
|
317
|
+
|
|
318
|
+
if (!options.disableUpdateDeployment)
|
|
319
|
+
for (const version of options.versions.split(',')) {
|
|
320
|
+
shellExec(`sudo kubectl delete svc ${deployId}-${env}-${version}-service`);
|
|
321
|
+
shellExec(`sudo kubectl delete deployment ${deployId}-${env}-${version}`);
|
|
322
|
+
}
|
|
238
323
|
|
|
239
324
|
const confServer = JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'));
|
|
240
325
|
for (const host of Object.keys(confServer)) {
|
|
@@ -249,7 +334,7 @@ kubectl scale statefulsets <stateful-set-name> --replicas=<new-replicas>
|
|
|
249
334
|
: `manifests/deployment/${deployId}-${env}`;
|
|
250
335
|
|
|
251
336
|
if (!options.remove === true) {
|
|
252
|
-
shellExec(`sudo kubectl apply -f ./${manifestsPath}/deployment.yaml`);
|
|
337
|
+
if (!options.disableUpdateDeployment) shellExec(`sudo kubectl apply -f ./${manifestsPath}/deployment.yaml`);
|
|
253
338
|
shellExec(`sudo kubectl apply -f ./${manifestsPath}/proxy.yaml`);
|
|
254
339
|
if (env === 'production' && options.cert === true)
|
|
255
340
|
shellExec(`sudo kubectl apply -f ./${manifestsPath}/secret.yaml`);
|
|
@@ -312,6 +397,90 @@ kubectl scale statefulsets <stateful-set-name> --replicas=<new-replicas>
|
|
|
312
397
|
|
|
313
398
|
return result;
|
|
314
399
|
},
|
|
400
|
+
rebuildClientsBundle(deployList) {
|
|
401
|
+
for (const _deployId of deployList.split(',')) {
|
|
402
|
+
const deployId = _deployId.trim();
|
|
403
|
+
const repoName = `engine-${deployId.split('-')[1]}`;
|
|
404
|
+
|
|
405
|
+
shellExec(`underpost script set ${deployId}-client-build '
|
|
406
|
+
cd /home/dd/engine &&
|
|
407
|
+
git checkout . &&
|
|
408
|
+
underpost pull . underpostnet/${repoName} &&
|
|
409
|
+
underpost pull ./engine-private underpostnet/${repoName}-private &&
|
|
410
|
+
underpost env ${deployId} production &&
|
|
411
|
+
node bin/deploy build-full-client ${deployId}
|
|
412
|
+
'`);
|
|
413
|
+
|
|
414
|
+
shellExec(`node bin script run ${deployId}-client-build --itc --pod-name ${deployId}`);
|
|
415
|
+
}
|
|
416
|
+
},
|
|
417
|
+
resourcesFactory() {
|
|
418
|
+
return {
|
|
419
|
+
requests: {
|
|
420
|
+
memory: UnderpostRootEnv.API.get('resources.requests.memory'),
|
|
421
|
+
cpu: UnderpostRootEnv.API.get('resources.requests.cpu'),
|
|
422
|
+
},
|
|
423
|
+
limits: {
|
|
424
|
+
memory: UnderpostRootEnv.API.get('resources.limits.memory'),
|
|
425
|
+
cpu: UnderpostRootEnv.API.get('resources.limits.cpu'),
|
|
426
|
+
},
|
|
427
|
+
totalPods: UnderpostRootEnv.API.get('total-pods'),
|
|
428
|
+
};
|
|
429
|
+
},
|
|
430
|
+
async updateDashboardData(deployList, env, options) {
|
|
431
|
+
try {
|
|
432
|
+
const deployId = process.env.DEFAULT_DEPLOY_ID;
|
|
433
|
+
const host = process.env.DEFAULT_DEPLOY_HOST;
|
|
434
|
+
const path = process.env.DEFAULT_DEPLOY_PATH;
|
|
435
|
+
const { db } = JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'))[host][
|
|
436
|
+
path
|
|
437
|
+
];
|
|
438
|
+
|
|
439
|
+
await DataBaseProvider.load({ apis: ['instance'], host, path, db });
|
|
440
|
+
|
|
441
|
+
/** @type {import('../api/instance/instance.model.js').InstanceModel} */
|
|
442
|
+
const Instance = DataBaseProvider.instance[`${host}${path}`].mongoose.models.Instance;
|
|
443
|
+
|
|
444
|
+
await Instance.deleteMany();
|
|
445
|
+
|
|
446
|
+
for (const _deployId of deployList.split(',')) {
|
|
447
|
+
const deployId = _deployId.trim();
|
|
448
|
+
if (!deployId) continue;
|
|
449
|
+
const confServer = loadReplicas(
|
|
450
|
+
JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8')),
|
|
451
|
+
'proxy',
|
|
452
|
+
);
|
|
453
|
+
const router = await UnderpostDeploy.API.routerFactory(deployId, env);
|
|
454
|
+
const pathPortAssignmentData = pathPortAssignmentFactory(router, confServer);
|
|
455
|
+
|
|
456
|
+
for (const host of Object.keys(confServer)) {
|
|
457
|
+
for (const { path, port } of pathPortAssignmentData[host]) {
|
|
458
|
+
if (!confServer[host][path]) continue;
|
|
459
|
+
|
|
460
|
+
const { client, runtime, apis } = confServer[host][path];
|
|
461
|
+
|
|
462
|
+
const body = {
|
|
463
|
+
deployId,
|
|
464
|
+
host,
|
|
465
|
+
path,
|
|
466
|
+
port,
|
|
467
|
+
client,
|
|
468
|
+
runtime,
|
|
469
|
+
apis,
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
logger.info('save', body);
|
|
473
|
+
|
|
474
|
+
await new Instance(body).save();
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
await DataBaseProvider.instance[`${host}${path}`].mongoose.close();
|
|
480
|
+
} catch (error) {
|
|
481
|
+
logger.error(error, error.stack);
|
|
482
|
+
}
|
|
483
|
+
},
|
|
315
484
|
};
|
|
316
485
|
}
|
|
317
486
|
|
package/src/cli/env.js
CHANGED
|
@@ -28,15 +28,21 @@ class UnderpostRootEnv {
|
|
|
28
28
|
get(key) {
|
|
29
29
|
const exeRootPath = `${getNpmRootPath()}/underpost`;
|
|
30
30
|
const envPath = `${exeRootPath}/.env`;
|
|
31
|
-
if (!fs.existsSync(envPath))
|
|
31
|
+
if (!fs.existsSync(envPath)) {
|
|
32
|
+
logger.error(`Unable to find underpost root environment`);
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
32
35
|
const env = dotenv.parse(fs.readFileSync(envPath, 'utf8'));
|
|
33
|
-
logger.info(
|
|
36
|
+
logger.info(`${key}(${typeof env[key]})`, env[key]);
|
|
34
37
|
return env[key];
|
|
35
38
|
},
|
|
36
39
|
list() {
|
|
37
40
|
const exeRootPath = `${getNpmRootPath()}/underpost`;
|
|
38
41
|
const envPath = `${exeRootPath}/.env`;
|
|
39
|
-
if (!fs.existsSync(envPath))
|
|
42
|
+
if (!fs.existsSync(envPath)) {
|
|
43
|
+
logger.error(`Unable to find underpost root environment`);
|
|
44
|
+
return {};
|
|
45
|
+
}
|
|
40
46
|
const env = dotenv.parse(fs.readFileSync(envPath, 'utf8'));
|
|
41
47
|
logger.info('underpost root', env);
|
|
42
48
|
return env;
|
package/src/cli/fs.js
CHANGED
|
@@ -24,7 +24,7 @@ class UnderpostFileStorage {
|
|
|
24
24
|
getStorageConf(options) {
|
|
25
25
|
let storage, storageConf;
|
|
26
26
|
if (options.deployId && typeof options.deployId === 'string') {
|
|
27
|
-
storageConf = `./engine-private/conf/${options.deployId}/storage.json`;
|
|
27
|
+
storageConf = options.storageFilePath ?? `./engine-private/conf/${options.deployId}/storage.json`;
|
|
28
28
|
if (!fs.existsSync(storageConf)) fs.writeFileSync(storageConf, JSON.stringify({}), 'utf8');
|
|
29
29
|
storage = JSON.parse(fs.readFileSync(storageConf, 'utf8'));
|
|
30
30
|
}
|
|
@@ -35,10 +35,18 @@ class UnderpostFileStorage {
|
|
|
35
35
|
},
|
|
36
36
|
async recursiveCallback(
|
|
37
37
|
path,
|
|
38
|
-
options = {
|
|
38
|
+
options = {
|
|
39
|
+
rm: false,
|
|
40
|
+
recursive: false,
|
|
41
|
+
deployId: '',
|
|
42
|
+
force: false,
|
|
43
|
+
pull: false,
|
|
44
|
+
git: false,
|
|
45
|
+
storageFilePath: '',
|
|
46
|
+
},
|
|
39
47
|
) {
|
|
40
48
|
const { storage, storageConf } = UnderpostFileStorage.API.getStorageConf(options);
|
|
41
|
-
const deleteFiles = UnderpostRepository.API.getDeleteFiles(path);
|
|
49
|
+
const deleteFiles = options.pull === true ? [] : UnderpostRepository.API.getDeleteFiles(path);
|
|
42
50
|
for (const relativePath of deleteFiles) {
|
|
43
51
|
const _path = path + '/' + relativePath;
|
|
44
52
|
if (_path in storage) {
|
|
@@ -46,10 +54,6 @@ class UnderpostFileStorage {
|
|
|
46
54
|
delete storage[_path];
|
|
47
55
|
}
|
|
48
56
|
}
|
|
49
|
-
const files =
|
|
50
|
-
options.git === true
|
|
51
|
-
? UnderpostRepository.API.getChangedFiles(path)
|
|
52
|
-
: await fs.readdir(path, { recursive: true });
|
|
53
57
|
if (options.pull === true) {
|
|
54
58
|
for (const _path of Object.keys(storage)) {
|
|
55
59
|
if (!fs.existsSync(_path) || options.force === true) {
|
|
@@ -57,7 +61,11 @@ class UnderpostFileStorage {
|
|
|
57
61
|
await UnderpostFileStorage.API.pull(_path, options);
|
|
58
62
|
} else logger.warn(`Pull path already exists`, _path);
|
|
59
63
|
}
|
|
60
|
-
} else
|
|
64
|
+
} else {
|
|
65
|
+
const files =
|
|
66
|
+
options.git === true
|
|
67
|
+
? UnderpostRepository.API.getChangedFiles(path)
|
|
68
|
+
: await fs.readdir(path, { recursive: true });
|
|
61
69
|
for (const relativePath of files) {
|
|
62
70
|
const _path = path + '/' + relativePath;
|
|
63
71
|
if (fs.statSync(_path).isDirectory()) {
|
|
@@ -68,6 +76,7 @@ class UnderpostFileStorage {
|
|
|
68
76
|
if (storage) storage[_path] = {};
|
|
69
77
|
} else logger.warn('File already exists', _path);
|
|
70
78
|
}
|
|
79
|
+
}
|
|
71
80
|
UnderpostFileStorage.API.writeStorageConf(storage, storageConf);
|
|
72
81
|
if (options.git === true) {
|
|
73
82
|
shellExec(`cd ${path} && git add .`);
|
|
@@ -84,7 +93,10 @@ class UnderpostFileStorage {
|
|
|
84
93
|
if (options.rm === true) return await UnderpostFileStorage.API.delete(path, options);
|
|
85
94
|
return await UnderpostFileStorage.API.upload(path, options);
|
|
86
95
|
},
|
|
87
|
-
async upload(
|
|
96
|
+
async upload(
|
|
97
|
+
path,
|
|
98
|
+
options = { rm: false, recursive: false, deployId: '', force: false, pull: false, storageFilePath: '' },
|
|
99
|
+
) {
|
|
88
100
|
UnderpostFileStorage.API.cloudinaryConfig();
|
|
89
101
|
const { storage, storageConf } = UnderpostFileStorage.API.getStorageConf(options);
|
|
90
102
|
// path = UnderpostFileStorage.API.file2Zip(path);
|