@underpostnet/underpost 2.8.5 → 2.8.6
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/settings.json +4 -0
- package/CHANGELOG.md +24 -0
- package/bin/build.js +29 -4
- package/bin/deploy.js +70 -74
- package/bin/hwt.js +0 -10
- package/bin/index.js +54 -23
- package/bin/util.js +0 -7
- package/bin/vs.js +1 -0
- package/conf.js +0 -2
- package/docker-compose.yml +1 -1
- package/manifests/kind-config-dev.yaml +12 -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/package.json +9 -7
- package/src/cli/cluster.js +99 -51
- package/src/cli/cron.js +1 -1
- package/src/cli/db.js +102 -38
- package/src/cli/deploy.js +76 -35
- package/src/cli/fs.js +149 -0
- package/src/cli/image.js +50 -27
- package/src/cli/repository.js +21 -0
- package/src/cli/script.js +25 -1
- package/src/cli/test.js +39 -4
- package/src/client/components/core/CalendarCore.js +12 -1
- package/src/client/components/core/CommonJs.js +52 -1
- package/src/client/components/core/CssCore.js +2 -4
- package/src/client/components/core/Docs.js +1 -2
- package/src/client/components/core/Input.js +4 -2
- package/src/client/components/core/LoadingAnimation.js +8 -1
- package/src/client/components/core/Modal.js +30 -6
- package/src/client/components/core/Panel.js +8 -6
- package/src/client/components/core/PanelForm.js +23 -7
- package/src/client/services/core/core.service.js +15 -10
- package/src/client/ssr/Render.js +4 -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 +9 -1
- package/src/server/backup.js +3 -3
- package/src/server/client-build.js +32 -23
- package/src/server/client-formatted.js +2 -1
- package/src/server/conf.js +17 -15
- package/src/server/dns.js +39 -46
- package/src/server/downloader.js +0 -8
- package/src/server/runtime.js +16 -1
- 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-headless-service.yaml +0 -10
- 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
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
apiVersion: apps/v1
|
|
2
|
+
kind: Deployment
|
|
3
|
+
metadata:
|
|
4
|
+
name: mongodb-deployment
|
|
5
|
+
namespace: default
|
|
6
|
+
spec:
|
|
7
|
+
selector:
|
|
8
|
+
matchLabels:
|
|
9
|
+
app: mongodb
|
|
10
|
+
replicas: 1
|
|
11
|
+
template:
|
|
12
|
+
metadata:
|
|
13
|
+
labels:
|
|
14
|
+
app: mongodb
|
|
15
|
+
spec:
|
|
16
|
+
hostname: mongo
|
|
17
|
+
containers:
|
|
18
|
+
- name: mongodb
|
|
19
|
+
image: docker.io/library/mongo:4.4
|
|
20
|
+
command: ['mongod', '--replSet', 'rs0', '--bind_ip_all']
|
|
21
|
+
# -- bash
|
|
22
|
+
# mongo
|
|
23
|
+
# use admin
|
|
24
|
+
# rs.initiate()
|
|
25
|
+
ports:
|
|
26
|
+
- containerPort: 27017
|
|
27
|
+
|
|
28
|
+
volumeMounts:
|
|
29
|
+
- name: mongo-persistent-storage
|
|
30
|
+
mountPath: /data/db
|
|
31
|
+
|
|
32
|
+
# resources:
|
|
33
|
+
# requests:
|
|
34
|
+
# memory: '500Mi'
|
|
35
|
+
# cpu: '500m'
|
|
36
|
+
volumes:
|
|
37
|
+
- name: mongo-persistent-storage
|
|
38
|
+
persistentVolumeClaim:
|
|
39
|
+
claimName: mongodb-pvc
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
apiVersion: v1
|
|
43
|
+
kind: Service
|
|
44
|
+
metadata:
|
|
45
|
+
name: mongodb-service
|
|
46
|
+
namespace: default
|
|
47
|
+
spec:
|
|
48
|
+
clusterIP: None
|
|
49
|
+
selector:
|
|
50
|
+
app: mongodb
|
|
51
|
+
ports:
|
|
52
|
+
- protocol: TCP
|
|
53
|
+
port: 27017
|
|
54
|
+
# targetPort: 27017
|
|
55
|
+
# type: ClusterIP
|
|
56
|
+
|
|
57
|
+
# rs.initiate();
|
|
58
|
+
# use admin;
|
|
59
|
+
# rs.initiate({ _id: "rs0", members: [ { _id: 0, host: "127.0.0.1:27017" } ] })
|
|
60
|
+
# db.createUser({user: "your_user",pwd: "your_password", roles: [{role: "userAdminAnyDatabase", db: "admin" },{ role: "readWriteAnyDatabase", db: "admin" }]});
|
|
61
|
+
# cfg = rs.conf();
|
|
62
|
+
# cfg.members[0].host = "127.0.0.1:27027";
|
|
63
|
+
# rs.reconfig(cfg);
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"type": "module",
|
|
3
3
|
"main": "src/index.js",
|
|
4
4
|
"name": "@underpostnet/underpost",
|
|
5
|
-
"version": "2.8.
|
|
5
|
+
"version": "2.8.6",
|
|
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",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"pm2": "env-cmd -f .env.production pm2 start src/server.js --node-args=\"--max-old-space-size=8192\" --name engine",
|
|
11
11
|
"dev": "env-cmd -f .env.development node src/client.dev default",
|
|
12
12
|
"dev-img": "env-cmd -f .env.development node src/server",
|
|
13
|
+
"prod-img": "env-cmd -f .env.production node src/server",
|
|
13
14
|
"dev-api": "env-cmd -f .env.development nodemon --watch src --ignore src/client src/api",
|
|
14
15
|
"dev-client": "env-cmd -f .env.development node src/client.dev",
|
|
15
16
|
"proxy": "node src/proxy proxy",
|
|
@@ -56,9 +57,11 @@
|
|
|
56
57
|
"ag-grid-community": "31.0.0",
|
|
57
58
|
"axios": "^1.5.1",
|
|
58
59
|
"chai": "^5.1.0",
|
|
60
|
+
"clean-jsdoc-theme": "^4.3.0",
|
|
59
61
|
"cli-progress": "^3.12.0",
|
|
60
62
|
"cli-spinners": "^3.0.0",
|
|
61
63
|
"clipboardy": "^4.0.0",
|
|
64
|
+
"cloudinary": "^2.5.1",
|
|
62
65
|
"color": "^4.2.3",
|
|
63
66
|
"colors": "^1.4.0",
|
|
64
67
|
"commander": "^12.1.0",
|
|
@@ -66,6 +69,7 @@
|
|
|
66
69
|
"cors": "^2.8.5",
|
|
67
70
|
"d3": "^7.9.0",
|
|
68
71
|
"dotenv": "^16.3.1",
|
|
72
|
+
"easy-json-schema": "^0.0.2-beta",
|
|
69
73
|
"easymde": "^2.18.0",
|
|
70
74
|
"env-cmd": "^10.1.0",
|
|
71
75
|
"express": "^4.18.2",
|
|
@@ -86,6 +90,7 @@
|
|
|
86
90
|
"log-update": "^6.0.0",
|
|
87
91
|
"mariadb": "^3.2.2",
|
|
88
92
|
"marked": "^12.0.2",
|
|
93
|
+
"mocha": "^10.8.2",
|
|
89
94
|
"mongoose": "^8.9.5",
|
|
90
95
|
"morgan": "^1.10.0",
|
|
91
96
|
"nodemailer": "^6.9.9",
|
|
@@ -94,6 +99,7 @@
|
|
|
94
99
|
"peer": "^1.0.2",
|
|
95
100
|
"peerjs": "^1.5.2",
|
|
96
101
|
"pixi.js": "7.4.2",
|
|
102
|
+
"plantuml": "^0.0.2",
|
|
97
103
|
"prom-client": "^15.1.2",
|
|
98
104
|
"public-ip": "^6.0.1",
|
|
99
105
|
"read": "^2.1.0",
|
|
@@ -105,17 +111,13 @@
|
|
|
105
111
|
"socket.io": "^4.8.0",
|
|
106
112
|
"sortablejs": "^1.15.0",
|
|
107
113
|
"split-file": "^2.3.0",
|
|
114
|
+
"swagger-autogen": "^2.23.7",
|
|
108
115
|
"swagger-ui-express": "^5.0.0",
|
|
109
116
|
"systeminformation": "^5.23.7",
|
|
110
117
|
"uglify-js": "^3.17.4",
|
|
111
118
|
"validator": "^13.11.0",
|
|
112
119
|
"vanilla-jsoneditor": "^2.3.2",
|
|
113
|
-
"winston": "^3.11.0"
|
|
114
|
-
"clean-jsdoc-theme": "^4.3.0",
|
|
115
|
-
"easy-json-schema": "^0.0.2-beta",
|
|
116
|
-
"mocha": "^10.8.2",
|
|
117
|
-
"plantuml": "^0.0.2",
|
|
118
|
-
"swagger-autogen": "^2.23.7"
|
|
120
|
+
"winston": "^3.11.0"
|
|
119
121
|
},
|
|
120
122
|
"devDependencies": {
|
|
121
123
|
"clean-jsdoc-theme": "^4.3.0",
|
package/src/cli/cluster.js
CHANGED
|
@@ -1,18 +1,40 @@
|
|
|
1
1
|
import { timer } from '../client/components/core/CommonJs.js';
|
|
2
|
-
import { cliSpinner } from '../server/conf.js';
|
|
2
|
+
import { cliSpinner, getNpmRootPath } from '../server/conf.js';
|
|
3
3
|
import { loggerFactory } from '../server/logger.js';
|
|
4
4
|
import { shellExec } from '../server/process.js';
|
|
5
|
+
import UnderpostDeploy from './deploy.js';
|
|
6
|
+
import UnderpostTest from './test.js';
|
|
5
7
|
|
|
6
8
|
const logger = loggerFactory(import.meta);
|
|
7
9
|
|
|
8
10
|
class UnderpostCluster {
|
|
9
11
|
static API = {
|
|
10
|
-
async init(
|
|
11
|
-
|
|
12
|
+
async init(
|
|
13
|
+
podName,
|
|
14
|
+
options = {
|
|
15
|
+
mongodb: false,
|
|
16
|
+
mongodb4: false,
|
|
17
|
+
mariadb: false,
|
|
18
|
+
valkey: false,
|
|
19
|
+
full: false,
|
|
20
|
+
info: false,
|
|
21
|
+
certManager: false,
|
|
22
|
+
listPods: false,
|
|
23
|
+
reset: false,
|
|
24
|
+
dev: false,
|
|
25
|
+
nsUse: '',
|
|
26
|
+
},
|
|
27
|
+
) {
|
|
28
|
+
const npmRoot = getNpmRootPath();
|
|
29
|
+
const underpostRoot = options?.dev === true ? '.' : `${npmRoot}/underpost`;
|
|
30
|
+
if (options.reset === true) return await UnderpostCluster.API.reset();
|
|
31
|
+
if (options.listPods === true) return console.table(UnderpostDeploy.API.get(podName ?? undefined));
|
|
32
|
+
|
|
33
|
+
if (options.nsUse && typeof options.nsUse === 'string') {
|
|
12
34
|
shellExec(`kubectl config set-context --current --namespace=${options.nsUse}`);
|
|
13
35
|
return;
|
|
14
36
|
}
|
|
15
|
-
if (options.info) {
|
|
37
|
+
if (options.info === true) {
|
|
16
38
|
shellExec(`kubectl config get-contexts`); // config env persisente for manage multiple clusters
|
|
17
39
|
shellExec(`kubectl config get-clusters`);
|
|
18
40
|
shellExec(`kubectl get nodes -o wide`); // set of nodes of a cluster
|
|
@@ -40,28 +62,31 @@ class UnderpostCluster {
|
|
|
40
62
|
logger.info('----------------------------------------------------------------');
|
|
41
63
|
shellExec(`kubectl get secrets --all-namespaces -o wide`);
|
|
42
64
|
shellExec(`docker secret ls`);
|
|
65
|
+
shellExec(`kubectl get crd --all-namespaces -o wide`);
|
|
43
66
|
return;
|
|
44
67
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
silent: true,
|
|
48
|
-
stdout: true,
|
|
49
|
-
});
|
|
50
|
-
if (!(testClusterInit.match('kube-system') && testClusterInit.match('kube-proxy'))) {
|
|
68
|
+
|
|
69
|
+
if (!UnderpostDeploy.API.get('kube-apiserver-kind-control-plane')[0]) {
|
|
51
70
|
shellExec(`containerd config default > /etc/containerd/config.toml`);
|
|
52
71
|
shellExec(`sed -i -e "s/SystemdCgroup = false/SystemdCgroup = true/g" /etc/containerd/config.toml`);
|
|
53
72
|
// shellExec(`cp /etc/kubernetes/admin.conf ~/.kube/config`);
|
|
54
73
|
shellExec(`sudo systemctl restart kubelet`);
|
|
55
74
|
shellExec(`sudo service docker restart`);
|
|
56
|
-
shellExec(`
|
|
75
|
+
shellExec(`sudo systemctl enable --now containerd.service`);
|
|
76
|
+
shellExec(`sudo systemctl restart containerd`);
|
|
77
|
+
shellExec(
|
|
78
|
+
`cd ${underpostRoot}/manifests && kind create cluster --config kind-config${
|
|
79
|
+
options?.dev === true ? '-dev' : ''
|
|
80
|
+
}.yaml`,
|
|
81
|
+
);
|
|
57
82
|
shellExec(`sudo chown $(id -u):$(id -g) $HOME/.kube/config**`);
|
|
58
83
|
} else logger.warn('Cluster already initialized');
|
|
59
84
|
|
|
60
|
-
if (options.full || options.valkey) {
|
|
85
|
+
if (options.full === true || options.valkey === true) {
|
|
61
86
|
shellExec(`kubectl delete statefulset service-valkey`);
|
|
62
|
-
shellExec(`kubectl apply -k
|
|
87
|
+
shellExec(`kubectl apply -k ${underpostRoot}/manifests/valkey`);
|
|
63
88
|
}
|
|
64
|
-
if (options.full || options.mariadb) {
|
|
89
|
+
if (options.full === true || options.mariadb === true) {
|
|
65
90
|
shellExec(
|
|
66
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`,
|
|
67
92
|
);
|
|
@@ -69,9 +94,31 @@ class UnderpostCluster {
|
|
|
69
94
|
`sudo kubectl create secret generic github-secret --from-literal=GITHUB_TOKEN=${process.env.GITHUB_TOKEN}`,
|
|
70
95
|
);
|
|
71
96
|
shellExec(`kubectl delete statefulset mariadb-statefulset`);
|
|
72
|
-
shellExec(`kubectl apply -k
|
|
97
|
+
shellExec(`kubectl apply -k ${underpostRoot}/manifests/mariadb`);
|
|
73
98
|
}
|
|
74
|
-
if (options.
|
|
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) {
|
|
75
122
|
shellExec(
|
|
76
123
|
`sudo kubectl create secret generic mongodb-keyfile --from-file=/home/dd/engine/engine-private/mongodb-keyfile`,
|
|
77
124
|
);
|
|
@@ -79,46 +126,47 @@ class UnderpostCluster {
|
|
|
79
126
|
`sudo kubectl create secret generic mongodb-secret --from-file=username=/home/dd/engine/engine-private/mongodb-username --from-file=password=/home/dd/engine/engine-private/mongodb-password`,
|
|
80
127
|
);
|
|
81
128
|
shellExec(`kubectl delete statefulset mongodb`);
|
|
82
|
-
shellExec(`kubectl apply -k
|
|
83
|
-
|
|
84
|
-
await new Promise(async (resolve) => {
|
|
85
|
-
cliSpinner(3000, `[cluster.js] `, ` Load mongodb instance`, 'yellow', 'material');
|
|
86
|
-
await timer(3000);
|
|
87
|
-
|
|
88
|
-
const monitor = async () => {
|
|
89
|
-
cliSpinner(1000, `[cluster.js] `, ` Load mongodb instance`, 'yellow', 'material');
|
|
90
|
-
await timer(1000);
|
|
91
|
-
if (
|
|
92
|
-
shellExec(`kubectl get pods --all-namespaces -o wide`, {
|
|
93
|
-
silent: true,
|
|
94
|
-
stdout: true,
|
|
95
|
-
disableLog: true,
|
|
96
|
-
}).match(`mongodb-1 1/1 Running`)
|
|
97
|
-
)
|
|
98
|
-
return resolve();
|
|
99
|
-
return monitor();
|
|
100
|
-
};
|
|
101
|
-
await monitor();
|
|
102
|
-
});
|
|
129
|
+
shellExec(`kubectl apply -k ${underpostRoot}/manifests/mongodb`);
|
|
103
130
|
|
|
104
|
-
const
|
|
105
|
-
_id: 'rs0',
|
|
106
|
-
members: [
|
|
107
|
-
{ _id: 0, host: 'mongodb-0.mongodb-service:27017', priority: 1 },
|
|
108
|
-
{ _id: 1, host: 'mongodb-1.mongodb-service:27017', priority: 1 },
|
|
109
|
-
],
|
|
110
|
-
};
|
|
131
|
+
const successInstance = await UnderpostTest.API.statusMonitor('mongodb-1');
|
|
111
132
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
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
|
+
};
|
|
141
|
+
|
|
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
|
+
}
|
|
118
149
|
}
|
|
119
150
|
|
|
120
|
-
if (options.full || options.contour)
|
|
151
|
+
if (options.full === true || options.contour === true)
|
|
121
152
|
shellExec(`kubectl apply -f https://projectcontour.io/quickstart/contour.yaml`);
|
|
153
|
+
|
|
154
|
+
if (options.full === true || options.certManager === true) {
|
|
155
|
+
if (!UnderpostDeploy.API.get('cert-manager').find((p) => p.STATUS === 'Running')) {
|
|
156
|
+
shellExec(`helm repo add jetstack https://charts.jetstack.io --force-update`);
|
|
157
|
+
shellExec(
|
|
158
|
+
`helm install cert-manager jetstack/cert-manager \
|
|
159
|
+
--namespace cert-manager \
|
|
160
|
+
--create-namespace \
|
|
161
|
+
--version v1.17.0 \
|
|
162
|
+
--set crds.enabled=true`,
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const letsEncName = 'letsencrypt-prod';
|
|
167
|
+
shellExec(`sudo kubectl delete ClusterIssuer ${letsEncName}`);
|
|
168
|
+
shellExec(`sudo kubectl apply -f ${underpostRoot}/manifests/${letsEncName}.yaml`);
|
|
169
|
+
}
|
|
122
170
|
},
|
|
123
171
|
reset() {
|
|
124
172
|
shellExec(`kind get clusters | xargs -t -n1 kind delete cluster --name`);
|
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 = {
|
|
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(
|
|
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
|
|
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
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
`kubectl
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
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
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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}
|
|
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(
|