underpost 2.8.46 → 2.8.47

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/Dockerfile CHANGED
@@ -4,7 +4,7 @@ FROM debian:${BASE_DEBIAN}
4
4
 
5
5
  ENV DEBIAN_FRONTEND=noninteractive
6
6
 
7
- WORKDIR /code
7
+ WORKDIR /home/dd
8
8
 
9
9
  # Set root password to root, format is 'user:password'.
10
10
  RUN echo 'root:root' | chpasswd
@@ -39,10 +39,10 @@ RUN npm --version
39
39
 
40
40
  RUN npm install -g underpost
41
41
 
42
- VOLUME [ "/code/app/logs" ]
42
+ VOLUME [ "/home/dd/engine/logs" ]
43
43
 
44
44
  EXPOSE 22
45
45
 
46
46
  EXPOSE 4000-4004
47
47
 
48
- CMD [ "underpost", "new", "app" ]
48
+ CMD [ "underpost", "new", "engine" ]
package/bin/file.js CHANGED
@@ -1,7 +1,13 @@
1
1
  import fs from 'fs-extra';
2
2
 
3
3
  import { loggerFactory } from '../src/server/logger.js';
4
- import { cap, getCapVariableName, getDirname, newInstance } from '../src/client/components/core/CommonJs.js';
4
+ import {
5
+ cap,
6
+ getCapVariableName,
7
+ getDirname,
8
+ newInstance,
9
+ uniqueArray,
10
+ } from '../src/client/components/core/CommonJs.js';
5
11
  import { shellCd, shellExec } from '../src/server/process.js';
6
12
  import walk from 'ignore-walk';
7
13
  import { validateTemplatePath } from '../src/server/conf.js';
@@ -81,10 +87,12 @@ try {
81
87
  '.github/workflows/engine.core.ci.yml',
82
88
  '.github/workflows/engine.cyberia.ci.yml',
83
89
  './manifests/deployment/dd-lampp-development',
90
+ './manifests/deployment/dd-cyberia-development',
91
+ './manifests/deployment/dd-core-development',
84
92
  'bin/web3.js',
85
93
  'bin/cyberia.js',
86
94
  ]) {
87
- fs.removeSync('../pwa-microservices-template/' + deletePath);
95
+ if (fs.existsSync(deletePath)) fs.removeSync('../pwa-microservices-template/' + deletePath);
88
96
  }
89
97
  const originPackageJson = JSON.parse(fs.readFileSync('./package.json', 'utf8'));
90
98
  const templatePackageJson = JSON.parse(fs.readFileSync('../pwa-microservices-template/package.json', 'utf8'));
@@ -102,8 +110,8 @@ try {
102
110
  templatePackageJson.description = description;
103
111
  templatePackageJson.scripts.dev = dev;
104
112
  templatePackageJson.scripts.build = build;
105
- templatePackageJson.keywords = ['pwa', 'microservices', 'template', 'builder'].concat(
106
- templatePackageJson.keywords,
113
+ templatePackageJson.keywords = uniqueArray(
114
+ ['pwa', 'microservices', 'template', 'builder'].concat(templatePackageJson.keywords),
107
115
  );
108
116
  delete templatePackageJson.scripts['update-template'];
109
117
  fs.writeFileSync(
package/bin/index.js CHANGED
@@ -97,6 +97,14 @@ program
97
97
  })
98
98
  .description('Manage cluster, for default initialization base kind cluster');
99
99
 
100
+ program
101
+ .command('deploy')
102
+ .argument('<deploy-list>', 'Deploy id list, e.g. default-a, default-b')
103
+ .argument('[env]', 'Optional environment, for default is development')
104
+ .option('--remove', 'Delete deployments and services')
105
+ .description('Manage deployment, for default deploy development pods')
106
+ .action(Underpost.deploy.callback);
107
+
100
108
  program
101
109
  .command('secret')
102
110
  .argument('<platform>', `Options: ${Object.keys(Underpost.secret)}`)
@@ -142,11 +150,11 @@ program
142
150
 
143
151
  program
144
152
  .command('db')
145
- .option('--import <deploy-id-list>', 'Import databases to containers from deploy id list, e.g. default-a, default-b')
153
+ .argument('<deploy-list>', 'Deploy id list, e.g. default-a, default-b')
154
+ .option('--import', 'Import container backups from repositories')
155
+ .option('--export', 'Export container backups to repositories')
146
156
  .description('Manage databases')
147
- .action((...args) => {
148
- if (args && args[0].import) return UnderpostDB.API.import(...args);
149
- });
157
+ .action(UnderpostDB.API.callback);
150
158
 
151
159
  program
152
160
  .command('script')
@@ -158,6 +166,12 @@ program
158
166
  )
159
167
  .action((...args) => Underpost.script[args[0]](args[1], args[2]));
160
168
 
161
- program.command('test').description('Run tests').action(Underpost.test.run);
169
+ program
170
+ .command('test')
171
+ .argument('[deploy-list]', 'Deploy id list, e.g. default-a, default-b')
172
+ .description('Manage Test, for default run current underpost default test')
173
+ .option('--inside-container', 'Inside container execution context')
174
+ .option('--sh', 'Copy to clipboard, container entrypoint shell command')
175
+ .action(Underpost.test.callback);
162
176
 
163
177
  program.parse();
@@ -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.46'
61
+ engine.version: '2.8.47'
62
62
  networks:
63
63
  - load-balancer
64
64
 
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.46",
5
+ "version": "2.8.47",
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",
@@ -32,10 +32,6 @@
32
32
  "url": "git+https://github.com/underpostnet/pwa-microservices-template.git"
33
33
  },
34
34
  "keywords": [
35
- "pwa",
36
- "microservices",
37
- "template",
38
- "builder",
39
35
  "pwa",
40
36
  "microservices",
41
37
  "template",
@@ -43,7 +43,7 @@ class UnderpostCluster {
43
43
  return;
44
44
  }
45
45
  const testClusterInit = shellExec(`kubectl get pods --all-namespaces -o wide`, {
46
- disableLogging: true,
46
+ disableLog: true,
47
47
  silent: true,
48
48
  stdout: true,
49
49
  });
package/src/cli/db.js CHANGED
@@ -1,4 +1,4 @@
1
- import { mergeFile } from '../server/conf.js';
1
+ 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';
@@ -7,8 +7,10 @@ const logger = loggerFactory(import.meta);
7
7
 
8
8
  class UnderpostDB {
9
9
  static API = {
10
- async import(options = { import: 'default' }) {
11
- for (const _deployId of options.import.split(',')) {
10
+ async callback(deployList = 'default', options = { import: false, export: false }) {
11
+ const newBackupTimestamp = new Date().getTime();
12
+ const nameSpace = 'default';
13
+ for (const _deployId of deployList.split(',')) {
12
14
  const deployId = _deployId.trim();
13
15
  if (!deployId) continue;
14
16
  const dbs = {};
@@ -38,18 +40,22 @@ class UnderpostDB {
38
40
  for (const dbName of Object.keys(dbs[provider])) {
39
41
  const { hostFolder, user, password } = dbs[provider][dbName];
40
42
  if (hostFolder) {
41
- logger.info('import', { hostFolder, provider, dbName });
43
+ logger.info('', { hostFolder, provider, dbName });
42
44
 
43
45
  const backUpPath = `../${repoName}/${hostFolder}`;
44
46
  const times = await fs.readdir(backUpPath);
45
47
  const currentBackupTimestamp = Math.max(...times.map((t) => parseInt(t)));
46
48
  dbs[provider][dbName].currentBackupTimestamp = currentBackupTimestamp;
49
+ const removeBackupTimestamp = Math.min(...times.map((t) => parseInt(t)));
47
50
 
51
+ const sqlContainerPath = `/home/${dbName}.sql`;
48
52
  const _fromPartsParts = `../${repoName}/${hostFolder}/${currentBackupTimestamp}/${dbName}-parths.json`;
49
53
  const _toSqlPath = `../${repoName}/${hostFolder}/${currentBackupTimestamp}/${dbName}.sql`;
54
+ const _toNewSqlPath = `../${repoName}/${hostFolder}/${newBackupTimestamp}/${dbName}.sql`;
50
55
  const _toBsonPath = `../${repoName}/${hostFolder}/${currentBackupTimestamp}/${dbName}`;
56
+ const _toNewBsonPath = `../${repoName}/${hostFolder}/${newBackupTimestamp}/${dbName}`;
51
57
 
52
- if (fs.existsSync(_fromPartsParts) && !fs.existsSync(_toSqlPath)) {
58
+ if (options.import === true && fs.existsSync(_fromPartsParts) && !fs.existsSync(_toSqlPath)) {
53
59
  const names = JSON.parse(fs.readFileSync(_fromPartsParts, 'utf8')).map((_path) => {
54
60
  return `../${repoName}/${hostFolder}/${currentBackupTimestamp}/${_path.split('/').pop()}`;
55
61
  });
@@ -61,26 +67,59 @@ class UnderpostDB {
61
67
  await mergeFile(names, _toSqlPath);
62
68
  }
63
69
 
70
+ if (options.export === true && times.length >= 5) {
71
+ fs.removeSync(`../${repoName}/${hostFolder}/${removeBackupTimestamp}`);
72
+ fs.mkdirSync(`../${repoName}/${hostFolder}/${newBackupTimestamp}`, { recursive: true });
73
+ }
74
+
64
75
  switch (provider) {
65
76
  case 'mariadb': {
66
77
  const podName = `mariadb-statefulset-0`;
67
- const nameSpace = 'default';
68
78
  const serviceName = 'mariadb';
69
- shellExec(`sudo kubectl cp ${_toSqlPath} ${nameSpace}/${podName}:/${dbName}.sql`);
70
- const cmd = `mariadb -u ${user} -p${password} ${dbName} < /${dbName}.sql`;
71
- shellExec(
72
- `kubectl exec -i ${podName} -- ${serviceName} -p${password} -e 'CREATE DATABASE ${dbName};'`,
73
- );
74
- shellExec(`sudo kubectl exec -i ${podName} -- sh -c "${cmd}"`);
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);
92
+ }
75
93
  break;
76
94
  }
77
95
 
78
96
  case 'mongoose': {
79
- const podName = `mongodb-0`;
80
- const nameSpace = 'default';
81
- shellExec(`sudo kubectl cp ${_toBsonPath} ${nameSpace}/${podName}:/${dbName}`);
82
- const cmd = `mongorestore -d ${dbName} /${dbName}`;
83
- shellExec(`sudo kubectl exec -i ${podName} -- sh -c "${cmd}"`);
97
+ 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}"`);
102
+ }
103
+ 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 {
118
+ shellExec(
119
+ `sudo kubectl cp ${nameSpace}/${podName}:${containerBaseBackupPath}/${timeFolder}/${dbName} ${_toNewBsonPath}`,
120
+ );
121
+ }
122
+ }
84
123
  break;
85
124
  }
86
125
 
@@ -90,6 +129,17 @@ class UnderpostDB {
90
129
  }
91
130
  }
92
131
  }
132
+ if (options.export === true) {
133
+ shellExec(`cd ../${repoName} && git add .`);
134
+ shellExec(
135
+ `underpost cmt ../${repoName} backup '' '${new Date(newBackupTimestamp).toLocaleDateString()} ${new Date(
136
+ newBackupTimestamp,
137
+ ).toLocaleTimeString()}'`,
138
+ );
139
+ shellExec(`cd ../${repoName} && underpost push . ${process.env.GITHUB_USERNAME}/${repoName}`, {
140
+ disableLog: true,
141
+ });
142
+ }
93
143
  }
94
144
  },
95
145
  };
@@ -0,0 +1,95 @@
1
+ import { loggerFactory } from '../server/logger.js';
2
+ import { shellExec } from '../server/process.js';
3
+ import fs from 'fs-extra';
4
+
5
+ const logger = loggerFactory(import.meta);
6
+
7
+ class UnderpostDeploy {
8
+ static API = {
9
+ callback: (deployList = 'default', env = 'development', options = { remove: false }) => {
10
+ for (const _deployId of deployList.split(',')) {
11
+ const deployId = _deployId.trim();
12
+ if (!deployId) continue;
13
+
14
+ shellExec(`sudo kubectl delete svc ${deployId}-${env}-service`);
15
+ shellExec(`sudo kubectl delete deployment ${deployId}-${env}`);
16
+
17
+ const etcHost = (
18
+ concat,
19
+ ) => `127.0.0.1 ${concat} localhost localhost.localdomain localhost4 localhost4.localdomain4
20
+ ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6`;
21
+ let concatHots = '';
22
+
23
+ const confServer = JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8'));
24
+ for (const host of Object.keys(confServer)) {
25
+ shellExec(`sudo kubectl delete HTTPProxy ${host}`);
26
+ if (!options.remove === true && env === 'development') concatHots += ` ${host}`;
27
+ }
28
+
29
+ if (!options.remove === true) {
30
+ shellExec(`sudo kubectl apply -f ./manifests/deployment/${deployId}-${env}/deployment.yaml`);
31
+ shellExec(`sudo kubectl apply -f ./manifests/deployment/${deployId}-${env}/proxy.yaml`);
32
+ }
33
+
34
+ let renderHosts;
35
+
36
+ switch (process.platform) {
37
+ case 'linux':
38
+ {
39
+ switch (env) {
40
+ case 'development':
41
+ renderHosts = etcHost(concatHots);
42
+ fs.writeFileSync(`/etc/hosts`, renderHosts, 'utf8');
43
+
44
+ break;
45
+
46
+ default:
47
+ break;
48
+ }
49
+ }
50
+ break;
51
+
52
+ default:
53
+ break;
54
+ }
55
+ logger.info(
56
+ `
57
+ ` + renderHosts,
58
+ );
59
+ }
60
+ },
61
+ getPods(deployId) {
62
+ const raw = shellExec(`sudo kubectl get pods --all-namespaces -o wide`, {
63
+ stdout: true,
64
+ disableLog: false,
65
+ silent: true,
66
+ });
67
+
68
+ const heads = raw
69
+ .split(`\n`)[0]
70
+ .split(' ')
71
+ .filter((_r) => _r.trim());
72
+
73
+ const pods = raw
74
+ .split(`\n`)
75
+ .filter((r) => (deployId ? r.match(deployId) : r.trim() && !r.match('NAME')))
76
+ .map((r) => r.split(' ').filter((_r) => _r.trim()));
77
+
78
+ const result = [];
79
+
80
+ for (const row of pods) {
81
+ const pod = {};
82
+ let index = -1;
83
+ for (const head of heads) {
84
+ index++;
85
+ pod[head] = row[index];
86
+ }
87
+ result.push(pod);
88
+ }
89
+
90
+ return result;
91
+ },
92
+ };
93
+ }
94
+
95
+ export default UnderpostDeploy;
package/src/cli/image.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import fs from 'fs-extra';
2
2
  import Underpost from '../index.js';
3
3
  import { shellExec } from '../server/process.js';
4
- import { MariaDB } from '../db/mariadb/MariaDB.js';
5
4
  import dotenv from 'dotenv';
6
5
  import { getNpmRootPath } from '../server/conf.js';
7
6
 
@@ -45,17 +44,6 @@ class UnderpostImage {
45
44
  case 'dd-lampp':
46
45
  {
47
46
  const lamppPublicPath = '/xampp/htdocs/online';
48
- if (process.argv.includes('test')) {
49
- const { MARIADB_HOST, MARIADB_USER, MARIADB_PASSWORD, DD_LAMPP_TEST_DB_0 } = process.env;
50
-
51
- await MariaDB.query({
52
- host: MARIADB_HOST,
53
- user: MARIADB_USER,
54
- password: MARIADB_PASSWORD,
55
- query: `SHOW TABLES FROM ${DD_LAMPP_TEST_DB_0}`,
56
- });
57
- process.exit(0);
58
- }
59
47
  shellExec(`sudo mkdir -p ${lamppPublicPath}`);
60
48
 
61
49
  {
@@ -54,6 +54,10 @@ class UnderpostRepository {
54
54
  empty: false,
55
55
  },
56
56
  ) {
57
+ if (commitType === 'reset') {
58
+ shellExec(`cd ${repoPath} && git reset --soft HEAD~${isNaN(parseInt(subModule)) ? 1 : parseInt(subModule)}`);
59
+ return;
60
+ }
57
61
  if (options.info) return logger.info('', commitData);
58
62
  const _message = `${commitType}${subModule ? `(${subModule})` : ''}${process.argv.includes('!') ? '!' : ''}: ${
59
63
  commitData[commitType].emoji
package/src/cli/test.js CHANGED
@@ -1,6 +1,8 @@
1
+ import { MariaDB } from '../db/mariadb/MariaDB.js';
1
2
  import { getNpmRootPath } from '../server/conf.js';
2
3
  import { actionInitLog, loggerFactory } from '../server/logger.js';
3
- import { shellExec } from '../server/process.js';
4
+ import { pbcopy, shellExec } from '../server/process.js';
5
+ import UnderpostDeploy from './deploy.js';
4
6
 
5
7
  const logger = loggerFactory(import.meta);
6
8
 
@@ -26,6 +28,52 @@ class UnderpostTest {
26
28
  actionInitLog();
27
29
  shellExec(`cd ${getNpmRootPath()}/underpost && npm run test`);
28
30
  },
31
+ async callback(deployList = '', options = { insideContainer: false, sh: false }) {
32
+ if (options.sh === true) {
33
+ const [pod] = UnderpostDeploy.API.getPods(deployList);
34
+ if (pod) return pbcopy(`sudo kubectl exec -it ${pod.NAME} -- sh`);
35
+ return logger.warn(`Couldn't find pods in deployment`, deployList);
36
+ }
37
+ if (deployList) {
38
+ for (const _deployId of deployList.split(',')) {
39
+ const deployId = _deployId.trim();
40
+ if (!deployId) continue;
41
+ if (options.insideContainer === true)
42
+ switch (deployId) {
43
+ case 'dd-lampp':
44
+ {
45
+ const { MARIADB_HOST, MARIADB_USER, MARIADB_PASSWORD, DD_LAMPP_TEST_DB_0 } = process.env;
46
+
47
+ await MariaDB.query({
48
+ host: MARIADB_HOST,
49
+ user: MARIADB_USER,
50
+ password: MARIADB_PASSWORD,
51
+ query: `SHOW TABLES FROM ${DD_LAMPP_TEST_DB_0}`,
52
+ });
53
+ }
54
+ break;
55
+
56
+ default:
57
+ {
58
+ shellExec('npm run test');
59
+ }
60
+
61
+ break;
62
+ }
63
+ else {
64
+ const pods = UnderpostDeploy.API.getPods(deployId);
65
+ if (pods.length > 0)
66
+ for (const deployData of pods) {
67
+ const { NAME } = deployData;
68
+ shellExec(
69
+ `sudo kubectl exec -i ${NAME} -- sh -c "cd /home/dd/engine && underpost test ${deployId} --inside-container"`,
70
+ );
71
+ }
72
+ else logger.warn(`Couldn't find pods in deployment`, { deployId });
73
+ }
74
+ }
75
+ } else return UnderpostTest.API.run();
76
+ },
29
77
  };
30
78
  }
31
79
 
package/src/index.js CHANGED
@@ -6,6 +6,7 @@
6
6
 
7
7
  import UnderpostCluster from './cli/cluster.js';
8
8
  import UnderpostDB from './cli/db.js';
9
+ import UnderpostDeploy from './cli/deploy.js';
9
10
  import UnderpostRootEnv from './cli/env.js';
10
11
  import UnderpostImage from './cli/image.js';
11
12
  import UnderpostRepository from './cli/repository.js';
@@ -25,7 +26,7 @@ class Underpost {
25
26
  * @type {String}
26
27
  * @memberof Underpost
27
28
  */
28
- static version = 'v2.8.46';
29
+ static version = 'v2.8.47';
29
30
  /**
30
31
  * Repository cli API
31
32
  * @static
@@ -82,6 +83,13 @@ class Underpost {
82
83
  * @memberof Underpost
83
84
  */
84
85
  static db = UnderpostDB.API;
86
+ /**
87
+ * Deployment cli API
88
+ * @static
89
+ * @type {UnderpostDeploy.API}
90
+ * @memberof Underpost
91
+ */
92
+ static deploy = UnderpostDeploy.API;
85
93
  }
86
94
 
87
95
  const up = Underpost;
@@ -120,7 +120,14 @@ const saveRuntimeCron = async () => {
120
120
 
121
121
  const listenServerFactory = (logic = async () => {}) => {
122
122
  return {
123
- listen: async (...args) => (logic ? await logic(...args) : undefined, args[1]()),
123
+ listen: async (...args) => (
124
+ setTimeout(() => {
125
+ const message = 'Listen server factory timeout';
126
+ logger.error(message);
127
+ throw new Error(message);
128
+ }, 80000000), // ~ 55 days
129
+ (logic ? await logic(...args) : undefined, args[1]())
130
+ ),
124
131
  };
125
132
  };
126
133