@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.
Files changed (109) hide show
  1. package/.github/workflows/ghpkg.yml +1 -1
  2. package/.github/workflows/npmpkg.yml +1 -1
  3. package/.github/workflows/pwa-microservices-template.page.yml +1 -1
  4. package/.vscode/extensions.json +3 -2
  5. package/.vscode/settings.json +6 -0
  6. package/CHANGELOG.md +44 -0
  7. package/Dockerfile +9 -10
  8. package/README.md +39 -2
  9. package/bin/build.js +31 -6
  10. package/bin/deploy.js +1404 -202
  11. package/bin/file.js +8 -0
  12. package/bin/hwt.js +0 -10
  13. package/bin/index.js +1 -187
  14. package/bin/util.js +0 -7
  15. package/bin/vs.js +1 -0
  16. package/cli.md +451 -0
  17. package/conf.js +0 -2
  18. package/docker-compose.yml +1 -1
  19. package/jsdoc.json +1 -1
  20. package/manifests/calico-custom-resources.yaml +25 -0
  21. package/manifests/deployment/adminer/deployment.yaml +32 -0
  22. package/manifests/deployment/adminer/kustomization.yaml +7 -0
  23. package/manifests/deployment/adminer/service.yaml +13 -0
  24. package/manifests/deployment/fastapi/backend-deployment.yml +120 -0
  25. package/manifests/deployment/fastapi/backend-service.yml +19 -0
  26. package/manifests/deployment/fastapi/frontend-deployment.yml +54 -0
  27. package/manifests/deployment/fastapi/frontend-service.yml +15 -0
  28. package/manifests/deployment/kafka/deployment.yaml +69 -0
  29. package/manifests/kind-config-dev.yaml +12 -0
  30. package/manifests/kubeadm-calico-config.yaml +119 -0
  31. package/manifests/mongodb/kustomization.yaml +2 -2
  32. package/manifests/mongodb-4.4/kustomization.yaml +7 -0
  33. package/manifests/mongodb-4.4/service-deployment.yaml +63 -0
  34. package/manifests/postgresql/configmap.yaml +9 -0
  35. package/manifests/postgresql/kustomization.yaml +10 -0
  36. package/manifests/postgresql/pv.yaml +15 -0
  37. package/manifests/postgresql/pvc.yaml +13 -0
  38. package/manifests/{core/underpost-engine-headless-service.yaml → postgresql/service.yaml} +3 -3
  39. package/manifests/postgresql/statefulset.yaml +37 -0
  40. package/manifests/valkey/statefulset.yaml +6 -4
  41. package/package.json +10 -14
  42. package/src/api/default/default.service.js +1 -1
  43. package/src/api/user/user.service.js +14 -11
  44. package/src/cli/cluster.js +298 -63
  45. package/src/cli/cron.js +39 -8
  46. package/src/cli/db.js +118 -44
  47. package/src/cli/deploy.js +312 -102
  48. package/src/cli/env.js +9 -3
  49. package/src/cli/fs.js +161 -0
  50. package/src/cli/image.js +45 -104
  51. package/src/cli/index.js +312 -0
  52. package/src/cli/monitor.js +236 -0
  53. package/src/cli/repository.js +26 -2
  54. package/src/cli/script.js +25 -1
  55. package/src/cli/test.js +39 -4
  56. package/src/client/components/core/Account.js +28 -24
  57. package/src/client/components/core/Blockchain.js +1 -1
  58. package/src/client/components/core/CalendarCore.js +14 -73
  59. package/src/client/components/core/CommonJs.js +54 -2
  60. package/src/client/components/core/Css.js +0 -1
  61. package/src/client/components/core/CssCore.js +10 -4
  62. package/src/client/components/core/Docs.js +1 -2
  63. package/src/client/components/core/EventsUI.js +3 -3
  64. package/src/client/components/core/FileExplorer.js +86 -78
  65. package/src/client/components/core/Input.js +4 -2
  66. package/src/client/components/core/JoyStick.js +2 -2
  67. package/src/client/components/core/LoadingAnimation.js +3 -12
  68. package/src/client/components/core/LogIn.js +3 -3
  69. package/src/client/components/core/LogOut.js +1 -1
  70. package/src/client/components/core/Modal.js +44 -14
  71. package/src/client/components/core/Panel.js +26 -66
  72. package/src/client/components/core/PanelForm.js +22 -15
  73. package/src/client/components/core/Recover.js +3 -3
  74. package/src/client/components/core/RichText.js +1 -11
  75. package/src/client/components/core/Router.js +3 -1
  76. package/src/client/components/core/SignUp.js +2 -2
  77. package/src/client/components/default/RoutesDefault.js +3 -2
  78. package/src/client/services/core/core.service.js +15 -10
  79. package/src/client/services/default/default.management.js +45 -38
  80. package/src/client/ssr/Render.js +6 -1
  81. package/src/client/ssr/body/CacheControl.js +2 -3
  82. package/src/client/sw/default.sw.js +3 -3
  83. package/src/db/mongo/MongooseDB.js +17 -1
  84. package/src/index.js +25 -1
  85. package/src/mailer/MailerProvider.js +3 -0
  86. package/src/runtime/lampp/Dockerfile +65 -0
  87. package/src/server/backup.js +3 -3
  88. package/src/server/client-build.js +45 -23
  89. package/src/server/client-formatted.js +2 -1
  90. package/src/server/conf.js +110 -16
  91. package/src/server/dns.js +74 -43
  92. package/src/server/downloader.js +0 -8
  93. package/src/server/json-schema.js +77 -0
  94. package/src/server/network.js +7 -122
  95. package/src/server/peer.js +2 -2
  96. package/src/server/proxy.js +4 -4
  97. package/src/server/runtime.js +40 -12
  98. package/src/server/start.js +122 -0
  99. package/src/server/valkey.js +25 -11
  100. package/test/api.test.js +0 -8
  101. package/manifests/core/kustomization.yaml +0 -11
  102. package/manifests/core/underpost-engine-backup-access.yaml +0 -16
  103. package/manifests/core/underpost-engine-backup-pv-pvc.yaml +0 -22
  104. package/manifests/core/underpost-engine-mongodb-backup-cronjob.yaml +0 -40
  105. package/manifests/core/underpost-engine-mongodb-configmap.yaml +0 -26
  106. package/manifests/core/underpost-engine-statefulset.yaml +0 -91
  107. package/manifests/valkey/underpost-engine-valkey-service.yaml +0 -17
  108. package/manifests/valkey/underpost-engine-valkey-statefulset.yaml +0 -39
  109. /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 Underpost from '../index.js';
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.tmp';
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
- async buildManifest(deployList, env) {
36
- for (const _deployId of deployList.split(',')) {
37
- const deployId = _deployId.trim();
38
- if (!deployId) continue;
39
-
40
- const router = await UnderpostDeploy.API.routerFactory(deployId, env);
41
- const ports = Object.values(router).map((p) => parseInt(p.split(':')[2]));
42
- const fromPort = Math.min(...ports);
43
- const toPort = Math.max(...ports);
44
- const confServer = loadReplicas(
45
- JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8')),
46
- 'proxy',
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: 2
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/${deployId}-${env}:${Underpost.version}
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`.split('ports:');
83
- deploymentYamlParts[1] =
84
- buildKindPorts(fromPort, toPort) +
85
- ` type: LoadBalancer
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
- fs.writeFileSync(
89
- `./engine-private/conf/${deployId}/build/${env}/deployment.yaml`,
90
- deploymentYamlParts.join(`ports:
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 pathPortConditions = [];
115
- for (const path of Object.keys(confServer[host])) {
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 pathPortConditions) {
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
- - name: ${deployId}-${env}-service
159
- port: ${port}`;
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 = { remove: false, infoRouter: false, sync: false, buildManifest: false },
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.sync) UnderpostDeploy.API.sync(deployList);
188
- if (options.buildManifest === true) await UnderpostDeploy.API.buildManifest(deployList, env);
189
- if (options.infoRouter === true)
190
- return logger.info('router', await UnderpostDeploy.API.routerFactory(deployList, env));
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
- shellExec(`sudo kubectl delete svc ${deployId}-${env}-service`);
197
- shellExec(`sudo kubectl delete deployment ${deployId}-${env}`);
198
-
199
- const etcHost = (
200
- concat,
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 ./manifests/deployment/${deployId}-${env}/deployment.yaml`);
213
- shellExec(`sudo kubectl apply -f ./manifests/deployment/${deployId}-${env}/proxy.yaml`);
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
- let renderHosts;
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
- default:
229
- break;
230
- }
354
+ default:
355
+ break;
231
356
  }
232
- break;
357
+ }
358
+ break;
233
359
 
234
- default:
235
- break;
236
- }
360
+ default:
361
+ break;
362
+ }
363
+ if (renderHosts)
237
364
  logger.info(
238
365
  `
239
366
  ` + renderHosts,
240
367
  );
241
- }
242
368
  },
243
- getPods(deployId) {
244
- const raw = shellExec(`sudo kubectl get pods --all-namespaces -o wide`, {
369
+ get(deployId, kindType = 'pods') {
370
+ const raw = shellExec(`sudo kubectl get ${kindType} --all-namespaces -o wide`, {
245
371
  stdout: true,
246
- disableLog: false,
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)) return logger.error(`Unable to find underpost root environment`);
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('underpost root', { [key]: env[key] });
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)) return logger.error(`Unable to find underpost root environment`);
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;