underpost 2.8.79 → 2.8.84
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 +22 -20
- package/.github/workflows/npmpkg.yml +15 -10
- package/.github/workflows/pwa-microservices-template.page.yml +12 -3
- package/.github/workflows/pwa-microservices-template.test.yml +20 -17
- package/.vscode/extensions.json +2 -3
- package/.vscode/settings.json +2 -42
- package/Dockerfile +14 -33
- package/README.md +43 -25
- package/bin/db.js +1 -0
- package/bin/deploy.js +104 -797
- package/bin/file.js +18 -1
- package/bin/vs.js +18 -3
- package/cli.md +367 -207
- package/conf.js +4 -0
- package/docker-compose.yml +1 -1
- package/manifests/deployment/dd-template-development/deployment.yaml +167 -0
- package/manifests/deployment/dd-template-development/proxy.yaml +46 -0
- package/manifests/deployment/tensorflow/tf-gpu-test.yaml +65 -0
- package/manifests/lxd/lxd-admin-profile.yaml +1 -0
- package/manifests/lxd/lxd-preseed.yaml +9 -37
- package/manifests/lxd/underpost-setup.sh +98 -81
- package/manifests/maas/device-scan.sh +43 -0
- package/manifests/maas/gpu-diag.sh +19 -0
- package/manifests/maas/lxd-preseed.yaml +32 -0
- package/manifests/maas/maas-setup.sh +120 -0
- package/manifests/maas/nat-iptables.sh +26 -0
- package/manifests/maas/snap-clean.sh +26 -0
- package/manifests/mariadb/statefulset.yaml +2 -1
- package/manifests/mariadb/storage-class.yaml +10 -0
- package/manifests/mongodb-4.4/service-deployment.yaml +2 -2
- package/manifests/valkey/service.yaml +3 -9
- package/manifests/valkey/statefulset.yaml +10 -12
- package/package.json +1 -1
- package/src/cli/baremetal.js +1280 -0
- package/src/cli/cloud-init.js +537 -0
- package/src/cli/cluster.js +506 -243
- package/src/cli/deploy.js +41 -3
- package/src/cli/env.js +2 -2
- package/src/cli/image.js +57 -9
- package/src/cli/index.js +271 -232
- package/src/cli/lxd.js +314 -81
- package/src/cli/repository.js +7 -4
- package/src/cli/run.js +262 -0
- package/src/cli/test.js +1 -1
- package/src/index.js +28 -1
- package/src/runtime/lampp/Dockerfile +41 -47
- package/src/server/conf.js +61 -0
- package/src/server/logger.js +3 -3
- package/src/server/process.js +16 -19
- package/src/server/runtime.js +1 -6
- package/src/server/ssl.js +1 -12
- package/src/server/valkey.js +3 -3
- package/supervisord-openssh-server.conf +0 -5
package/src/cli/run.js
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
import { daemonProcess, getTerminalPid, openTerminal, pbcopy, shellCd, shellExec } from '../server/process.js';
|
|
2
|
+
import read from 'read';
|
|
3
|
+
import { getNpmRootPath } from '../server/conf.js';
|
|
4
|
+
import { loggerFactory } from '../server/logger.js';
|
|
5
|
+
import UnderpostTest from './test.js';
|
|
6
|
+
import fs from 'fs-extra';
|
|
7
|
+
import { range, setPad, timer } from '../client/components/core/CommonJs.js';
|
|
8
|
+
import UnderpostDeploy from './deploy.js';
|
|
9
|
+
|
|
10
|
+
const logger = loggerFactory(import.meta);
|
|
11
|
+
|
|
12
|
+
class UnderpostRun {
|
|
13
|
+
static DEFAULT_OPTION = {
|
|
14
|
+
dev: false,
|
|
15
|
+
podName: '',
|
|
16
|
+
volumeHostPath: '',
|
|
17
|
+
volumeMountPath: '',
|
|
18
|
+
imageName: '',
|
|
19
|
+
containerName: '',
|
|
20
|
+
namespace: '',
|
|
21
|
+
};
|
|
22
|
+
static RUNNERS = {
|
|
23
|
+
'spark-template': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
24
|
+
const dir = '/home/dd/spark-template';
|
|
25
|
+
shellExec(`sudo rm -rf ${dir}`);
|
|
26
|
+
shellCd('/home/dd');
|
|
27
|
+
|
|
28
|
+
// pbcopy(`cd /home/dd && sbt new underpostnet/spark-template.g8`);
|
|
29
|
+
// await read({ prompt: 'Command copy to clipboard, press enter to continue.\n' });
|
|
30
|
+
shellExec(`cd /home/dd && sbt new underpostnet/spark-template.g8 '--name=spark-template'`);
|
|
31
|
+
|
|
32
|
+
shellCd(dir);
|
|
33
|
+
|
|
34
|
+
shellExec(`git init && git add . && git commit -m "Base implementation"`);
|
|
35
|
+
shellExec(`chmod +x ./replace_params.sh`);
|
|
36
|
+
shellExec(`chmod +x ./build.sh`);
|
|
37
|
+
|
|
38
|
+
shellExec(`./replace_params.sh`);
|
|
39
|
+
shellExec(`./build.sh`);
|
|
40
|
+
|
|
41
|
+
shellCd('/home/dd/engine');
|
|
42
|
+
},
|
|
43
|
+
rmi: (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
44
|
+
shellExec(`podman rmi $(podman images -qa) --force`);
|
|
45
|
+
},
|
|
46
|
+
kill: (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
47
|
+
shellExec(`sudo kill -9 $(lsof -t -i:${path})`);
|
|
48
|
+
},
|
|
49
|
+
secret: (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
50
|
+
shellExec(
|
|
51
|
+
`underpost secret underpost --create-from-file ${
|
|
52
|
+
path ? path : `/home/dd/engine/engine-private/conf/dd-cron/.env.production`
|
|
53
|
+
}`,
|
|
54
|
+
);
|
|
55
|
+
},
|
|
56
|
+
'gpu-env': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
57
|
+
shellExec(
|
|
58
|
+
`node bin cluster --dev --reset && node bin cluster --dev --dedicated-gpu --kubeadm && kubectl get pods --all-namespaces -o wide -w`,
|
|
59
|
+
);
|
|
60
|
+
},
|
|
61
|
+
'tf-gpu-test': (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
62
|
+
const { underpostRoot } = options;
|
|
63
|
+
shellExec(`kubectl delete configmap tf-gpu-test-script`);
|
|
64
|
+
shellExec(`kubectl delete pod tf-gpu-test-pod`);
|
|
65
|
+
shellExec(`kubectl apply -f ${underpostRoot}/manifests/deployment/tensorflow/tf-gpu-test.yaml`);
|
|
66
|
+
},
|
|
67
|
+
ide: (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
68
|
+
const { underpostRoot } = options;
|
|
69
|
+
shellExec(`node ${underpostRoot}/bin/vs ${path}`);
|
|
70
|
+
},
|
|
71
|
+
monitor: (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
72
|
+
const pid = getTerminalPid();
|
|
73
|
+
logger.info('monitor pid', pid);
|
|
74
|
+
const checkPath = '/await';
|
|
75
|
+
const _monitor = async () => {
|
|
76
|
+
const result = UnderpostDeploy.API.existsContainerFile({ podName: path, path: checkPath });
|
|
77
|
+
logger.info('monitor', result);
|
|
78
|
+
if (result === true) {
|
|
79
|
+
switch (path) {
|
|
80
|
+
case 'tf-vae-test':
|
|
81
|
+
{
|
|
82
|
+
const nameSpace = 'default';
|
|
83
|
+
const podName = path;
|
|
84
|
+
const basePath = '/home/dd';
|
|
85
|
+
const scriptPath = '/site/en/tutorials/generative/cvae.py';
|
|
86
|
+
// shellExec(
|
|
87
|
+
// `sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${scriptPath} ${basePath}/lab/src/${scriptPath
|
|
88
|
+
// .split('/')
|
|
89
|
+
// .pop()}`,
|
|
90
|
+
// );
|
|
91
|
+
// const file = fs.readFileSync(`${basePath}/lab/src/${scriptPath.split('/').pop()}`, 'utf8');
|
|
92
|
+
// fs.writeFileSync(
|
|
93
|
+
// `${basePath}/lab/src/${scriptPath.split('/').pop()}`,
|
|
94
|
+
// file.replace(
|
|
95
|
+
// `import time`,
|
|
96
|
+
// `import time
|
|
97
|
+
// print('=== SCRIPT UPDATE TEST ===')`,
|
|
98
|
+
// ),
|
|
99
|
+
// 'utf8',
|
|
100
|
+
// );
|
|
101
|
+
shellExec(
|
|
102
|
+
`sudo kubectl cp ${basePath}/lab/src/${scriptPath
|
|
103
|
+
.split('/')
|
|
104
|
+
.pop()} ${nameSpace}/${podName}:${basePath}/docs${scriptPath}`,
|
|
105
|
+
);
|
|
106
|
+
// shellExec(`sudo kubectl exec -i ${podName} -- sh -c "ipython ${basePath}/docs${scriptPath}"`);
|
|
107
|
+
shellExec(`sudo kubectl exec -i ${podName} -- sh -c "rm -rf ${checkPath}"`);
|
|
108
|
+
|
|
109
|
+
{
|
|
110
|
+
const checkPath = `/latent_space_plot.png`;
|
|
111
|
+
const outsPaths = [];
|
|
112
|
+
logger.info('monitor', checkPath);
|
|
113
|
+
while (!UnderpostDeploy.API.existsContainerFile({ podName, path: `/home/dd/docs${checkPath}` }))
|
|
114
|
+
await timer(1000);
|
|
115
|
+
|
|
116
|
+
{
|
|
117
|
+
const toPath = `${basePath}/lab${checkPath}`;
|
|
118
|
+
outsPaths.push(toPath);
|
|
119
|
+
shellExec(`sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${checkPath} ${toPath}`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
for (let i of range(1, 10)) {
|
|
123
|
+
i = `/image_at_epoch_${setPad(i, '0', 4)}.png`;
|
|
124
|
+
const toPath = `${basePath}/lab/${i}`;
|
|
125
|
+
outsPaths.push(toPath);
|
|
126
|
+
shellExec(`sudo kubectl cp ${nameSpace}/${podName}:${basePath}/docs${i} ${toPath}`);
|
|
127
|
+
}
|
|
128
|
+
openTerminal(`firefox ${outsPaths.join(' ')}`, { single: true });
|
|
129
|
+
}
|
|
130
|
+
shellExec(`sudo kill -9 ${pid}`);
|
|
131
|
+
}
|
|
132
|
+
break;
|
|
133
|
+
|
|
134
|
+
default:
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
await timer(1000);
|
|
140
|
+
_monitor();
|
|
141
|
+
};
|
|
142
|
+
_monitor();
|
|
143
|
+
},
|
|
144
|
+
'tf-vae-test': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
145
|
+
const { underpostRoot } = options;
|
|
146
|
+
const podName = 'tf-vae-test';
|
|
147
|
+
await UnderpostRun.RUNNERS['deploy-job']('', {
|
|
148
|
+
podName,
|
|
149
|
+
// volumeMountPath: '/custom_images',
|
|
150
|
+
// volumeHostPath: '/home/dd/engine/src/client/public/cyberia/assets/skin',
|
|
151
|
+
on: {
|
|
152
|
+
init: async () => {
|
|
153
|
+
openTerminal(`node bin run --dev monitor ${podName}`);
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
args: [
|
|
157
|
+
`pip install --upgrade \
|
|
158
|
+
nbconvert \
|
|
159
|
+
tensorflow-probability==0.23.0 \
|
|
160
|
+
imageio \
|
|
161
|
+
git+https://github.com/tensorflow/docs \
|
|
162
|
+
matplotlib \
|
|
163
|
+
"numpy<1.25,>=1.21"`,
|
|
164
|
+
'mkdir -p /home/dd',
|
|
165
|
+
'cd /home/dd',
|
|
166
|
+
'git clone https://github.com/tensorflow/docs.git',
|
|
167
|
+
'cd docs',
|
|
168
|
+
'jupyter nbconvert --to python site/en/tutorials/generative/cvae.ipynb',
|
|
169
|
+
`echo '' > /await`,
|
|
170
|
+
`echo '=== WAITING SCRIPT LAUNCH ==='`,
|
|
171
|
+
`while [ -f /await ]; do sleep 1; done`,
|
|
172
|
+
`echo '=== FINISHED ==='`,
|
|
173
|
+
daemonProcess(`ipython site/en/tutorials/generative/cvae.py`),
|
|
174
|
+
],
|
|
175
|
+
});
|
|
176
|
+
},
|
|
177
|
+
'deploy-job': async (path, options = UnderpostRun.DEFAULT_OPTION) => {
|
|
178
|
+
const podName = options.podName || 'deploy-job';
|
|
179
|
+
const volumeName = `${podName}-volume`;
|
|
180
|
+
const args = (options.args ? options.args : path ? [`python ${path}`] : []).filter((c) => c.trim());
|
|
181
|
+
const imageName = options.imageName || 'nvcr.io/nvidia/tensorflow:24.04-tf2-py3';
|
|
182
|
+
const containerName = options.containerName || `${podName}-container`;
|
|
183
|
+
const gpuEnable = imageName.match('nvidia');
|
|
184
|
+
const runtimeClassName = gpuEnable ? 'nvidia' : '';
|
|
185
|
+
const namespace = options.namespace || 'default';
|
|
186
|
+
const volumeMountPath = options.volumeMountPath || path;
|
|
187
|
+
const volumeHostPath = options.volumeHostPath || path;
|
|
188
|
+
const enableVolumeMount = volumeHostPath && volumeMountPath;
|
|
189
|
+
|
|
190
|
+
const cmd = `kubectl apply -f - <<EOF
|
|
191
|
+
apiVersion: v1
|
|
192
|
+
kind: Pod
|
|
193
|
+
metadata:
|
|
194
|
+
name: ${podName}
|
|
195
|
+
namespace: ${namespace}
|
|
196
|
+
spec:
|
|
197
|
+
restartPolicy: Never
|
|
198
|
+
${runtimeClassName ? ` runtimeClassName: ${runtimeClassName}` : ''}
|
|
199
|
+
containers:
|
|
200
|
+
- name: ${containerName}
|
|
201
|
+
image: ${imageName}
|
|
202
|
+
imagePullPolicy: IfNotPresent
|
|
203
|
+
tty: true
|
|
204
|
+
stdin: true
|
|
205
|
+
command: ${JSON.stringify(options.command ? options.command : ['/bin/bash', '-c'])}
|
|
206
|
+
${
|
|
207
|
+
args.length > 0
|
|
208
|
+
? ` args:
|
|
209
|
+
- |
|
|
210
|
+
${args.map((arg) => ` ${arg}`).join('\n')}`
|
|
211
|
+
: ''
|
|
212
|
+
}
|
|
213
|
+
${
|
|
214
|
+
gpuEnable
|
|
215
|
+
? ` resources:
|
|
216
|
+
limits:
|
|
217
|
+
nvidia.com/gpu: '1'
|
|
218
|
+
env:
|
|
219
|
+
- name: NVIDIA_VISIBLE_DEVICES
|
|
220
|
+
value: all`
|
|
221
|
+
: ''
|
|
222
|
+
}
|
|
223
|
+
${
|
|
224
|
+
enableVolumeMount
|
|
225
|
+
? `
|
|
226
|
+
volumeMounts:
|
|
227
|
+
- name: ${volumeName}
|
|
228
|
+
mountPath: ${volumeMountPath}
|
|
229
|
+
volumes:
|
|
230
|
+
- name: ${volumeName}
|
|
231
|
+
hostPath:
|
|
232
|
+
path: ${volumeHostPath}
|
|
233
|
+
type: ${fs.statSync(volumeHostPath).isDirectory() ? 'Directory' : 'File'}`
|
|
234
|
+
: ''
|
|
235
|
+
}
|
|
236
|
+
EOF`;
|
|
237
|
+
shellExec(`kubectl delete pod ${podName}`);
|
|
238
|
+
console.log(cmd);
|
|
239
|
+
shellExec(cmd, { disableLog: true });
|
|
240
|
+
const successInstance = await UnderpostTest.API.statusMonitor(podName);
|
|
241
|
+
if (successInstance) {
|
|
242
|
+
options.on?.init ? await options.on.init() : null;
|
|
243
|
+
shellExec(`kubectl logs -f ${podName}`);
|
|
244
|
+
}
|
|
245
|
+
},
|
|
246
|
+
};
|
|
247
|
+
static API = {
|
|
248
|
+
async callback(runner, path, options = UnderpostRun.DEFAULT_OPTION) {
|
|
249
|
+
const npmRoot = getNpmRootPath();
|
|
250
|
+
const underpostRoot = options?.dev === true ? '.' : `${npmRoot}/underpost`;
|
|
251
|
+
if (options.command) options.command = options.command.split(',');
|
|
252
|
+
if (options.args) options.args = options.args.split(',');
|
|
253
|
+
options.underpostRoot = underpostRoot;
|
|
254
|
+
options.npmRoot = npmRoot;
|
|
255
|
+
logger.info('callback', { path, options });
|
|
256
|
+
const result = await UnderpostRun.RUNNERS[runner](path, options);
|
|
257
|
+
return result;
|
|
258
|
+
},
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export default UnderpostRun;
|
package/src/cli/test.js
CHANGED
|
@@ -94,7 +94,7 @@ class UnderpostTest {
|
|
|
94
94
|
const _monitor = async () => {
|
|
95
95
|
await timer(deltaMs);
|
|
96
96
|
const pods = UnderpostDeploy.API.get(podName, kindType);
|
|
97
|
-
|
|
97
|
+
let result = pods.find((p) => p.STATUS === status || (status === 'Running' && p.STATUS === 'Completed'));
|
|
98
98
|
logger.info(
|
|
99
99
|
`Testing pod ${podName}... ${result ? 1 : 0}/1 - elapsed time ${deltaMs * (index + 1)}s - attempt ${
|
|
100
100
|
index + 1
|
package/src/index.js
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
* @namespace Underpost
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
+
import UnderpostBaremetal from './cli/baremetal.js';
|
|
8
|
+
import UnderpostCloudInit from './cli/cloud-init.js';
|
|
7
9
|
import UnderpostCluster from './cli/cluster.js';
|
|
8
10
|
import UnderpostCron from './cli/cron.js';
|
|
9
11
|
import UnderpostDB from './cli/db.js';
|
|
@@ -14,6 +16,7 @@ import UnderpostImage from './cli/image.js';
|
|
|
14
16
|
import UnderpostLxd from './cli/lxd.js';
|
|
15
17
|
import UnderpostMonitor from './cli/monitor.js';
|
|
16
18
|
import UnderpostRepository from './cli/repository.js';
|
|
19
|
+
import UnderpostRun from './cli/run.js';
|
|
17
20
|
import UnderpostScript from './cli/script.js';
|
|
18
21
|
import UnderpostSecret from './cli/secrets.js';
|
|
19
22
|
import UnderpostTest from './cli/test.js';
|
|
@@ -31,7 +34,7 @@ class Underpost {
|
|
|
31
34
|
* @type {String}
|
|
32
35
|
* @memberof Underpost
|
|
33
36
|
*/
|
|
34
|
-
static version = 'v2.8.
|
|
37
|
+
static version = 'v2.8.84';
|
|
35
38
|
/**
|
|
36
39
|
* Repository cli API
|
|
37
40
|
* @static
|
|
@@ -130,6 +133,30 @@ class Underpost {
|
|
|
130
133
|
* @memberof Underpost
|
|
131
134
|
*/
|
|
132
135
|
static lxd = UnderpostLxd.API;
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Cloud Init cli API
|
|
139
|
+
* @static
|
|
140
|
+
* @type {UnderpostCloudInit.API}
|
|
141
|
+
* @memberof Underpost
|
|
142
|
+
*/
|
|
143
|
+
static cloudInit = UnderpostCloudInit.API;
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Run cli API
|
|
147
|
+
* @static
|
|
148
|
+
* @type {UnderpostRun.API}
|
|
149
|
+
* @memberof Underpost
|
|
150
|
+
*/
|
|
151
|
+
static run = UnderpostRun.API;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Baremetal cli API
|
|
155
|
+
* @static
|
|
156
|
+
* @type {UnderpostBaremetal.API}
|
|
157
|
+
* @memberof Underpost
|
|
158
|
+
*/
|
|
159
|
+
static baremetal = UnderpostBaremetal.API;
|
|
133
160
|
}
|
|
134
161
|
|
|
135
162
|
const up = Underpost;
|
|
@@ -1,65 +1,59 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
RUN
|
|
11
|
-
|
|
12
|
-
RUN
|
|
13
|
-
RUN
|
|
14
|
-
|
|
15
|
-
RUN
|
|
16
|
-
|
|
17
|
-
RUN
|
|
18
|
-
RUN
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
|
1
|
+
FROM rockylinux:9
|
|
2
|
+
|
|
3
|
+
RUN dnf install -y --allowerasing bzip2
|
|
4
|
+
|
|
5
|
+
RUN dnf update -y
|
|
6
|
+
RUN dnf install -y epel-release
|
|
7
|
+
RUN dnf install -y --allowerasing sudo
|
|
8
|
+
RUN dnf install -y --allowerasing curl
|
|
9
|
+
RUN dnf install -y --allowerasing net-tools
|
|
10
|
+
RUN dnf install -y --allowerasing openssh-server
|
|
11
|
+
RUN dnf install -y --allowerasing nano
|
|
12
|
+
RUN dnf install -y --allowerasing vim-enhanced
|
|
13
|
+
RUN dnf install -y --allowerasing less
|
|
14
|
+
RUN dnf install -y --allowerasing openssl-devel
|
|
15
|
+
RUN dnf install -y --allowerasing wget
|
|
16
|
+
RUN dnf install -y --allowerasing git
|
|
17
|
+
RUN dnf install -y --allowerasing gnupg2
|
|
18
|
+
RUN dnf clean all
|
|
19
|
+
|
|
20
|
+
# Install LAMPP (XAMPP)
|
|
21
|
+
# Download the XAMPP installer for Linux
|
|
32
22
|
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
23
|
RUN chmod +x xampp-linux-installer.run
|
|
34
|
-
|
|
24
|
+
# Run the XAMPP installer in silent mode
|
|
25
|
+
RUN bash -c './xampp-linux-installer.run --mode unattended'
|
|
26
|
+
# Create a symbolic link for easy access to lampp command
|
|
35
27
|
RUN ln -sf /opt/lampp/lampp /usr/bin/lampp
|
|
36
|
-
|
|
37
|
-
|
|
28
|
+
|
|
29
|
+
# Configure XAMPP
|
|
30
|
+
# Enable XAMPP web interface (remove security checks)
|
|
31
|
+
RUN sed -i.bak 's/Require local/Require all granted/g' /opt/lampp/etc/extra/httpd-xampp.conf
|
|
38
32
|
# Enable error display in php
|
|
39
|
-
RUN sed -i.bak s
|
|
40
|
-
# Enable includes of several configuration files
|
|
41
|
-
RUN mkdir /opt/lampp/apache2/conf.d
|
|
33
|
+
RUN sed -i.bak 's/display_errors=Off/display_errors=On/g' /opt/lampp/etc/php.ini
|
|
34
|
+
# Enable includes of several configuration files for Apache
|
|
35
|
+
RUN mkdir -p /opt/lampp/apache2/conf.d
|
|
42
36
|
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
|
|
44
|
-
# This is convenient because it doesn't interfere with xampp, phpmyadmin or other tools
|
|
45
|
-
# /opt/lampp/etc/httpd.conf
|
|
37
|
+
# Create a /www folder and a symbolic link to it in /opt/lampp/htdocs
|
|
38
|
+
# This is convenient because it doesn't interfere with xampp, phpmyadmin or other tools
|
|
46
39
|
RUN mkdir /www
|
|
47
40
|
RUN ln -s /www /opt/lampp/htdocs
|
|
48
41
|
|
|
49
|
-
#
|
|
50
|
-
RUN curl -fsSL https://
|
|
51
|
-
RUN
|
|
42
|
+
# Install Node.js
|
|
43
|
+
RUN curl -fsSL https://rpm.nodesource.com/setup_23.x | bash -
|
|
44
|
+
RUN dnf install nodejs -y
|
|
45
|
+
RUN dnf clean all
|
|
46
|
+
|
|
47
|
+
# Verify Node.js and npm versions
|
|
52
48
|
RUN node --version
|
|
53
49
|
RUN npm --version
|
|
54
50
|
|
|
51
|
+
# Set working directory
|
|
55
52
|
WORKDIR /home/dd
|
|
56
53
|
|
|
54
|
+
# Expose necessary ports
|
|
57
55
|
EXPOSE 22
|
|
58
|
-
|
|
59
56
|
EXPOSE 80
|
|
60
|
-
|
|
61
57
|
EXPOSE 443
|
|
62
|
-
|
|
63
58
|
EXPOSE 3000-3100
|
|
64
|
-
|
|
65
59
|
EXPOSE 4000-4100
|
package/src/server/conf.js
CHANGED
|
@@ -1171,6 +1171,66 @@ const writeEnv = (envPath, envObj) =>
|
|
|
1171
1171
|
'utf8',
|
|
1172
1172
|
);
|
|
1173
1173
|
|
|
1174
|
+
const buildCliDoc = (program, oldVersion, newVersion) => {
|
|
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
|
+
md = md.replaceAll(oldVersion, newVersion);
|
|
1211
|
+
fs.writeFileSync(`./src/client/public/nexodev/docs/references/Command Line Interface.md`, md, 'utf8');
|
|
1212
|
+
fs.writeFileSync(`./cli.md`, md, 'utf8');
|
|
1213
|
+
const readmeSplit = `pwa-microservices-template</a>`;
|
|
1214
|
+
const readme = fs.readFileSync(`./README.md`, 'utf8').split(readmeSplit);
|
|
1215
|
+
fs.writeFileSync(
|
|
1216
|
+
'./README.md',
|
|
1217
|
+
(
|
|
1218
|
+
readme[0] +
|
|
1219
|
+
readmeSplit +
|
|
1220
|
+
`
|
|
1221
|
+
|
|
1222
|
+
` +
|
|
1223
|
+
baseOptions +
|
|
1224
|
+
`
|
|
1225
|
+
|
|
1226
|
+
<a target="_top" href="https://github.com/underpostnet/pwa-microservices-template/blob/master/cli.md">See complete CLI Docs here.</a>
|
|
1227
|
+
|
|
1228
|
+
`
|
|
1229
|
+
).replaceAll(oldVersion, newVersion),
|
|
1230
|
+
'utf8',
|
|
1231
|
+
);
|
|
1232
|
+
};
|
|
1233
|
+
|
|
1174
1234
|
export {
|
|
1175
1235
|
Cmd,
|
|
1176
1236
|
Config,
|
|
@@ -1214,4 +1274,5 @@ export {
|
|
|
1214
1274
|
deployRangePortFactory,
|
|
1215
1275
|
awaitDeployMonitor,
|
|
1216
1276
|
rebuildConfFactory,
|
|
1277
|
+
buildCliDoc,
|
|
1217
1278
|
};
|
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 };
|
package/src/server/process.js
CHANGED
|
@@ -10,8 +10,6 @@ dotenv.config();
|
|
|
10
10
|
|
|
11
11
|
const logger = loggerFactory(import.meta);
|
|
12
12
|
|
|
13
|
-
// process.exit();
|
|
14
|
-
|
|
15
13
|
const getRootDirectory = () => process.cwd().replace(/\\/g, '/');
|
|
16
14
|
|
|
17
15
|
const ProcessController = {
|
|
@@ -63,27 +61,26 @@ const shellCd = (cd, options = { disableLog: false }) => {
|
|
|
63
61
|
return shell.cd(cd);
|
|
64
62
|
};
|
|
65
63
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
64
|
+
const openTerminal = (cmd, options = { single: false }) => {
|
|
65
|
+
if (options.single === true) {
|
|
66
|
+
shellExec(`setsid gnome-terminal -- bash -ic "${cmd}; exec bash" >/dev/null 2>&1 &`);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
shellExec(`gnome-terminal -- bash -c "${cmd}; exec bash" & disown`, {
|
|
70
|
+
async: true,
|
|
71
|
+
stdout: true,
|
|
72
|
+
});
|
|
73
|
+
};
|
|
77
74
|
|
|
78
|
-
|
|
75
|
+
const daemonProcess = (cmd) => `exec bash -c '${cmd}; exec tail -f /dev/null'`;
|
|
79
76
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
77
|
+
// list all terminals: pgrep gnome-terminal
|
|
78
|
+
// list last terminal: pgrep -n gnome-terminal
|
|
79
|
+
const getTerminalPid = () => JSON.parse(shellExec(`pgrep -n gnome-terminal`, { stdout: true, silent: true }));
|
|
83
80
|
|
|
81
|
+
function pbcopy(data) {
|
|
84
82
|
clipboard.writeSync(data || '🦄');
|
|
85
|
-
|
|
86
83
|
logger.info(`copied to clipboard`, clipboard.readSync());
|
|
87
84
|
}
|
|
88
85
|
|
|
89
|
-
export { ProcessController, getRootDirectory, shellExec, shellCd, pbcopy };
|
|
86
|
+
export { ProcessController, getRootDirectory, shellExec, shellCd, pbcopy, openTerminal, getTerminalPid, daemonProcess };
|
package/src/server/runtime.js
CHANGED
|
@@ -251,11 +251,6 @@ const buildRuntime = async () => {
|
|
|
251
251
|
return next();
|
|
252
252
|
});
|
|
253
253
|
|
|
254
|
-
// https://github.com/prometheus/prometheus/blob/main/documentation/examples/prometheus.yml
|
|
255
|
-
// https://github.com/grafana/grafana/tree/main/conf
|
|
256
|
-
// https://medium.com/@diego.coder/monitoreo-de-aplicaciones-con-node-js-grafana-y-prometheus-afd2b33e3f91
|
|
257
|
-
// for grafana prometheus server: host.docker.internal:9090
|
|
258
|
-
|
|
259
254
|
app.use((req, res, next) => {
|
|
260
255
|
requestCounter.inc({
|
|
261
256
|
instance: `${host}:${port}${path}`,
|
|
@@ -366,7 +361,7 @@ const buildRuntime = async () => {
|
|
|
366
361
|
if (db && apis) await DataBaseProvider.load({ apis, host, path, db });
|
|
367
362
|
|
|
368
363
|
// valkey server
|
|
369
|
-
await createValkeyConnection({ host, path }, valkey);
|
|
364
|
+
if (valkey) await createValkeyConnection({ host, path }, valkey);
|
|
370
365
|
|
|
371
366
|
if (mailer) {
|
|
372
367
|
const mailerSsrConf = confSSR[getCapVariableName(client)];
|
package/src/server/ssl.js
CHANGED
|
@@ -106,15 +106,4 @@ const sslRedirectMiddleware = (req, res, port, proxyRouter) => {
|
|
|
106
106
|
return res.status(302).redirect(sslRedirectUrl);
|
|
107
107
|
};
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
switch (process.platform) {
|
|
111
|
-
case 'win32':
|
|
112
|
-
break;
|
|
113
|
-
case 'linux':
|
|
114
|
-
break;
|
|
115
|
-
default:
|
|
116
|
-
break;
|
|
117
|
-
}
|
|
118
|
-
};
|
|
119
|
-
|
|
120
|
-
export { buildSSL, buildSecureContext, validateSecureContext, createSslServer, sslRedirectMiddleware, installCertbot };
|
|
109
|
+
export { buildSSL, buildSecureContext, validateSecureContext, createSslServer, sslRedirectMiddleware };
|
package/src/server/valkey.js
CHANGED
|
@@ -34,14 +34,14 @@ const selectDtoFactory = (payload, select) => {
|
|
|
34
34
|
const valkeyClientFactory = async (options) => {
|
|
35
35
|
const valkey = new Valkey({
|
|
36
36
|
// port: 6379,
|
|
37
|
-
// host: 'service
|
|
37
|
+
// host: 'valkey-service.default.svc.cluster.local',
|
|
38
38
|
port: options?.port ? options.port : undefined,
|
|
39
|
-
host: options?.
|
|
39
|
+
host: options?.host ? options.host : undefined,
|
|
40
40
|
retryStrategy: (attempt) => {
|
|
41
41
|
if (attempt === 1) {
|
|
42
42
|
valkey.disconnect();
|
|
43
43
|
valkeyEnabled = false;
|
|
44
|
-
logger.warn('Valkey service not enabled', { valkeyEnabled });
|
|
44
|
+
logger.warn('Valkey service not enabled', { ...options, valkeyEnabled });
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
47
|
return 1000; // 1 second interval attempt
|