underpost 2.8.55 → 2.8.61

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 (42) 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/settings.json +3 -0
  5. package/bin/build.js +9 -0
  6. package/bin/index.js +31 -6
  7. package/bin/vs.js +1 -0
  8. package/docker-compose.yml +1 -1
  9. package/manifests/kind-config-dev.yaml +12 -0
  10. package/manifests/mongodb/kustomization.yaml +2 -2
  11. package/manifests/mongodb-4.4/service-deployment.yaml +4 -4
  12. package/package.json +8 -7
  13. package/src/cli/cluster.js +56 -30
  14. package/src/cli/cron.js +1 -1
  15. package/src/cli/db.js +102 -38
  16. package/src/cli/deploy.js +27 -6
  17. package/src/cli/fs.js +149 -0
  18. package/src/cli/image.js +36 -4
  19. package/src/cli/repository.js +21 -0
  20. package/src/cli/test.js +17 -6
  21. package/src/client/components/core/CalendarCore.js +12 -1
  22. package/src/client/components/core/CommonJs.js +52 -1
  23. package/src/client/components/core/CssCore.js +2 -4
  24. package/src/client/components/core/Docs.js +1 -2
  25. package/src/client/components/core/Input.js +4 -2
  26. package/src/client/components/core/LoadingAnimation.js +8 -1
  27. package/src/client/components/core/Modal.js +30 -6
  28. package/src/client/components/core/Panel.js +8 -6
  29. package/src/client/components/core/PanelForm.js +23 -7
  30. package/src/client/services/core/core.service.js +15 -10
  31. package/src/client/ssr/Render.js +4 -1
  32. package/src/client/ssr/body/CacheControl.js +2 -3
  33. package/src/client/sw/default.sw.js +3 -3
  34. package/src/index.js +9 -1
  35. package/src/server/backup.js +2 -2
  36. package/src/server/client-build.js +32 -23
  37. package/src/server/client-formatted.js +2 -1
  38. package/src/server/conf.js +1 -1
  39. package/src/server/dns.js +2 -2
  40. package/src/server/runtime.js +16 -1
  41. package/manifests/valkey/underpost-engine-valkey-service.yaml +0 -17
  42. package/manifests/valkey/underpost-engine-valkey-statefulset.yaml +0 -39
@@ -43,7 +43,7 @@ jobs:
43
43
  run: |
44
44
  npm install -g underpost
45
45
  underpost config set GITHUB_TOKEN ${{ secrets.GIT_AUTH_TOKEN }}
46
- underpost install
46
+ npm install
47
47
  node ./bin/deploy rename-package @underpostnet/underpost
48
48
  node ./bin/deploy set-repo underpostnet/pwa-microservices-template-ghpkg
49
49
 
@@ -28,7 +28,7 @@ jobs:
28
28
  run: |
29
29
  npm install -g underpost
30
30
  underpost config set GITHUB_TOKEN ${{ secrets.GIT_AUTH_TOKEN }}
31
- underpost install
31
+ npm install
32
32
 
33
33
  - name: Set git credentials
34
34
  run: |
@@ -43,7 +43,7 @@ jobs:
43
43
  - name: Build the site
44
44
  run: |
45
45
  npm install -g underpost
46
- underpost install
46
+ npm install
47
47
  node bin/deploy update-default-conf ghpkg
48
48
  env-cmd -f .env.production node bin/deploy build-full-client github-pages underpostnet.github.io /pwa-microservices-template-ghpkg
49
49
  # git lfs install
@@ -119,5 +119,8 @@
119
119
  "docwriter.hotkey.mac": "⌘ + .",
120
120
  "[dotenv]": {
121
121
  "editor.defaultFormatter": "foxundermoon.shell-format"
122
+ },
123
+ "[shellscript]": {
124
+ "editor.defaultFormatter": "foxundermoon.shell-format"
122
125
  }
123
126
  }
package/bin/build.js CHANGED
@@ -155,6 +155,15 @@ const { DefaultConf } = await import(`../conf.${confName}.js`);
155
155
  `${basePath}/.github/workflows/engine.${confName.split('dd-')[1]}.ci.yml`,
156
156
  );
157
157
 
158
+ switch (confName) {
159
+ case 'dd-cyberia':
160
+ fs.copyFileSync(`./bin/cyberia.js`, `${basePath}/bin/cyberia.js`);
161
+ break;
162
+
163
+ default:
164
+ break;
165
+ }
166
+
158
167
  const packageJson = JSON.parse(fs.readFileSync(`${basePath}/package.json`, 'utf8'));
159
168
  packageJson.name = repoName;
160
169
  fs.writeFileSync(
package/bin/index.js CHANGED
@@ -6,9 +6,6 @@ import Underpost from '../src/index.js';
6
6
  import { getUnderpostRootPath, loadConf } from '../src/server/conf.js';
7
7
  import fs from 'fs-extra';
8
8
  import { commitData } from '../src/client/components/core/CommonJs.js';
9
- import UnderpostScript from '../src/cli/script.js';
10
- import UnderpostDB from '../src/cli/db.js';
11
- import UnderpostCron from '../src/cli/cron.js';
12
9
 
13
10
  const underpostRootPath = getUnderpostRootPath();
14
11
  fs.existsSync(`${underpostRootPath}/.env`)
@@ -85,12 +82,14 @@ program
85
82
  .option('--reset', `Delete all clusters and prune all data and caches`)
86
83
  .option('--mariadb', 'Init with mariadb statefulset')
87
84
  .option('--mongodb', 'Init with mongodb statefulset')
85
+ .option('--mongodb4', 'Init with mongodb 4.4 service')
88
86
  .option('--valkey', 'Init with valkey service')
89
87
  .option('--contour', 'Init with project contour base HTTPProxy and envoy')
90
88
  .option('--cert-manager', 'Init with letsencrypt-prod ClusterIssuer')
91
89
  .option('--info', 'Get all kinds objects deployed')
92
90
  .option('--full', 'Init with all statefulsets and services available')
93
91
  .option('--ns-use <ns-name>', 'Switches current context to namespace')
92
+ .option('--dev', 'init with dev cluster')
94
93
  .option('--list-pods', 'Display list pods information')
95
94
  .action(Underpost.cluster.init)
96
95
  .description('Manage cluster, for default initialization base kind cluster');
@@ -104,7 +103,9 @@ program
104
103
  .option('--info-router', 'Display router structure')
105
104
  .option('--expose', 'Expose service match deploy-list')
106
105
  .option('--info-util', 'Display kubectl util management commands')
106
+ .option('--cert', 'Reset tls/ssl certificate secrets')
107
107
  .option('--build-manifest', 'Build kind yaml manifests: deployments, services, proxy and secrets')
108
+ .option('--version', 'Set custom version')
108
109
  .description('Manage deployment, for default deploy development pods')
109
110
  .action(Underpost.deploy.callback);
110
111
 
@@ -128,6 +129,7 @@ program
128
129
  .argument('<deploy-id>', 'Deploy configuration id')
129
130
  .argument('[env]', 'Optional environment, for default is development')
130
131
  .option('--run', 'Run custom entry point script')
132
+ .option('--build', 'Build custom image container scripts')
131
133
  .description('Dockerfile custom node build script')
132
134
  .action(Underpost.image.dockerfile.script);
133
135
 
@@ -138,6 +140,8 @@ program
138
140
  .argument('[path]', 'Absolute or relative directory, for default is current')
139
141
  .option('--image-archive', 'Only load tar image from ./images')
140
142
  .option('--podman-save', 'Save image from podman to ./images')
143
+ .option('--image-name <image-name>', 'Set custom image name')
144
+ .option('--image-version <image-version>', 'Set custom image version')
141
145
  .description('Build image from Dockerfile')
142
146
  .action(Underpost.image.dockerfile.build);
143
147
 
@@ -158,12 +162,19 @@ program
158
162
  .argument('<deploy-list>', 'Deploy id list, e.g. default-a,default-b')
159
163
  .option('--import', 'Import container backups from repositories')
160
164
  .option('--export', 'Export container backups to repositories')
165
+ .option('--pod-name <pod-name>', 'Optional pod context')
166
+ .option('--collection <collection>', 'Collection')
167
+ .option('--out-path <out-path>', 'Custom out path backup')
168
+ .option('--drop', 'Drop databases')
169
+ .option('--preserveUUID', 'Preserve Ids')
170
+ .option('--git', 'Upload to github')
171
+ .option('--ns <ns-name>', 'Optional name space context')
161
172
  .description('Manage databases')
162
- .action(UnderpostDB.API.callback);
173
+ .action(Underpost.db.callback);
163
174
 
164
175
  program
165
176
  .command('script')
166
- .argument('operator', `Options: ${Object.keys(UnderpostScript.API)}`)
177
+ .argument('operator', `Options: ${Object.keys(Underpost.script)}`)
167
178
  .argument('<script-name>', 'Script name')
168
179
  .argument('[script-value]', 'Literal command, or path')
169
180
  .option('--itc', 'Inside container execution context')
@@ -178,12 +189,25 @@ program
178
189
  program
179
190
  .command('cron')
180
191
  .argument('[deploy-list]', 'Deploy id list, e.g. default-a,default-b')
181
- .argument('[job-list]', `Deploy id list, e.g. ${Object.keys(UnderpostCron.JOB)}, for default all available jobs`)
192
+ .argument('[job-list]', `Deploy id list, e.g. ${Object.keys(Underpost.cron)}, for default all available jobs`)
182
193
  .option('--itc', 'Inside container execution context')
183
194
  .option('--init', 'Init cron jobs for cron job default deploy id')
195
+ .option('--git', 'Upload to github')
184
196
  .description('Cron jobs management')
185
197
  .action(Underpost.cron.callback);
186
198
 
199
+ program
200
+ .command('fs')
201
+ .argument('[path]', 'Absolute or relative directory')
202
+ .option('--rm', 'Remove file')
203
+ .option('--git', 'Current git changes')
204
+ .option('--recursive', 'Upload files recursively')
205
+ .option('--deploy-id <deploy-id>', 'Deploy configuration id')
206
+ .option('--pull', 'Download file')
207
+ .option('--force', 'Force action')
208
+ .description('File storage management, for default upload file')
209
+ .action(Underpost.fs.callback);
210
+
187
211
  program
188
212
  .command('test')
189
213
  .argument('[deploy-list]', 'Deploy id list, e.g. default-a,default-b')
@@ -193,6 +217,7 @@ program
193
217
  .option('--logs', 'Display container logs')
194
218
  .option('--pod-name <pod-name>')
195
219
  .option('--pod-status <pod-status>')
220
+ .option('--kind-type <kind-type>')
196
221
  .action(Underpost.test.callback);
197
222
 
198
223
  program.parse();
package/bin/vs.js CHANGED
@@ -20,6 +20,7 @@ switch (process.argv[2]) {
20
20
  logger.info('Open new vs windows', 'Ctrl Shift N');
21
21
  logger.info('Close current vs windows', 'Ctrl Shift W');
22
22
  logger.info('Preview md', 'Ctrl shift V');
23
+ logger.info('Open git changes', 'Ctrl G + G');
23
24
  logger.warn('Terminal shortcut configure with command pallette', 'Ctl shift T');
24
25
  break;
25
26
  }
@@ -58,7 +58,7 @@ services:
58
58
  cpus: '0.25'
59
59
  memory: 20M
60
60
  labels: # labels in Compose file instead of Dockerfile
61
- engine.version: '2.8.55'
61
+ engine.version: '2.8.61'
62
62
  networks:
63
63
  - load-balancer
64
64
 
@@ -0,0 +1,12 @@
1
+ kind: Cluster
2
+ apiVersion: kind.x-k8s.io/v1alpha4
3
+ nodes:
4
+ - role: control-plane
5
+ - role: worker
6
+ # extraPortMappings:
7
+ # - containerPort: 80
8
+ # hostPort: 80
9
+ # listenAddress: '0.0.0.0'
10
+ # - containerPort: 443
11
+ # hostPort: 443
12
+ # listenAddress: '0.0.0.0'
@@ -7,5 +7,5 @@ resources:
7
7
  - headless-service.yaml
8
8
  - statefulset.yaml
9
9
  - backup-pv-pvc.yaml
10
- - backup-cronjob.yaml
11
- - backup-access.yaml
10
+ # - backup-cronjob.yaml
11
+ # - backup-access.yaml
@@ -29,10 +29,10 @@ spec:
29
29
  - name: mongo-persistent-storage
30
30
  mountPath: /data/db
31
31
 
32
- resources:
33
- requests:
34
- memory: '500Mi'
35
- cpu: '500m'
32
+ # resources:
33
+ # requests:
34
+ # memory: '500Mi'
35
+ # cpu: '500m'
36
36
  volumes:
37
37
  - name: mongo-persistent-storage
38
38
  persistentVolumeClaim:
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "type": "module",
3
3
  "main": "src/index.js",
4
4
  "name": "underpost",
5
- "version": "2.8.55",
5
+ "version": "2.8.61",
6
6
  "description": "pwa api rest template",
7
7
  "scripts": {
8
8
  "start": "env-cmd -f .env.production node --max-old-space-size=8192 src/server",
@@ -57,9 +57,11 @@
57
57
  "ag-grid-community": "31.0.0",
58
58
  "axios": "^1.5.1",
59
59
  "chai": "^5.1.0",
60
+ "clean-jsdoc-theme": "^4.3.0",
60
61
  "cli-progress": "^3.12.0",
61
62
  "cli-spinners": "^3.0.0",
62
63
  "clipboardy": "^4.0.0",
64
+ "cloudinary": "^2.5.1",
63
65
  "color": "^4.2.3",
64
66
  "colors": "^1.4.0",
65
67
  "commander": "^12.1.0",
@@ -67,6 +69,7 @@
67
69
  "cors": "^2.8.5",
68
70
  "d3": "^7.9.0",
69
71
  "dotenv": "^16.3.1",
72
+ "easy-json-schema": "^0.0.2-beta",
70
73
  "easymde": "^2.18.0",
71
74
  "env-cmd": "^10.1.0",
72
75
  "express": "^4.18.2",
@@ -87,6 +90,7 @@
87
90
  "log-update": "^6.0.0",
88
91
  "mariadb": "^3.2.2",
89
92
  "marked": "^12.0.2",
93
+ "mocha": "^10.8.2",
90
94
  "mongoose": "^8.9.5",
91
95
  "morgan": "^1.10.0",
92
96
  "nodemailer": "^6.9.9",
@@ -95,6 +99,7 @@
95
99
  "peer": "^1.0.2",
96
100
  "peerjs": "^1.5.2",
97
101
  "pixi.js": "7.4.2",
102
+ "plantuml": "^0.0.2",
98
103
  "prom-client": "^15.1.2",
99
104
  "public-ip": "^6.0.1",
100
105
  "read": "^2.1.0",
@@ -106,17 +111,13 @@
106
111
  "socket.io": "^4.8.0",
107
112
  "sortablejs": "^1.15.0",
108
113
  "split-file": "^2.3.0",
114
+ "swagger-autogen": "^2.23.7",
109
115
  "swagger-ui-express": "^5.0.0",
110
116
  "systeminformation": "^5.23.7",
111
117
  "uglify-js": "^3.17.4",
112
118
  "validator": "^13.11.0",
113
119
  "vanilla-jsoneditor": "^2.3.2",
114
- "winston": "^3.11.0",
115
- "clean-jsdoc-theme": "^4.3.0",
116
- "easy-json-schema": "^0.0.2-beta",
117
- "mocha": "^10.8.2",
118
- "plantuml": "^0.0.2",
119
- "swagger-autogen": "^2.23.7"
120
+ "winston": "^3.11.0"
120
121
  },
121
122
  "devDependencies": {
122
123
  "clean-jsdoc-theme": "^4.3.0",
@@ -12,7 +12,8 @@ class UnderpostCluster {
12
12
  async init(
13
13
  podName,
14
14
  options = {
15
- valkey: false,
15
+ mongodb: false,
16
+ mongodb4: false,
16
17
  mariadb: false,
17
18
  valkey: false,
18
19
  full: false,
@@ -20,19 +21,20 @@ class UnderpostCluster {
20
21
  certManager: false,
21
22
  listPods: false,
22
23
  reset: false,
24
+ dev: false,
23
25
  nsUse: '',
24
26
  },
25
27
  ) {
26
28
  const npmRoot = getNpmRootPath();
27
- const underpostRoot = `${npmRoot}/underpost`;
29
+ const underpostRoot = options?.dev === true ? '.' : `${npmRoot}/underpost`;
28
30
  if (options.reset === true) return await UnderpostCluster.API.reset();
29
31
  if (options.listPods === true) return console.table(UnderpostDeploy.API.get(podName ?? undefined));
30
32
 
31
- if (options.nsUse) {
33
+ if (options.nsUse && typeof options.nsUse === 'string') {
32
34
  shellExec(`kubectl config set-context --current --namespace=${options.nsUse}`);
33
35
  return;
34
36
  }
35
- if (options.info) {
37
+ if (options.info === true) {
36
38
  shellExec(`kubectl config get-contexts`); // config env persisente for manage multiple clusters
37
39
  shellExec(`kubectl config get-clusters`);
38
40
  shellExec(`kubectl get nodes -o wide`); // set of nodes of a cluster
@@ -63,12 +65,8 @@ class UnderpostCluster {
63
65
  shellExec(`kubectl get crd --all-namespaces -o wide`);
64
66
  return;
65
67
  }
66
- const testClusterInit = shellExec(`kubectl get pods --all-namespaces -o wide`, {
67
- disableLog: true,
68
- silent: true,
69
- stdout: true,
70
- });
71
- if (!(testClusterInit.match('kube-system') && testClusterInit.match('kube-proxy'))) {
68
+
69
+ if (!UnderpostDeploy.API.get('kube-apiserver-kind-control-plane')[0]) {
72
70
  shellExec(`containerd config default > /etc/containerd/config.toml`);
73
71
  shellExec(`sed -i -e "s/SystemdCgroup = false/SystemdCgroup = true/g" /etc/containerd/config.toml`);
74
72
  // shellExec(`cp /etc/kubernetes/admin.conf ~/.kube/config`);
@@ -76,15 +74,19 @@ class UnderpostCluster {
76
74
  shellExec(`sudo service docker restart`);
77
75
  shellExec(`sudo systemctl enable --now containerd.service`);
78
76
  shellExec(`sudo systemctl restart containerd`);
79
- shellExec(`cd ${underpostRoot}/manifests && kind create cluster --config kind-config.yaml`);
77
+ shellExec(
78
+ `cd ${underpostRoot}/manifests && kind create cluster --config kind-config${
79
+ options?.dev === true ? '-dev' : ''
80
+ }.yaml`,
81
+ );
80
82
  shellExec(`sudo chown $(id -u):$(id -g) $HOME/.kube/config**`);
81
83
  } else logger.warn('Cluster already initialized');
82
84
 
83
- if (options.full || options.valkey) {
85
+ if (options.full === true || options.valkey === true) {
84
86
  shellExec(`kubectl delete statefulset service-valkey`);
85
87
  shellExec(`kubectl apply -k ${underpostRoot}/manifests/valkey`);
86
88
  }
87
- if (options.full || options.mariadb) {
89
+ if (options.full === true || options.mariadb === true) {
88
90
  shellExec(
89
91
  `sudo kubectl create secret generic mariadb-secret --from-file=username=/home/dd/engine/engine-private/mariadb-username --from-file=password=/home/dd/engine/engine-private/mariadb-password`,
90
92
  );
@@ -94,7 +96,29 @@ class UnderpostCluster {
94
96
  shellExec(`kubectl delete statefulset mariadb-statefulset`);
95
97
  shellExec(`kubectl apply -k ${underpostRoot}/manifests/mariadb`);
96
98
  }
97
- if (options.full || options.mongodb) {
99
+ if (options.mongodb4 === true) {
100
+ shellExec(`kubectl apply -k ${underpostRoot}/manifests/mongodb-4.4`);
101
+
102
+ const deploymentName = 'mongodb-deployment';
103
+
104
+ const successInstance = await UnderpostTest.API.statusMonitor(deploymentName);
105
+
106
+ if (successInstance) {
107
+ const mongoConfig = {
108
+ _id: 'rs0',
109
+ members: [{ _id: 0, host: '127.0.0.1:27017' }],
110
+ };
111
+
112
+ const [pod] = UnderpostDeploy.API.get(deploymentName);
113
+
114
+ shellExec(
115
+ `sudo kubectl exec -i ${pod.NAME} -- mongo --quiet \
116
+ --eval 'rs.initiate(${JSON.stringify(mongoConfig)})'`,
117
+ );
118
+ }
119
+
120
+ // await UnderpostTest.API.statusMonitor('mongodb-1');
121
+ } else if (options.full === true || options.mongodb === true) {
98
122
  shellExec(
99
123
  `sudo kubectl create secret generic mongodb-keyfile --from-file=/home/dd/engine/engine-private/mongodb-keyfile`,
100
124
  );
@@ -104,28 +128,30 @@ class UnderpostCluster {
104
128
  shellExec(`kubectl delete statefulset mongodb`);
105
129
  shellExec(`kubectl apply -k ${underpostRoot}/manifests/mongodb`);
106
130
 
107
- await UnderpostTest.API.podStatusMonitor('mongodb-1');
131
+ const successInstance = await UnderpostTest.API.statusMonitor('mongodb-1');
108
132
 
109
- const mongoConfig = {
110
- _id: 'rs0',
111
- members: [
112
- { _id: 0, host: 'mongodb-0.mongodb-service:27017', priority: 1 },
113
- { _id: 1, host: 'mongodb-1.mongodb-service:27017', priority: 1 },
114
- ],
115
- };
133
+ if (successInstance) {
134
+ const mongoConfig = {
135
+ _id: 'rs0',
136
+ members: [
137
+ { _id: 0, host: 'mongodb-0.mongodb-service:27017', priority: 1 },
138
+ { _id: 1, host: 'mongodb-1.mongodb-service:27017', priority: 1 },
139
+ ],
140
+ };
116
141
 
117
- shellExec(
118
- `sudo kubectl exec -i mongodb-0 -- mongosh --quiet --json=relaxed \
119
- --eval 'use admin' \
120
- --eval 'rs.initiate(${JSON.stringify(mongoConfig)})' \
121
- --eval 'rs.status()'`,
122
- );
142
+ shellExec(
143
+ `sudo kubectl exec -i mongodb-0 -- mongosh --quiet --json=relaxed \
144
+ --eval 'use admin' \
145
+ --eval 'rs.initiate(${JSON.stringify(mongoConfig)})' \
146
+ --eval 'rs.status()'`,
147
+ );
148
+ }
123
149
  }
124
150
 
125
- if (options.full || options.contour)
151
+ if (options.full === true || options.contour === true)
126
152
  shellExec(`kubectl apply -f https://projectcontour.io/quickstart/contour.yaml`);
127
153
 
128
- if (options.full || options.certManager) {
154
+ if (options.full === true || options.certManager === true) {
129
155
  if (!UnderpostDeploy.API.get('cert-manager').find((p) => p.STATUS === 'Running')) {
130
156
  shellExec(`helm repo add jetstack https://charts.jetstack.io --force-update`);
131
157
  shellExec(
package/src/cli/cron.js CHANGED
@@ -46,7 +46,7 @@ class UnderpostCron {
46
46
  callback: async function (
47
47
  deployList = 'default',
48
48
  jobList = Object.keys(UnderpostCron.JOB),
49
- options = { itc: false, init: false },
49
+ options = { itc: false, init: false, git: false },
50
50
  ) {
51
51
  if (options.init === true) {
52
52
  await Underpost.test.setUpInfo();
package/src/cli/db.js CHANGED
@@ -2,14 +2,28 @@ import { mergeFile, splitFileFactory } from '../server/conf.js';
2
2
  import { loggerFactory } from '../server/logger.js';
3
3
  import { shellExec } from '../server/process.js';
4
4
  import fs from 'fs-extra';
5
+ import UnderpostDeploy from './deploy.js';
5
6
 
6
7
  const logger = loggerFactory(import.meta);
7
8
 
8
9
  class UnderpostDB {
9
10
  static API = {
10
- async callback(deployList = 'default', options = { import: false, export: false }) {
11
+ async callback(
12
+ deployList = 'default',
13
+ options = {
14
+ import: false,
15
+ export: false,
16
+ podName: false,
17
+ ns: false,
18
+ collection: '',
19
+ outPath: '',
20
+ drop: false,
21
+ preserveUUID: false,
22
+ git: false,
23
+ },
24
+ ) {
11
25
  const newBackupTimestamp = new Date().getTime();
12
- const nameSpace = 'default';
26
+ const nameSpace = options.ns && typeof options.ns === 'string' ? options.ns : 'default';
13
27
  for (const _deployId of deployList.split(',')) {
14
28
  const deployId = _deployId.trim();
15
29
  if (!deployId) continue;
@@ -43,10 +57,12 @@ class UnderpostDB {
43
57
  logger.info('', { hostFolder, provider, dbName });
44
58
 
45
59
  const backUpPath = `../${repoName}/${hostFolder}`;
60
+ if (!fs.existsSync(backUpPath)) fs.mkdirSync(backUpPath, { recursive: true });
61
+ shellExec(`cd ${backUpPath} && find . -type d -empty -delete`); // delete empty folders
46
62
  const times = await fs.readdir(backUpPath);
47
- const currentBackupTimestamp = Math.max(...times.map((t) => parseInt(t)));
63
+ const currentBackupTimestamp = Math.max(...times.map((t) => parseInt(t)).filter((t) => !isNaN(t)));
48
64
  dbs[provider][dbName].currentBackupTimestamp = currentBackupTimestamp;
49
- const removeBackupTimestamp = Math.min(...times.map((t) => parseInt(t)));
65
+ const removeBackupTimestamp = Math.min(...times.map((t) => parseInt(t)).filter((t) => !isNaN(t)));
50
66
 
51
67
  const sqlContainerPath = `/home/${dbName}.sql`;
52
68
  const _fromPartsParts = `../${repoName}/${hostFolder}/${currentBackupTimestamp}/${dbName}-parths.json`;
@@ -68,57 +84,105 @@ class UnderpostDB {
68
84
  }
69
85
 
70
86
  if (options.export === true && times.length >= 5) {
87
+ logger.info('remove', `../${repoName}/${hostFolder}/${removeBackupTimestamp}`);
71
88
  fs.removeSync(`../${repoName}/${hostFolder}/${removeBackupTimestamp}`);
89
+ logger.info('create', `../${repoName}/${hostFolder}/${newBackupTimestamp}`);
72
90
  fs.mkdirSync(`../${repoName}/${hostFolder}/${newBackupTimestamp}`, { recursive: true });
73
91
  }
74
92
 
75
93
  switch (provider) {
76
94
  case 'mariadb': {
77
- const podName = `mariadb-statefulset-0`;
95
+ const podNames =
96
+ options.podName && typeof options.podName === 'string'
97
+ ? options.podName.split(',')
98
+ : UnderpostDeploy.API.get('mariadb'); // `mariadb-statefulset-0`;
78
99
  const serviceName = 'mariadb';
79
- if (options.import === true) {
80
- shellExec(`sudo kubectl cp ${_toSqlPath} ${nameSpace}/${podName}:/${dbName}.sql`);
81
- const cmd = `mariadb -u ${user} -p${password} ${dbName} < /${dbName}.sql`;
82
- shellExec(
83
- `kubectl exec -i ${podName} -- ${serviceName} -p${password} -e 'CREATE DATABASE ${dbName};'`,
84
- );
85
- shellExec(`sudo kubectl exec -i ${podName} -- sh -c "${cmd}"`);
86
- }
87
- if (options.export === true) {
88
- const cmd = `mariadb-dump --user=${user} --password=${password} --lock-tables ${dbName} > ${sqlContainerPath}`;
89
- shellExec(`sudo kubectl exec -i ${podName} -- sh -c "${cmd}"`);
90
- shellExec(`sudo kubectl cp ${nameSpace}/${podName}:${sqlContainerPath} ${_toNewSqlPath}`);
91
- await splitFileFactory(dbName, _toNewSqlPath);
100
+ for (const podNameData of [podNames[0]]) {
101
+ const podName = podNameData.NAME;
102
+ if (options.import === true) {
103
+ shellExec(`sudo kubectl exec -i ${podName} -- sh -c "rm -rf /${dbName}.sql"`);
104
+ shellExec(`sudo kubectl cp ${_toSqlPath} ${nameSpace}/${podName}:/${dbName}.sql`);
105
+ const cmd = `mariadb -u ${user} -p${password} ${dbName} < /${dbName}.sql`;
106
+ shellExec(
107
+ `kubectl exec -i ${podName} -- ${serviceName} -p${password} -e 'CREATE DATABASE ${dbName};'`,
108
+ );
109
+ shellExec(`sudo kubectl exec -i ${podName} -- sh -c "${cmd}"`);
110
+ }
111
+ if (options.export === true) {
112
+ shellExec(`sudo kubectl exec -i ${podName} -- sh -c "rm -rf ${sqlContainerPath}"`);
113
+ const cmd = `mariadb-dump --user=${user} --password=${password} --lock-tables ${dbName} > ${sqlContainerPath}`;
114
+ shellExec(`sudo kubectl exec -i ${podName} -- sh -c "${cmd}"`);
115
+ shellExec(
116
+ `sudo kubectl cp ${nameSpace}/${podName}:${sqlContainerPath} ${
117
+ options.outPath ? options.outPath : _toNewSqlPath
118
+ }`,
119
+ );
120
+ await splitFileFactory(dbName, options.outPath ? options.outPath : _toNewSqlPath);
121
+ }
92
122
  }
93
123
  break;
94
124
  }
95
125
 
96
126
  case 'mongoose': {
97
127
  if (options.import === true) {
98
- const podName = `mongodb-0`;
99
- shellExec(`sudo kubectl cp ${_toBsonPath} ${nameSpace}/${podName}:/${dbName}`);
100
- const cmd = `mongorestore -d ${dbName} /${dbName}`;
101
- shellExec(`sudo kubectl exec -i ${podName} -- sh -c "${cmd}"`);
128
+ const podNames =
129
+ options.podName && typeof options.podName === 'string'
130
+ ? options.podName.split(',')
131
+ : UnderpostDeploy.API.get('mongo');
132
+ // `mongodb-0`;
133
+ for (const podNameData of [podNames[0]]) {
134
+ const podName = podNameData.NAME;
135
+ shellExec(`sudo kubectl exec -i ${podName} -- sh -c "rm -rf /${dbName}"`);
136
+ shellExec(
137
+ `sudo kubectl cp ${
138
+ options.outPath ? options.outPath : _toBsonPath
139
+ } ${nameSpace}/${podName}:/${dbName}`,
140
+ );
141
+ const cmd = `mongorestore -d ${dbName} /${dbName}${options.drop ? ' --drop' : ''}${
142
+ options.preserveUUID ? ' --preserveUUID' : ''
143
+ }`;
144
+ shellExec(`sudo kubectl exec -i ${podName} -- sh -c "${cmd}"`);
145
+ }
102
146
  }
103
147
  if (options.export === true) {
104
- const podName = `backup-access`;
105
- const containerBaseBackupPath = '/backup';
106
- let timeFolder = shellExec(
107
- `sudo kubectl exec -i ${podName} -- sh -c "cd ${containerBaseBackupPath} && ls -a"`,
108
- {
109
- stdout: true,
110
- disableLog: false,
111
- silent: true,
112
- },
113
- ).split(`\n`);
114
- timeFolder = timeFolder[timeFolder.length - 2];
115
- if (timeFolder === '..') {
116
- logger.warn(`Cannot backup available`, { timeFolder });
117
- } else {
148
+ const podNames =
149
+ options.podName && typeof options.podName === 'string'
150
+ ? options.podName.split(',')
151
+ : UnderpostDeploy.API.get('mongo'); // `backup-access`;
152
+ for (const podNameData of [podNames[0]]) {
153
+ const podName = podNameData.NAME;
154
+ shellExec(`sudo kubectl exec -i ${podName} -- sh -c "rm -rf /${dbName}"`);
155
+ if (options.collections)
156
+ for (const collection of options.collections)
157
+ shellExec(
158
+ `sudo kubectl exec -i ${podName} -- sh -c "mongodump -d ${dbName} --collection ${collection} -o /${dbName}"`,
159
+ );
160
+ else shellExec(`sudo kubectl exec -i ${podName} -- sh -c "mongodump -d ${dbName} -o /${dbName}"`);
118
161
  shellExec(
119
- `sudo kubectl cp ${nameSpace}/${podName}:${containerBaseBackupPath}/${timeFolder}/${dbName} ${_toNewBsonPath}`,
162
+ `sudo kubectl cp ${nameSpace}/${podName}:/${dbName} ${
163
+ options.outPath ? options.outPath : _toNewBsonPath
164
+ }`,
120
165
  );
121
166
  }
167
+ if (false) {
168
+ const containerBaseBackupPath = '/backup';
169
+ let timeFolder = shellExec(
170
+ `sudo kubectl exec -i ${podName} -- sh -c "cd ${containerBaseBackupPath} && ls -a"`,
171
+ {
172
+ stdout: true,
173
+ disableLog: false,
174
+ silent: true,
175
+ },
176
+ ).split(`\n`);
177
+ timeFolder = timeFolder[timeFolder.length - 2];
178
+ if (timeFolder === '..') {
179
+ logger.warn(`Cannot backup available`, { timeFolder });
180
+ } else {
181
+ shellExec(
182
+ `sudo kubectl cp ${nameSpace}/${podName}:${containerBaseBackupPath}/${timeFolder}/${dbName} ${_toNewBsonPath}`,
183
+ );
184
+ }
185
+ }
122
186
  }
123
187
  break;
124
188
  }
@@ -129,7 +193,7 @@ class UnderpostDB {
129
193
  }
130
194
  }
131
195
  }
132
- if (options.export === true) {
196
+ if (options.export === true && options.git === true) {
133
197
  shellExec(`cd ../${repoName} && git add .`);
134
198
  shellExec(
135
199
  `underpost cmt ../${repoName} backup '' '${new Date(newBackupTimestamp).toLocaleDateString()} ${new Date(