underpost 2.8.6 → 2.8.8
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/.vscode/extensions.json +36 -3
- package/.vscode/settings.json +2 -0
- package/CHANGELOG.md +24 -4
- package/Dockerfile +9 -10
- package/README.md +41 -2
- package/bin/build.js +2 -2
- package/bin/db.js +1 -0
- package/bin/deploy.js +1521 -130
- package/bin/file.js +8 -0
- package/bin/index.js +1 -218
- package/cli.md +530 -0
- package/conf.js +4 -0
- package/docker-compose.yml +1 -1
- package/jsdoc.json +1 -1
- package/manifests/deployment/adminer/deployment.yaml +32 -0
- package/manifests/deployment/adminer/kustomization.yaml +7 -0
- package/manifests/deployment/adminer/service.yaml +13 -0
- package/manifests/deployment/dd-template-development/deployment.yaml +167 -0
- package/manifests/deployment/dd-template-development/proxy.yaml +46 -0
- package/manifests/deployment/fastapi/backend-deployment.yml +120 -0
- package/manifests/deployment/fastapi/backend-service.yml +19 -0
- package/manifests/deployment/fastapi/frontend-deployment.yml +54 -0
- package/manifests/deployment/fastapi/frontend-service.yml +15 -0
- package/manifests/deployment/fastapi/initial_data.sh +56 -0
- package/manifests/deployment/kafka/deployment.yaml +69 -0
- package/manifests/deployment/spark/spark-pi-py.yaml +21 -0
- package/manifests/envoy-service-nodeport.yaml +23 -0
- package/manifests/kubeadm-calico-config.yaml +119 -0
- package/manifests/kubelet-config.yaml +65 -0
- package/manifests/lxd/lxd-admin-profile.yaml +17 -0
- package/manifests/lxd/lxd-preseed.yaml +30 -0
- package/manifests/lxd/underpost-setup.sh +163 -0
- package/manifests/maas/lxd-preseed.yaml +32 -0
- package/manifests/maas/maas-setup.sh +82 -0
- package/manifests/mariadb/statefulset.yaml +2 -1
- package/manifests/mariadb/storage-class.yaml +10 -0
- package/manifests/mongodb/kustomization.yaml +1 -1
- package/manifests/mongodb/statefulset.yaml +12 -11
- package/manifests/mongodb/storage-class.yaml +9 -0
- package/manifests/mongodb-4.4/service-deployment.yaml +3 -3
- package/manifests/mysql/kustomization.yaml +7 -0
- package/manifests/mysql/pv-pvc.yaml +27 -0
- package/manifests/mysql/statefulset.yaml +55 -0
- package/manifests/postgresql/configmap.yaml +9 -0
- package/manifests/postgresql/kustomization.yaml +10 -0
- package/manifests/postgresql/pv.yaml +15 -0
- package/manifests/postgresql/pvc.yaml +13 -0
- package/manifests/postgresql/service.yaml +10 -0
- package/manifests/postgresql/statefulset.yaml +37 -0
- package/manifests/valkey/service.yaml +3 -9
- package/manifests/valkey/statefulset.yaml +12 -13
- package/package.json +3 -9
- package/src/api/default/default.service.js +1 -1
- package/src/api/user/user.service.js +14 -11
- package/src/cli/baremetal.js +60 -0
- package/src/cli/cluster.js +551 -65
- package/src/cli/cron.js +39 -8
- package/src/cli/db.js +20 -10
- package/src/cli/deploy.js +288 -86
- package/src/cli/env.js +10 -4
- package/src/cli/fs.js +21 -9
- package/src/cli/image.js +116 -124
- package/src/cli/index.js +319 -0
- package/src/cli/lxd.js +395 -0
- package/src/cli/monitor.js +236 -0
- package/src/cli/repository.js +14 -8
- package/src/client/components/core/Account.js +28 -24
- package/src/client/components/core/Blockchain.js +1 -1
- package/src/client/components/core/CalendarCore.js +14 -84
- package/src/client/components/core/CommonJs.js +2 -1
- package/src/client/components/core/Css.js +0 -1
- package/src/client/components/core/CssCore.js +10 -2
- package/src/client/components/core/Docs.js +1 -1
- package/src/client/components/core/EventsUI.js +3 -3
- package/src/client/components/core/FileExplorer.js +86 -78
- package/src/client/components/core/JoyStick.js +2 -2
- package/src/client/components/core/LoadingAnimation.js +1 -17
- package/src/client/components/core/LogIn.js +3 -3
- package/src/client/components/core/LogOut.js +1 -1
- package/src/client/components/core/Modal.js +14 -8
- package/src/client/components/core/Panel.js +19 -61
- package/src/client/components/core/PanelForm.js +13 -22
- package/src/client/components/core/Recover.js +3 -3
- package/src/client/components/core/RichText.js +1 -11
- package/src/client/components/core/Router.js +3 -1
- package/src/client/components/core/SignUp.js +2 -2
- package/src/client/components/default/RoutesDefault.js +3 -2
- package/src/client/services/default/default.management.js +45 -38
- package/src/client/ssr/Render.js +2 -0
- package/src/index.js +34 -2
- package/src/mailer/MailerProvider.js +3 -0
- package/src/runtime/lampp/Dockerfile +65 -0
- package/src/server/client-build.js +13 -0
- package/src/server/conf.js +151 -1
- package/src/server/dns.js +56 -18
- package/src/server/json-schema.js +77 -0
- package/src/server/logger.js +3 -3
- package/src/server/network.js +7 -122
- package/src/server/peer.js +2 -2
- package/src/server/proxy.js +4 -4
- package/src/server/runtime.js +24 -11
- package/src/server/start.js +122 -0
- package/src/server/valkey.js +27 -13
package/src/index.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* @namespace Underpost
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import UnderpostBaremetal from './cli/baremetal.js';
|
|
7
8
|
import UnderpostCluster from './cli/cluster.js';
|
|
8
9
|
import UnderpostCron from './cli/cron.js';
|
|
9
10
|
import UnderpostDB from './cli/db.js';
|
|
@@ -11,10 +12,13 @@ import UnderpostDeploy from './cli/deploy.js';
|
|
|
11
12
|
import UnderpostRootEnv from './cli/env.js';
|
|
12
13
|
import UnderpostFileStorage from './cli/fs.js';
|
|
13
14
|
import UnderpostImage from './cli/image.js';
|
|
15
|
+
import UnderpostLxd from './cli/lxd.js';
|
|
16
|
+
import UnderpostMonitor from './cli/monitor.js';
|
|
14
17
|
import UnderpostRepository from './cli/repository.js';
|
|
15
18
|
import UnderpostScript from './cli/script.js';
|
|
16
19
|
import UnderpostSecret from './cli/secrets.js';
|
|
17
20
|
import UnderpostTest from './cli/test.js';
|
|
21
|
+
import UnderpostStartUp from './server/start.js';
|
|
18
22
|
|
|
19
23
|
/**
|
|
20
24
|
* Underpost main module methods
|
|
@@ -28,7 +32,7 @@ class Underpost {
|
|
|
28
32
|
* @type {String}
|
|
29
33
|
* @memberof Underpost
|
|
30
34
|
*/
|
|
31
|
-
static version = 'v2.8.
|
|
35
|
+
static version = 'v2.8.8';
|
|
32
36
|
/**
|
|
33
37
|
* Repository cli API
|
|
34
38
|
* @static
|
|
@@ -50,6 +54,13 @@ class Underpost {
|
|
|
50
54
|
* @memberof Underpost
|
|
51
55
|
*/
|
|
52
56
|
static test = UnderpostTest.API;
|
|
57
|
+
/**
|
|
58
|
+
* Underpost Start Up cli API
|
|
59
|
+
* @static
|
|
60
|
+
* @type {UnderpostStartUp.API}
|
|
61
|
+
* @memberof Underpost
|
|
62
|
+
*/
|
|
63
|
+
static start = UnderpostStartUp.API;
|
|
53
64
|
/**
|
|
54
65
|
* Cluster cli API
|
|
55
66
|
* @static
|
|
@@ -103,9 +114,30 @@ class Underpost {
|
|
|
103
114
|
* File Storage cli API
|
|
104
115
|
* @static
|
|
105
116
|
* @type {UnderpostFileStorage.API}
|
|
106
|
-
* @memberof
|
|
117
|
+
* @memberof Underpost
|
|
107
118
|
*/
|
|
108
119
|
static fs = UnderpostFileStorage.API;
|
|
120
|
+
/**
|
|
121
|
+
* Monitor cli API
|
|
122
|
+
* @static
|
|
123
|
+
* @type {UnderpostMonitor.API}
|
|
124
|
+
* @memberof Underpost
|
|
125
|
+
*/
|
|
126
|
+
static monitor = UnderpostMonitor.API;
|
|
127
|
+
/**
|
|
128
|
+
* LXD cli API
|
|
129
|
+
* @static
|
|
130
|
+
* @type {UnderpostLxd.API}
|
|
131
|
+
* @memberof Underpost
|
|
132
|
+
*/
|
|
133
|
+
static lxd = UnderpostLxd.API;
|
|
134
|
+
/**
|
|
135
|
+
* Baremetal cli API
|
|
136
|
+
* @static
|
|
137
|
+
* @type {UnderpostBaremetal.API}
|
|
138
|
+
* @memberof Underpost
|
|
139
|
+
*/
|
|
140
|
+
static baremetal = UnderpostBaremetal.API;
|
|
109
141
|
}
|
|
110
142
|
|
|
111
143
|
const up = Underpost;
|
|
@@ -32,6 +32,9 @@ const MailerProvider = {
|
|
|
32
32
|
},
|
|
33
33
|
) {
|
|
34
34
|
try {
|
|
35
|
+
options.transport.tls = {
|
|
36
|
+
rejectUnauthorized: false,
|
|
37
|
+
};
|
|
35
38
|
const { id } = options;
|
|
36
39
|
// Generate test SMTP service account from ethereal.email
|
|
37
40
|
// Only needed if you don't have a real mail account for testing
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
ARG BASE_DEBIAN=buster
|
|
2
|
+
|
|
3
|
+
# USER root
|
|
4
|
+
|
|
5
|
+
FROM debian:${BASE_DEBIAN}
|
|
6
|
+
|
|
7
|
+
ENV DEBIAN_FRONTEND=noninteractive
|
|
8
|
+
|
|
9
|
+
# Set root password to root, format is 'user:password'.
|
|
10
|
+
RUN echo 'root:root' | chpasswd
|
|
11
|
+
|
|
12
|
+
RUN apt-get update --fix-missing
|
|
13
|
+
RUN apt-get upgrade -y
|
|
14
|
+
# install sudo
|
|
15
|
+
RUN apt-get -y install sudo
|
|
16
|
+
# net-tools provides netstat commands
|
|
17
|
+
RUN apt-get -y install curl net-tools
|
|
18
|
+
RUN apt-get -yq install openssh-server supervisor
|
|
19
|
+
# Few handy utilities which are nice to have
|
|
20
|
+
RUN apt-get -y install nano vim less --no-install-recommends
|
|
21
|
+
RUN apt-get clean
|
|
22
|
+
|
|
23
|
+
# install ssh
|
|
24
|
+
RUN mkdir -p /var/run/sshd
|
|
25
|
+
# Allow root login via password
|
|
26
|
+
RUN sed -ri 's/#PermitRootLogin prohibit-password/PermitRootLogin yes/g' /etc/ssh/sshd_config
|
|
27
|
+
|
|
28
|
+
# install open ssl git and others tools
|
|
29
|
+
RUN apt-get install -yq --no-install-recommends libssl-dev curl wget git gnupg
|
|
30
|
+
|
|
31
|
+
# install lampp
|
|
32
|
+
RUN curl -Lo xampp-linux-installer.run https://sourceforge.net/projects/xampp/files/XAMPP%20Linux/7.4.33/xampp-linux-x64-7.4.33-0-installer.run?from_af=true
|
|
33
|
+
RUN chmod +x xampp-linux-installer.run
|
|
34
|
+
RUN bash -c './xampp-linux-installer.run'
|
|
35
|
+
RUN ln -sf /opt/lampp/lampp /usr/bin/lampp
|
|
36
|
+
# Enable XAMPP web interface(remove security checks)
|
|
37
|
+
RUN sed -i.bak s'/Require local/Require all granted/g' /opt/lampp/etc/extra/httpd-xampp.conf
|
|
38
|
+
# Enable error display in php
|
|
39
|
+
RUN sed -i.bak s'/display_errors=Off/display_errors=On/g' /opt/lampp/etc/php.ini
|
|
40
|
+
# Enable includes of several configuration files
|
|
41
|
+
RUN mkdir /opt/lampp/apache2/conf.d
|
|
42
|
+
RUN echo "IncludeOptional /opt/lampp/apache2/conf.d/*.conf" >>/opt/lampp/etc/httpd.conf
|
|
43
|
+
# Create a /www folder and a symbolic link to it in /opt/lampp/htdocs. It'll be accessible via http://localhost:[port]/www/
|
|
44
|
+
# This is convenient because it doesn't interfere with xampp, phpmyadmin or other tools in /opt/lampp/htdocs
|
|
45
|
+
# /opt/lampp/etc/httpd.conf
|
|
46
|
+
RUN mkdir /www
|
|
47
|
+
RUN ln -s /www /opt/lampp/htdocs
|
|
48
|
+
|
|
49
|
+
# install nodejs https://github.com/nodesource/distributions/blob/master/README.md#deb
|
|
50
|
+
RUN curl -fsSL https://deb.nodesource.com/setup_23.x | bash -
|
|
51
|
+
RUN apt-get install -y nodejs build-essential
|
|
52
|
+
RUN node --version
|
|
53
|
+
RUN npm --version
|
|
54
|
+
|
|
55
|
+
WORKDIR /home/dd
|
|
56
|
+
|
|
57
|
+
EXPOSE 22
|
|
58
|
+
|
|
59
|
+
EXPOSE 80
|
|
60
|
+
|
|
61
|
+
EXPOSE 443
|
|
62
|
+
|
|
63
|
+
EXPOSE 3000-3100
|
|
64
|
+
|
|
65
|
+
EXPOSE 4000-4100
|
|
@@ -683,6 +683,19 @@ Sitemap: https://${host}${path === '/' ? '' : path}/sitemap.xml`,
|
|
|
683
683
|
root file where the route starts, such as index.js, app.js, routes.js, etc ... */
|
|
684
684
|
|
|
685
685
|
await swaggerAutoGen({ openapi: '3.0.0' })(outputFile, routes, doc);
|
|
686
|
+
|
|
687
|
+
const htmlFiles = await fs.readdir(`./public/${host}/docs/engine/${Underpost.version.replace('v', '')}`);
|
|
688
|
+
for (const htmlFile of htmlFiles) {
|
|
689
|
+
if (htmlFile.match('.html')) {
|
|
690
|
+
fs.writeFileSync(
|
|
691
|
+
`./public/${host}/docs/engine/${Underpost.version.replace('v', '')}/${htmlFile}`,
|
|
692
|
+
fs
|
|
693
|
+
.readFileSync(`./public/${host}/docs/engine/${Underpost.version.replace('v', '')}/${htmlFile}`, 'utf8')
|
|
694
|
+
.replaceAll('Tutorials', 'References'),
|
|
695
|
+
'utf8',
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
}
|
|
686
699
|
}
|
|
687
700
|
|
|
688
701
|
if (client) {
|
package/src/server/conf.js
CHANGED
|
@@ -499,6 +499,40 @@ const buildProxyRouter = () => {
|
|
|
499
499
|
return proxyRouter;
|
|
500
500
|
};
|
|
501
501
|
|
|
502
|
+
const pathPortAssignmentFactory = (router, confServer) => {
|
|
503
|
+
const pathPortAssignmentData = {};
|
|
504
|
+
for (const host of Object.keys(confServer)) {
|
|
505
|
+
const pathPortAssignment = [];
|
|
506
|
+
for (const path of Object.keys(confServer[host])) {
|
|
507
|
+
const { peer } = confServer[host][path];
|
|
508
|
+
if (!router[`${host}${path === '/' ? '' : path}`]) continue;
|
|
509
|
+
const port = parseInt(router[`${host}${path === '/' ? '' : path}`].split(':')[2]);
|
|
510
|
+
// logger.info('', { host, port, path });
|
|
511
|
+
pathPortAssignment.push({
|
|
512
|
+
port,
|
|
513
|
+
path,
|
|
514
|
+
});
|
|
515
|
+
|
|
516
|
+
if (peer) {
|
|
517
|
+
// logger.info('', { host, port: port + 1, path: '/peer' });
|
|
518
|
+
pathPortAssignment.push({
|
|
519
|
+
port: port + 1,
|
|
520
|
+
path: '/peer',
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
pathPortAssignmentData[host] = pathPortAssignment;
|
|
525
|
+
}
|
|
526
|
+
return pathPortAssignmentData;
|
|
527
|
+
};
|
|
528
|
+
|
|
529
|
+
const deployRangePortFactory = (router) => {
|
|
530
|
+
const ports = Object.values(router).map((p) => parseInt(p.split(':')[2]));
|
|
531
|
+
const fromPort = Math.min(...ports);
|
|
532
|
+
const toPort = Math.max(...ports);
|
|
533
|
+
return { ports, fromPort, toPort };
|
|
534
|
+
};
|
|
535
|
+
|
|
502
536
|
const buildKindPorts = (from, to) =>
|
|
503
537
|
range(parseInt(from), parseInt(to))
|
|
504
538
|
.map(
|
|
@@ -729,7 +763,7 @@ const validateTemplatePath = (absolutePath = '') => {
|
|
|
729
763
|
return true;
|
|
730
764
|
};
|
|
731
765
|
|
|
732
|
-
const deployTest = async (dataDeploy) => {
|
|
766
|
+
const deployTest = async (dataDeploy = [{ deployId: 'default' }]) => {
|
|
733
767
|
const failed = [];
|
|
734
768
|
for (const deploy of dataDeploy) {
|
|
735
769
|
const deployServerConfPath = fs.existsSync(`./engine-private/replica/${deploy.deployId}/conf.server.json`)
|
|
@@ -773,6 +807,12 @@ const deployTest = async (dataDeploy) => {
|
|
|
773
807
|
return { failed };
|
|
774
808
|
};
|
|
775
809
|
|
|
810
|
+
const awaitDeployMonitor = async (init = false, deltaMs = 1000) => {
|
|
811
|
+
if (init) fs.writeFileSync(`./tmp/await-deploy`, '', 'utf8');
|
|
812
|
+
await timer(deltaMs);
|
|
813
|
+
if (fs.existsSync(`./tmp/await-deploy`)) return await awaitDeployMonitor();
|
|
814
|
+
};
|
|
815
|
+
|
|
776
816
|
const getDeployGroupId = () => {
|
|
777
817
|
const deployGroupIndexArg = process.argv.findIndex((a) => a.match(`deploy-group:`));
|
|
778
818
|
if (deployGroupIndexArg > -1) return process.argv[deployGroupIndexArg].split(':')[1].trim();
|
|
@@ -883,6 +923,53 @@ const mergeFile = async (parts = [], outputFilePath) => {
|
|
|
883
923
|
});
|
|
884
924
|
};
|
|
885
925
|
|
|
926
|
+
const rebuildConfFactory = ({ deployId, valkey, mongo }) => {
|
|
927
|
+
const confServer = loadReplicas(
|
|
928
|
+
JSON.parse(fs.readFileSync(`./engine-private/conf/${deployId}/conf.server.json`, 'utf8')),
|
|
929
|
+
);
|
|
930
|
+
const hosts = {};
|
|
931
|
+
for (const host of Object.keys(confServer)) {
|
|
932
|
+
hosts[host] = {};
|
|
933
|
+
for (const path of Object.keys(confServer[host])) {
|
|
934
|
+
if (!confServer[host][path].db) continue;
|
|
935
|
+
const { singleReplica, replicas, db } = confServer[host][path];
|
|
936
|
+
const { provider } = db;
|
|
937
|
+
if (singleReplica) {
|
|
938
|
+
for (const replica of replicas) {
|
|
939
|
+
const deployIdReplica = buildReplicaId({ replica, deployId });
|
|
940
|
+
const confServerReplica = JSON.parse(
|
|
941
|
+
fs.readFileSync(`./engine-private/replica/${deployIdReplica}/conf.server.json`, 'utf8'),
|
|
942
|
+
);
|
|
943
|
+
for (const _host of Object.keys(confServerReplica)) {
|
|
944
|
+
for (const _path of Object.keys(confServerReplica[_host])) {
|
|
945
|
+
hosts[host][_path] = { replica: { host, path } };
|
|
946
|
+
confServerReplica[_host][_path].valkey = valkey;
|
|
947
|
+
switch (provider) {
|
|
948
|
+
case 'mongoose':
|
|
949
|
+
confServerReplica[_host][_path].db.host = mongo.host;
|
|
950
|
+
break;
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
fs.writeFileSync(
|
|
955
|
+
`./engine-private/replica/${deployIdReplica}/conf.server.json`,
|
|
956
|
+
JSON.stringify(confServerReplica, null, 4),
|
|
957
|
+
'utf8',
|
|
958
|
+
);
|
|
959
|
+
}
|
|
960
|
+
} else hosts[host][path] = {};
|
|
961
|
+
confServer[host][path].valkey = valkey;
|
|
962
|
+
switch (provider) {
|
|
963
|
+
case 'mongoose':
|
|
964
|
+
confServer[host][path].db.host = mongo.host;
|
|
965
|
+
break;
|
|
966
|
+
}
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
fs.writeFileSync(`./engine-private/conf/${deployId}/conf.server.json`, JSON.stringify(confServer, null, 4), 'utf8');
|
|
970
|
+
return { hosts };
|
|
971
|
+
};
|
|
972
|
+
|
|
886
973
|
const getRestoreCronCmd = async (options = { host: '', path: '', conf: {}, deployId: '' }) => {
|
|
887
974
|
const { host, path, conf, deployId } = options;
|
|
888
975
|
const { runtime, db, git, directory } = conf[host][path];
|
|
@@ -1084,6 +1171,63 @@ const writeEnv = (envPath, envObj) =>
|
|
|
1084
1171
|
'utf8',
|
|
1085
1172
|
);
|
|
1086
1173
|
|
|
1174
|
+
const buildCliDoc = (program) => {
|
|
1175
|
+
let md = shellExec(`node bin help`, { silent: true, stdout: true }).split('Options:');
|
|
1176
|
+
const baseOptions =
|
|
1177
|
+
`## ${md[0].split(`\n`)[2]}
|
|
1178
|
+
|
|
1179
|
+
### Usage: ` +
|
|
1180
|
+
'`' +
|
|
1181
|
+
md[0].split(`\n`)[0].split('Usage: ')[1] +
|
|
1182
|
+
'`' +
|
|
1183
|
+
`
|
|
1184
|
+
` +
|
|
1185
|
+
'```\n Options:' +
|
|
1186
|
+
md[1] +
|
|
1187
|
+
' \n```';
|
|
1188
|
+
md =
|
|
1189
|
+
baseOptions +
|
|
1190
|
+
`
|
|
1191
|
+
|
|
1192
|
+
## Commands:
|
|
1193
|
+
`;
|
|
1194
|
+
program.commands.map((o) => {
|
|
1195
|
+
md +=
|
|
1196
|
+
`
|
|
1197
|
+
|
|
1198
|
+
` +
|
|
1199
|
+
'### `' +
|
|
1200
|
+
o._name +
|
|
1201
|
+
'` :' +
|
|
1202
|
+
`
|
|
1203
|
+
` +
|
|
1204
|
+
'```\n ' +
|
|
1205
|
+
shellExec(`node bin help ${o._name}`, { silent: true, stdout: true }) +
|
|
1206
|
+
' \n```' +
|
|
1207
|
+
`
|
|
1208
|
+
`;
|
|
1209
|
+
});
|
|
1210
|
+
fs.writeFileSync(`./src/client/public/nexodev/docs/references/Command Line Interface.md`, md, 'utf8');
|
|
1211
|
+
fs.writeFileSync(`./cli.md`, md, 'utf8');
|
|
1212
|
+
const readmeSplit = `pwa-microservices-template</a>`;
|
|
1213
|
+
const readme = fs.readFileSync(`./README.md`, 'utf8').split(readmeSplit);
|
|
1214
|
+
fs.writeFileSync(
|
|
1215
|
+
'./README.md',
|
|
1216
|
+
readme[0] +
|
|
1217
|
+
readmeSplit +
|
|
1218
|
+
`
|
|
1219
|
+
|
|
1220
|
+
` +
|
|
1221
|
+
baseOptions +
|
|
1222
|
+
`
|
|
1223
|
+
|
|
1224
|
+
<a target="_top" href="https://github.com/underpostnet/pwa-microservices-template/blob/master/cli.md">See complete CLI Docs here.</a>
|
|
1225
|
+
|
|
1226
|
+
`,
|
|
1227
|
+
'utf8',
|
|
1228
|
+
);
|
|
1229
|
+
};
|
|
1230
|
+
|
|
1087
1231
|
export {
|
|
1088
1232
|
Cmd,
|
|
1089
1233
|
Config,
|
|
@@ -1122,4 +1266,10 @@ export {
|
|
|
1122
1266
|
getNpmRootPath,
|
|
1123
1267
|
getUnderpostRootPath,
|
|
1124
1268
|
writeEnv,
|
|
1269
|
+
deployTest,
|
|
1270
|
+
pathPortAssignmentFactory,
|
|
1271
|
+
deployRangePortFactory,
|
|
1272
|
+
awaitDeployMonitor,
|
|
1273
|
+
rebuildConfFactory,
|
|
1274
|
+
buildCliDoc,
|
|
1125
1275
|
};
|
package/src/server/dns.js
CHANGED
|
@@ -2,43 +2,78 @@ import axios from 'axios';
|
|
|
2
2
|
import dotenv from 'dotenv';
|
|
3
3
|
import fs from 'fs';
|
|
4
4
|
import validator from 'validator';
|
|
5
|
-
import {
|
|
5
|
+
import { publicIp, publicIpv4, publicIpv6 } from 'public-ip';
|
|
6
6
|
import { loggerFactory } from './logger.js';
|
|
7
7
|
import UnderpostRootEnv from '../cli/env.js';
|
|
8
|
+
import dns from 'node:dns';
|
|
9
|
+
import os from 'node:os';
|
|
10
|
+
import { shellExec } from './process.js';
|
|
8
11
|
|
|
9
12
|
dotenv.config();
|
|
10
13
|
|
|
11
14
|
const logger = loggerFactory(import.meta);
|
|
12
15
|
|
|
16
|
+
const ip = {
|
|
17
|
+
public: {
|
|
18
|
+
get: async () => await publicIp(), // => 'fe80::200:f8ff:fe21:67cf'
|
|
19
|
+
ipv4: async () => await publicIpv4(), // => '46.5.21.123'
|
|
20
|
+
ipv6: async () => await publicIpv6(), // => 'fe80::200:f8ff:fe21:67cf'
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const isInternetConnection = (domain = 'google.com') =>
|
|
25
|
+
new Promise((resolve) => dns.lookup(domain, {}, (err) => resolve(err ? false : true)));
|
|
26
|
+
|
|
27
|
+
// export INTERFACE=$(ip route | grep default | cut -d ' ' -f 5)
|
|
28
|
+
// export IP_ADDRESS=$(ip -4 addr show dev $INTERFACE | grep -oP '(?<=inet\s)\d+(\.\d+){3}')
|
|
29
|
+
const getLocalIPv4Address = () =>
|
|
30
|
+
os.networkInterfaces()[
|
|
31
|
+
shellExec(`ip route | grep default | cut -d ' ' -f 5`, {
|
|
32
|
+
stdout: true,
|
|
33
|
+
silent: true,
|
|
34
|
+
disableLog: true,
|
|
35
|
+
}).trim()
|
|
36
|
+
].find((i) => i.family === 'IPv4').address;
|
|
37
|
+
|
|
13
38
|
class Dns {
|
|
14
39
|
static callback = async function (deployList) {
|
|
15
40
|
// Network topology configuration:
|
|
16
41
|
// LAN -> [NAT-VPS](modem/router device) -> WAN
|
|
17
42
|
// enabled DMZ Host to proxy IP 80-443 (79-444) sometimes router block first port
|
|
18
|
-
|
|
43
|
+
|
|
44
|
+
// Enabling DHCP
|
|
45
|
+
// Navigate to Subnets > VLAN > Configure DHCP.
|
|
46
|
+
// Select the appropriate DHCP options (Managed or Relay).
|
|
47
|
+
// Save and apply changes.
|
|
48
|
+
|
|
19
49
|
// verify inet ip proxy server address
|
|
20
50
|
// DHCP (Dynamic Host Configuration Protocol) LAN reserver IP -> MAC ID
|
|
21
51
|
// LAN server or device's local servers port -> 3000-3100 (2999-3101)
|
|
22
52
|
// DNS Records: [ANAME](Address Dynamic) -> [A](ipv4) host | [AAAA](ipv6) host -> [public-ip]
|
|
23
53
|
// Forward the router's TCP/UDP ports to the LAN device's IP address
|
|
24
|
-
|
|
25
|
-
const deployId = _deployId.trim();
|
|
26
|
-
const privateCronConfPath = `./engine-private/conf/${deployId}/conf.cron.json`;
|
|
27
|
-
const confCronPath = fs.existsSync(privateCronConfPath) ? privateCronConfPath : './conf/conf.cron.json';
|
|
28
|
-
const confCronData = JSON.parse(fs.readFileSync(confCronPath, 'utf8'));
|
|
29
|
-
|
|
30
|
-
let testIp;
|
|
31
|
-
|
|
32
|
-
try {
|
|
33
|
-
testIp = await ip.public.ipv4();
|
|
34
|
-
} catch (error) {
|
|
35
|
-
logger.error(error, { testIp, stack: error.stack });
|
|
36
|
-
}
|
|
54
|
+
const isOnline = await isInternetConnection();
|
|
37
55
|
|
|
38
|
-
|
|
56
|
+
if (!isOnline) return;
|
|
39
57
|
|
|
40
|
-
|
|
41
|
-
|
|
58
|
+
let testIp;
|
|
59
|
+
|
|
60
|
+
try {
|
|
61
|
+
testIp = await ip.public.ipv4();
|
|
62
|
+
} catch (error) {
|
|
63
|
+
logger.error(error, { testIp, stack: error.stack });
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const currentIp = UnderpostRootEnv.API.get('ip');
|
|
67
|
+
|
|
68
|
+
if (validator.isIP(testIp) && currentIp !== testIp) {
|
|
69
|
+
logger.info(`new ip`, testIp);
|
|
70
|
+
UnderpostRootEnv.API.set('monitor-input', 'pause');
|
|
71
|
+
|
|
72
|
+
for (const _deployId of deployList.split(',')) {
|
|
73
|
+
const deployId = _deployId.trim();
|
|
74
|
+
const privateCronConfPath = `./engine-private/conf/${deployId}/conf.cron.json`;
|
|
75
|
+
const confCronPath = fs.existsSync(privateCronConfPath) ? privateCronConfPath : './conf/conf.cron.json';
|
|
76
|
+
const confCronData = JSON.parse(fs.readFileSync(confCronPath, 'utf8'));
|
|
42
77
|
for (const recordType of Object.keys(confCronData.records)) {
|
|
43
78
|
switch (recordType) {
|
|
44
79
|
case 'A':
|
|
@@ -60,6 +95,7 @@ class Dns {
|
|
|
60
95
|
if (verifyIp === testIp) {
|
|
61
96
|
logger.info('ip updated successfully', testIp);
|
|
62
97
|
UnderpostRootEnv.API.set('ip', testIp);
|
|
98
|
+
UnderpostRootEnv.API.delete('monitor-input');
|
|
63
99
|
} else logger.error('ip not updated', testIp);
|
|
64
100
|
} catch (error) {
|
|
65
101
|
logger.error(error, error.stack);
|
|
@@ -94,3 +130,5 @@ class Dns {
|
|
|
94
130
|
}
|
|
95
131
|
|
|
96
132
|
export default Dns;
|
|
133
|
+
|
|
134
|
+
export { Dns, ip, isInternetConnection, getLocalIPv4Address };
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
function isPlainObject(obj) {
|
|
2
|
+
return obj ? typeof obj === 'object' && Object.getPrototypeOf(obj) === Object.prototype : false;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
const supportType = ['string', 'number', 'array', 'object', 'boolean', 'integer'];
|
|
6
|
+
|
|
7
|
+
function getType(type) {
|
|
8
|
+
if (!type) type = 'string';
|
|
9
|
+
if (supportType.indexOf(type) !== -1) {
|
|
10
|
+
return type;
|
|
11
|
+
}
|
|
12
|
+
return typeof type;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function isSchema(object) {
|
|
16
|
+
if (supportType.indexOf(object.type) !== -1) {
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function handleSchema(json, schema) {
|
|
23
|
+
Object.assign(schema, json);
|
|
24
|
+
if (schema.type === 'object') {
|
|
25
|
+
delete schema.properties;
|
|
26
|
+
parse(json.properties, schema);
|
|
27
|
+
}
|
|
28
|
+
if (schema.type === 'array') {
|
|
29
|
+
delete schema.items;
|
|
30
|
+
schema.items = {};
|
|
31
|
+
parse(json.items, schema.items);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function handleArray(arr, schema) {
|
|
36
|
+
schema.type = 'array';
|
|
37
|
+
let props = (schema.items = {});
|
|
38
|
+
parse(arr[0], props);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function handleObject(json, schema) {
|
|
42
|
+
if (isSchema(json)) {
|
|
43
|
+
return handleSchema(json, schema);
|
|
44
|
+
}
|
|
45
|
+
schema.type = 'object';
|
|
46
|
+
schema.required = [];
|
|
47
|
+
let props = (schema.properties = {});
|
|
48
|
+
for (let key in json) {
|
|
49
|
+
let item = json[key];
|
|
50
|
+
let curSchema = (props[key] = {});
|
|
51
|
+
if (key[0] === '*') {
|
|
52
|
+
delete props[key];
|
|
53
|
+
key = key.substr(1);
|
|
54
|
+
schema.required.push(key);
|
|
55
|
+
curSchema = props[key] = {};
|
|
56
|
+
}
|
|
57
|
+
parse(item, curSchema);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function parse(json, schema) {
|
|
62
|
+
if (Array.isArray(json)) {
|
|
63
|
+
handleArray(json, schema);
|
|
64
|
+
} else if (isPlainObject(json)) {
|
|
65
|
+
handleObject(json, schema);
|
|
66
|
+
} else {
|
|
67
|
+
schema.type = getType(json);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function ejs(data) {
|
|
72
|
+
let JsonSchema = {};
|
|
73
|
+
parse(data, JsonSchema);
|
|
74
|
+
return JsonSchema;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export { ejs };
|
package/src/server/logger.js
CHANGED
|
@@ -176,7 +176,7 @@ const loggerMiddleware = (meta = { url: '' }) => {
|
|
|
176
176
|
);
|
|
177
177
|
};
|
|
178
178
|
|
|
179
|
-
const
|
|
179
|
+
const underpostASCII = () => `
|
|
180
180
|
|
|
181
181
|
██╗░░░██╗███╗░░██╗██████╗░███████╗██████╗░██████╗░░█████╗░░██████╗████████╗
|
|
182
182
|
██║░░░██║████╗░██║██╔══██╗██╔════╝██╔══██╗██╔══██╗██╔══██╗██╔════╝╚══██╔══╝
|
|
@@ -188,10 +188,10 @@ const underpostASCI = () => `
|
|
|
188
188
|
|
|
189
189
|
const actionInitLog = () =>
|
|
190
190
|
console.log(
|
|
191
|
-
|
|
191
|
+
underpostASCII() +
|
|
192
192
|
`
|
|
193
193
|
https://www.nexodev.org/docs
|
|
194
194
|
`,
|
|
195
195
|
);
|
|
196
196
|
|
|
197
|
-
export { loggerFactory, loggerMiddleware, setUpInfo,
|
|
197
|
+
export { loggerFactory, loggerMiddleware, setUpInfo, underpostASCII, actionInitLog };
|