@underpostnet/underpost 2.8.5 → 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/.github/workflows/ghpkg.yml +1 -1
- package/.github/workflows/npmpkg.yml +1 -1
- package/.github/workflows/pwa-microservices-template.page.yml +1 -1
- package/.vscode/extensions.json +3 -2
- package/.vscode/settings.json +6 -0
- package/CHANGELOG.md +44 -0
- package/Dockerfile +9 -10
- package/README.md +39 -2
- package/bin/build.js +31 -6
- package/bin/deploy.js +1404 -202
- package/bin/file.js +8 -0
- package/bin/hwt.js +0 -10
- package/bin/index.js +1 -187
- package/bin/util.js +0 -7
- package/bin/vs.js +1 -0
- package/cli.md +451 -0
- package/conf.js +0 -2
- 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/kind-config-dev.yaml +12 -0
- package/manifests/kubeadm-calico-config.yaml +119 -0
- package/manifests/mongodb/kustomization.yaml +2 -2
- package/manifests/mongodb-4.4/kustomization.yaml +7 -0
- package/manifests/mongodb-4.4/service-deployment.yaml +63 -0
- 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/{core/underpost-engine-headless-service.yaml → postgresql/service.yaml} +3 -3
- package/manifests/postgresql/statefulset.yaml +37 -0
- package/manifests/valkey/statefulset.yaml +6 -4
- package/package.json +10 -14
- package/src/api/default/default.service.js +1 -1
- package/src/api/user/user.service.js +14 -11
- package/src/cli/cluster.js +298 -63
- package/src/cli/cron.js +39 -8
- package/src/cli/db.js +118 -44
- package/src/cli/deploy.js +312 -102
- package/src/cli/env.js +9 -3
- package/src/cli/fs.js +161 -0
- package/src/cli/image.js +45 -104
- package/src/cli/index.js +312 -0
- package/src/cli/monitor.js +236 -0
- package/src/cli/repository.js +26 -2
- package/src/cli/script.js +25 -1
- package/src/cli/test.js +39 -4
- 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 -73
- package/src/client/components/core/CommonJs.js +54 -2
- package/src/client/components/core/Css.js +0 -1
- package/src/client/components/core/CssCore.js +10 -4
- package/src/client/components/core/Docs.js +1 -2
- package/src/client/components/core/EventsUI.js +3 -3
- package/src/client/components/core/FileExplorer.js +86 -78
- package/src/client/components/core/Input.js +4 -2
- package/src/client/components/core/JoyStick.js +2 -2
- package/src/client/components/core/LoadingAnimation.js +3 -12
- 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 +44 -14
- package/src/client/components/core/Panel.js +26 -66
- package/src/client/components/core/PanelForm.js +22 -15
- 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/core/core.service.js +15 -10
- package/src/client/services/default/default.management.js +45 -38
- package/src/client/ssr/Render.js +6 -1
- package/src/client/ssr/body/CacheControl.js +2 -3
- package/src/client/sw/default.sw.js +3 -3
- package/src/db/mongo/MongooseDB.js +17 -1
- package/src/index.js +25 -1
- package/src/mailer/MailerProvider.js +3 -0
- package/src/runtime/lampp/Dockerfile +65 -0
- package/src/server/backup.js +3 -3
- package/src/server/client-build.js +45 -23
- package/src/server/client-formatted.js +2 -1
- package/src/server/conf.js +110 -16
- package/src/server/dns.js +74 -43
- package/src/server/downloader.js +0 -8
- 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 +40 -12
- package/src/server/start.js +122 -0
- package/src/server/valkey.js +25 -11
- package/test/api.test.js +0 -8
- package/manifests/core/kustomization.yaml +0 -11
- package/manifests/core/underpost-engine-backup-access.yaml +0 -16
- package/manifests/core/underpost-engine-backup-pv-pvc.yaml +0 -22
- package/manifests/core/underpost-engine-mongodb-backup-cronjob.yaml +0 -40
- package/manifests/core/underpost-engine-mongodb-configmap.yaml +0 -26
- package/manifests/core/underpost-engine-statefulset.yaml +0 -91
- package/manifests/valkey/underpost-engine-valkey-service.yaml +0 -17
- package/manifests/valkey/underpost-engine-valkey-statefulset.yaml +0 -39
- /package/manifests/{core/underpost-engine-pv-pvc.yaml → mongodb-4.4/pv-pvc.yaml} +0 -0
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,64 +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
|
|
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
|
|
73
106
|
---
|
|
74
107
|
apiVersion: v1
|
|
75
108
|
kind: Service
|
|
76
109
|
metadata:
|
|
77
|
-
name: ${deployId}-${env}-service
|
|
110
|
+
name: ${deployId}-${env}-${suffix}-service
|
|
78
111
|
spec:
|
|
79
112
|
selector:
|
|
80
|
-
app: ${deployId}-${env}
|
|
113
|
+
app: ${deployId}-${env}-${suffix}
|
|
81
114
|
ports:
|
|
82
|
-
type: LoadBalancer
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
115
|
+
{{ports}} type: LoadBalancer`;
|
|
116
|
+
},
|
|
117
|
+
async buildManifest(deployList, env, options) {
|
|
118
|
+
const resources = UnderpostDeploy.API.resourcesFactory();
|
|
119
|
+
const replicas = options.replicas;
|
|
87
120
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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',
|
|
92
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');
|
|
93
150
|
|
|
94
151
|
let proxyYaml = '';
|
|
95
152
|
let secretYaml = '';
|
|
@@ -111,27 +168,8 @@ spec:
|
|
|
111
168
|
kind: ClusterIssuer
|
|
112
169
|
secretName: ${host}`;
|
|
113
170
|
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
const { peer } = confServer[host][path];
|
|
117
|
-
if (!router[`${host}${path === '/' ? '' : path}`]) continue;
|
|
118
|
-
const port = parseInt(router[`${host}${path === '/' ? '' : path}`].split(':')[2]);
|
|
119
|
-
// logger.info('', { host, port, path });
|
|
120
|
-
pathPortConditions.push({
|
|
121
|
-
port,
|
|
122
|
-
path,
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
if (peer) {
|
|
126
|
-
// logger.info('', { host, port: port + 1, path: '/peer' });
|
|
127
|
-
pathPortConditions.push({
|
|
128
|
-
port: port + 1,
|
|
129
|
-
path: '/peer',
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// logger.info('', { host, pathPortConditions });
|
|
171
|
+
const pathPortAssignment = pathPortAssignmentData[host];
|
|
172
|
+
// logger.info('', { host, pathPortAssignment });
|
|
135
173
|
proxyYaml += `
|
|
136
174
|
---
|
|
137
175
|
apiVersion: projectcontour.io/v1
|
|
@@ -148,15 +186,20 @@ spec:
|
|
|
148
186
|
secretName: ${host}`
|
|
149
187
|
}
|
|
150
188
|
routes:`;
|
|
151
|
-
for (const conditionObj of
|
|
189
|
+
for (const conditionObj of pathPortAssignment) {
|
|
152
190
|
const { path, port } = conditionObj;
|
|
153
191
|
proxyYaml += `
|
|
154
192
|
- conditions:
|
|
155
193
|
- prefix: ${path}
|
|
156
194
|
enableWebsockets: true
|
|
157
195
|
services:
|
|
158
|
-
|
|
159
|
-
|
|
196
|
+
${UnderpostDeploy.API.deploymentYamlServiceFactory({
|
|
197
|
+
deployId,
|
|
198
|
+
env,
|
|
199
|
+
port,
|
|
200
|
+
deploymentVersions:
|
|
201
|
+
options.traffic && typeof options.traffic === 'string' ? options.traffic.split(',') : ['blue'],
|
|
202
|
+
})}`;
|
|
160
203
|
}
|
|
161
204
|
}
|
|
162
205
|
const yamlPath = `./engine-private/conf/${deployId}/build/${env}/proxy.yaml`;
|
|
@@ -177,73 +220,156 @@ spec:
|
|
|
177
220
|
}
|
|
178
221
|
}
|
|
179
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
|
+
},
|
|
180
231
|
async callback(
|
|
181
232
|
deployList = 'default',
|
|
182
233
|
env = 'development',
|
|
183
|
-
options = {
|
|
234
|
+
options = {
|
|
235
|
+
remove: false,
|
|
236
|
+
infoRouter: false,
|
|
237
|
+
sync: false,
|
|
238
|
+
buildManifest: false,
|
|
239
|
+
infoUtil: false,
|
|
240
|
+
expose: false,
|
|
241
|
+
cert: false,
|
|
242
|
+
versions: '',
|
|
243
|
+
traffic: '',
|
|
244
|
+
dashboardUpdate: false,
|
|
245
|
+
replicas: '',
|
|
246
|
+
disableUpdateDeployment: false,
|
|
247
|
+
infoTraffic: false,
|
|
248
|
+
rebuildClientsBundle: false,
|
|
249
|
+
},
|
|
184
250
|
) {
|
|
251
|
+
if (options.infoUtil === true)
|
|
252
|
+
return logger.info(`
|
|
253
|
+
kubectl rollout restart deployment/deployment-name
|
|
254
|
+
kubectl rollout undo deployment/deployment-name
|
|
255
|
+
kubectl scale statefulsets <stateful-set-name> --replicas=<new-replicas>
|
|
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
|
+
`);
|
|
185
273
|
if (deployList === 'dd' && fs.existsSync(`./engine-private/deploy/dd.router`))
|
|
186
274
|
deployList = fs.readFileSync(`./engine-private/deploy/dd.router`, 'utf8');
|
|
187
|
-
if (options.
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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
|
+
);
|
|
298
|
+
const etcHost = (
|
|
299
|
+
concat,
|
|
300
|
+
) => `127.0.0.1 ${concat} localhost localhost.localdomain localhost4 localhost4.localdomain4
|
|
301
|
+
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6`;
|
|
302
|
+
let concatHots = '';
|
|
191
303
|
|
|
192
304
|
for (const _deployId of deployList.split(',')) {
|
|
193
305
|
const deployId = _deployId.trim();
|
|
194
306
|
if (!deployId) continue;
|
|
307
|
+
if (options.expose === true) {
|
|
308
|
+
const svc = UnderpostDeploy.API.get(deployId, 'svc')[0];
|
|
309
|
+
const port = parseInt(svc[`PORT(S)`].split('/TCP')[0]);
|
|
310
|
+
logger.info(deployId, {
|
|
311
|
+
svc,
|
|
312
|
+
port,
|
|
313
|
+
});
|
|
314
|
+
shellExec(`sudo kubectl port-forward -n default svc/${svc.NAME} ${port}:${port}`, { async: true });
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
195
317
|
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
) => `127.0.0.1 ${concat} localhost localhost.localdomain localhost4 localhost4.localdomain4
|
|
202
|
-
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6`;
|
|
203
|
-
let concatHots = '';
|
|
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
|
+
}
|
|
204
323
|
|
|
205
324
|
const confServer = JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'));
|
|
206
325
|
for (const host of Object.keys(confServer)) {
|
|
207
326
|
shellExec(`sudo kubectl delete HTTPProxy ${host}`);
|
|
327
|
+
if (env === 'production' && options.cert === true) shellExec(`sudo kubectl delete Certificate ${host}`);
|
|
208
328
|
if (!options.remove === true && env === 'development') concatHots += ` ${host}`;
|
|
209
329
|
}
|
|
210
330
|
|
|
331
|
+
const manifestsPath =
|
|
332
|
+
env === 'production'
|
|
333
|
+
? `engine-private/conf/${deployId}/build/production`
|
|
334
|
+
: `manifests/deployment/${deployId}-${env}`;
|
|
335
|
+
|
|
211
336
|
if (!options.remove === true) {
|
|
212
|
-
shellExec(`sudo kubectl apply -f
|
|
213
|
-
shellExec(`sudo kubectl apply -f
|
|
337
|
+
if (!options.disableUpdateDeployment) shellExec(`sudo kubectl apply -f ./${manifestsPath}/deployment.yaml`);
|
|
338
|
+
shellExec(`sudo kubectl apply -f ./${manifestsPath}/proxy.yaml`);
|
|
339
|
+
if (env === 'production' && options.cert === true)
|
|
340
|
+
shellExec(`sudo kubectl apply -f ./${manifestsPath}/secret.yaml`);
|
|
214
341
|
}
|
|
342
|
+
}
|
|
343
|
+
let renderHosts;
|
|
344
|
+
switch (process.platform) {
|
|
345
|
+
case 'linux':
|
|
346
|
+
{
|
|
347
|
+
switch (env) {
|
|
348
|
+
case 'development':
|
|
349
|
+
renderHosts = etcHost(concatHots);
|
|
350
|
+
fs.writeFileSync(`/etc/hosts`, renderHosts, 'utf8');
|
|
215
351
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
switch (process.platform) {
|
|
219
|
-
case 'linux':
|
|
220
|
-
{
|
|
221
|
-
switch (env) {
|
|
222
|
-
case 'development':
|
|
223
|
-
renderHosts = etcHost(concatHots);
|
|
224
|
-
fs.writeFileSync(`/etc/hosts`, renderHosts, 'utf8');
|
|
225
|
-
|
|
226
|
-
break;
|
|
352
|
+
break;
|
|
227
353
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
}
|
|
354
|
+
default:
|
|
355
|
+
break;
|
|
231
356
|
}
|
|
232
|
-
|
|
357
|
+
}
|
|
358
|
+
break;
|
|
233
359
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
360
|
+
default:
|
|
361
|
+
break;
|
|
362
|
+
}
|
|
363
|
+
if (renderHosts)
|
|
237
364
|
logger.info(
|
|
238
365
|
`
|
|
239
366
|
` + renderHosts,
|
|
240
367
|
);
|
|
241
|
-
}
|
|
242
368
|
},
|
|
243
|
-
|
|
244
|
-
const raw = shellExec(`sudo kubectl get
|
|
369
|
+
get(deployId, kindType = 'pods') {
|
|
370
|
+
const raw = shellExec(`sudo kubectl get ${kindType} --all-namespaces -o wide`, {
|
|
245
371
|
stdout: true,
|
|
246
|
-
disableLog:
|
|
372
|
+
disableLog: true,
|
|
247
373
|
silent: true,
|
|
248
374
|
});
|
|
249
375
|
|
|
@@ -271,6 +397,90 @@ spec:
|
|
|
271
397
|
|
|
272
398
|
return result;
|
|
273
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
|
+
},
|
|
274
484
|
};
|
|
275
485
|
}
|
|
276
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;
|