underpost 2.8.78 → 2.8.82

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/.github/workflows/ghpkg.yml +23 -21
  2. package/.github/workflows/npmpkg.yml +16 -11
  3. package/.github/workflows/pwa-microservices-template.page.yml +12 -3
  4. package/.github/workflows/pwa-microservices-template.test.yml +20 -17
  5. package/.vscode/extensions.json +1 -2
  6. package/.vscode/settings.json +3 -0
  7. package/Dockerfile +14 -33
  8. package/README.md +25 -24
  9. package/bin/db.js +1 -0
  10. package/bin/deploy.js +91 -796
  11. package/bin/vs.js +10 -3
  12. package/cli.md +340 -191
  13. package/conf.js +4 -0
  14. package/docker-compose.yml +1 -1
  15. package/manifests/deployment/dd-template-development/deployment.yaml +167 -0
  16. package/manifests/deployment/dd-template-development/proxy.yaml +46 -0
  17. package/manifests/lxd/lxd-admin-profile.yaml +17 -0
  18. package/manifests/lxd/lxd-preseed.yaml +30 -0
  19. package/manifests/lxd/underpost-setup.sh +163 -0
  20. package/manifests/maas/device-scan.sh +43 -0
  21. package/manifests/maas/lxd-preseed.yaml +32 -0
  22. package/manifests/maas/maas-setup.sh +120 -0
  23. package/manifests/maas/nat-iptables.sh +26 -0
  24. package/manifests/mariadb/statefulset.yaml +2 -1
  25. package/manifests/mariadb/storage-class.yaml +10 -0
  26. package/manifests/mongodb-4.4/service-deployment.yaml +2 -2
  27. package/manifests/valkey/service.yaml +3 -9
  28. package/manifests/valkey/statefulset.yaml +10 -12
  29. package/package.json +1 -1
  30. package/src/cli/baremetal.js +1248 -0
  31. package/src/cli/cloud-init.js +528 -0
  32. package/src/cli/cluster.js +459 -232
  33. package/src/cli/deploy.js +34 -10
  34. package/src/cli/env.js +2 -2
  35. package/src/cli/image.js +57 -9
  36. package/src/cli/index.js +256 -218
  37. package/src/cli/lxd.js +380 -4
  38. package/src/index.js +40 -14
  39. package/src/runtime/lampp/Dockerfile +41 -47
  40. package/src/server/conf.js +58 -0
  41. package/src/server/logger.js +3 -3
  42. package/src/server/runtime.js +1 -6
  43. package/src/server/ssl.js +1 -12
  44. package/src/server/valkey.js +3 -3
  45. package/supervisord-openssh-server.conf +0 -5
package/src/cli/lxd.js CHANGED
@@ -1,16 +1,392 @@
1
- import { shellExec } from '../server/process.js';
1
+ import { getNpmRootPath } from '../server/conf.js';
2
+ import { getLocalIPv4Address } from '../server/dns.js';
3
+ import { pbcopy, shellExec } from '../server/process.js';
4
+ import fs from 'fs-extra';
2
5
 
6
+ /**
7
+ * @class UnderpostLxd
8
+ * @description Provides a set of static methods to interact with LXD,
9
+ * encapsulating common LXD operations for VM management and network testing.
10
+ */
3
11
  class UnderpostLxd {
4
12
  static API = {
5
- async callback(options = { init: false, reset: false, install: false }) {
13
+ /**
14
+ * @method callback
15
+ * @description Main entry point for LXD operations based on provided options.
16
+ * @param {object} options - Configuration options for LXD operations.
17
+ * @param {boolean} [options.init=false] - Initialize LXD.
18
+ * @param {boolean} [options.reset=false] - Reset LXD installation.
19
+ * @param {boolean} [options.dev=false] - Run in development mode (adjusts paths).
20
+ * @param {boolean} [options.install=false] - Install LXD snap.
21
+ * @param {boolean} [options.createVirtualNetwork=false] - Create default LXD bridge network (lxdbr0).
22
+ * @param {boolean} [options.createAdminProfile=false] - Create admin-profile for VMs.
23
+ * @param {boolean} [options.control=false] - Flag for control plane VM initialization.
24
+ * @param {boolean} [options.worker=false] - Flag for worker node VM initialization.
25
+ * @param {boolean} [options.k3s=false] - Flag to indicate K3s cluster type for VM initialization.
26
+ * @param {string} [options.initVm=''] - Initialize a specific VM.
27
+ * @param {string} [options.createVm=''] - Create a new VM with the given name.
28
+ * @param {string} [options.infoVm=''] - Display information about a specific VM.
29
+ * @param {string} [options.rootSize=''] - Root disk size for new VMs (e.g., '32GiB').
30
+ * @param {string} [options.joinNode=''] - Join a worker node to a control plane (format: 'workerName,controlName').
31
+ * @param {string} [options.expose=''] - Expose ports from a VM to the host (format: 'vmName:port1,port2').
32
+ * @param {string} [options.deleteExpose=''] - Delete exposed ports from a VM (format: 'vmName:port1,port2').
33
+ * @param {string} [options.test=''] - Test health, status and network connectivity for a VM.
34
+ * @param {string} [options.autoExposeK8sPorts=''] - Automatically expose common Kubernetes ports for the VM.
35
+ */
36
+ async callback(
37
+ options = {
38
+ init: false,
39
+ reset: false,
40
+ dev: false,
41
+ install: false,
42
+ createVirtualNetwork: false,
43
+ createAdminProfile: false,
44
+ control: false,
45
+ worker: false,
46
+ k3s: false,
47
+ initVm: '',
48
+ createVm: '',
49
+ infoVm: '',
50
+ rootSize: '',
51
+ joinNode: '',
52
+ expose: '',
53
+ deleteExpose: '',
54
+ test: '',
55
+ autoExposeK8sPorts: '',
56
+ },
57
+ ) {
58
+ const npmRoot = getNpmRootPath();
59
+ const underpostRoot = options?.dev === true ? '.' : `${npmRoot}/underpost`;
6
60
  if (options.reset === true) {
7
- shellExec(`sudo systemctl stop snap.lxd.daemon`);
8
- shellExec(`sudo snap remove lxd --purge`);
61
+ shellExec(`sudo systemctl stop snap.lxd.daemon || true`);
62
+ shellExec(`sudo snap remove lxd --purge || true`);
9
63
  }
10
64
  if (options.install === true) shellExec(`sudo snap install lxd`);
11
65
  if (options.init === true) {
12
66
  shellExec(`sudo systemctl start snap.lxd.daemon`);
13
67
  shellExec(`sudo systemctl status snap.lxd.daemon`);
68
+ const lxdPressedContent = fs
69
+ .readFileSync(`${underpostRoot}/manifests/lxd/lxd-preseed.yaml`, 'utf8')
70
+ .replaceAll(`127.0.0.1`, getLocalIPv4Address());
71
+ shellExec(`echo "${lxdPressedContent}" | lxd init --preseed`);
72
+ shellExec(`lxc cluster list`);
73
+ }
74
+ if (options.createVirtualNetwork === true) {
75
+ shellExec(`lxc network create lxdbr0 \
76
+ ipv4.address=10.250.250.1/24 \
77
+ ipv4.nat=true \
78
+ ipv4.dhcp=true \
79
+ ipv6.address=none`);
80
+ }
81
+ if (options.createAdminProfile === true) {
82
+ pbcopy(`lxc profile create admin-profile`);
83
+ shellExec(`cat ${underpostRoot}/manifests/lxd/lxd-admin-profile.yaml | lxc profile edit admin-profile`);
84
+ shellExec(`lxc profile show admin-profile`);
85
+ }
86
+ if (options.createVm && typeof options.createVm === 'string') {
87
+ pbcopy(
88
+ `lxc launch images:rockylinux/9 ${
89
+ options.createVm
90
+ } --vm --target lxd-node1 -c limits.cpu=2 -c limits.memory=4GB --profile admin-profile -d root,size=${
91
+ options.rootSize && typeof options.rootSize === 'string' ? options.rootSize + 'GiB' : '32GiB'
92
+ }`,
93
+ );
94
+ }
95
+ if (options.initVm && typeof options.initVm === 'string') {
96
+ let flag = '';
97
+ if (options.control === true) {
98
+ if (options.k3s === true) {
99
+ flag = ' -s -- --k3s';
100
+ } else {
101
+ // Default to kubeadm if not K3s
102
+ flag = ' -s -- --kubeadm';
103
+ }
104
+ shellExec(`lxc exec ${options.initVm} -- bash -c 'mkdir -p /home/dd/engine'`);
105
+ shellExec(`lxc file push /home/dd/engine/engine-private ${options.initVm}/home/dd/engine --recursive`);
106
+ shellExec(`lxc file push /home/dd/engine/manifests ${options.initVm}/home/dd/engine --recursive`);
107
+ } else if (options.worker == true) {
108
+ if (options.k3s === true) {
109
+ flag = ' -s -- --worker --k3s';
110
+ } else {
111
+ // Default to kubeadm worker
112
+ flag = ' -s -- --worker';
113
+ }
114
+ }
115
+ console.log(`Executing underpost-setup.sh on VM: ${options.initVm}`);
116
+ shellExec(`cat ${underpostRoot}/manifests/lxd/underpost-setup.sh | lxc exec ${options.initVm} -- bash${flag}`);
117
+ console.log(`underpost-setup.sh execution completed on VM: ${options.initVm}`);
118
+ }
119
+ // --- Automatic Kubernetes Port Exposure ---
120
+ if (options.autoExposeK8sPorts && typeof options.autoExposeK8sPorts === 'string') {
121
+ console.log(`Automatically exposing Kubernetes ports for VM: ${options.autoExposeK8sPorts}`);
122
+ const vmName = options.autoExposeK8sPorts;
123
+ const hostIp = getLocalIPv4Address();
124
+ let vmIp = '';
125
+ let retries = 0;
126
+ const maxRetries = 10;
127
+ const delayMs = 5000; // 5 seconds
128
+
129
+ // Wait for VM to get an IP address
130
+ while (!vmIp && retries < maxRetries) {
131
+ try {
132
+ console.log(`Attempting to get IPv4 address for ${vmName} (Attempt ${retries + 1}/${maxRetries})...`);
133
+ vmIp = shellExec(
134
+ `lxc list ${vmName} --format json | jq -r '.[0].state.network.enp5s0.addresses[] | select(.family=="inet") | .address'`,
135
+ { stdout: true },
136
+ ).trim();
137
+ if (vmIp) {
138
+ console.log(`IPv4 address found for ${vmName}: ${vmIp}`);
139
+ } else {
140
+ console.log(`IPv4 address not yet available for ${vmName}. Retrying in ${delayMs / 1000} seconds...`);
141
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
142
+ }
143
+ } catch (error) {
144
+ console.error(`Error getting IPv4 address for exposure: ${error.message}`);
145
+ console.log(`Retrying in ${delayMs / 1000} seconds...`);
146
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
147
+ }
148
+ retries++;
149
+ }
150
+
151
+ if (!vmIp) {
152
+ console.error(`Failed to get VM IP for ${vmName} after ${maxRetries} attempts. Cannot expose ports.`);
153
+ return;
154
+ }
155
+
156
+ let portsToExpose = [];
157
+ if (options.control === true) {
158
+ // Kubernetes API Server (Kubeadm and K3s both use 6443 by default)
159
+ portsToExpose.push('6443');
160
+ // Standard HTTP/HTTPS for Ingress if deployed
161
+ portsToExpose.push('80');
162
+ portsToExpose.push('443');
163
+ }
164
+ // Add common NodePorts if needed, or rely on explicit 'expose'
165
+ portsToExpose.push('30000'); // Example NodePort
166
+ portsToExpose.push('30001'); // Example NodePort
167
+ portsToExpose.push('30002'); // Example NodePort
168
+
169
+ const protocols = ['tcp']; // Most K8s services are TCP, UDP for some like DNS
170
+
171
+ for (const port of portsToExpose) {
172
+ for (const protocol of protocols) {
173
+ const deviceName = `${vmName}-${protocol}-port-${port}`;
174
+ try {
175
+ // Remove existing device first to avoid conflicts if re-running
176
+ shellExec(`lxc config device remove ${vmName} ${deviceName} || true`);
177
+ shellExec(
178
+ `lxc config device add ${vmName} ${deviceName} proxy listen=${protocol}:${hostIp}:${port} connect=${protocol}:${vmIp}:${port} nat=true`,
179
+ );
180
+ console.log(`Exposed ${protocol}:${hostIp}:${port} -> ${vmIp}:${port} for ${vmName}`);
181
+ } catch (error) {
182
+ console.error(`Failed to expose port ${port} for ${vmName}: ${error.message}`);
183
+ }
184
+ }
185
+ }
186
+ }
187
+ if (options.joinNode && typeof options.joinNode === 'string') {
188
+ const [workerNode, controlNode] = options.joinNode.split(',');
189
+ // Determine if it's a Kubeadm or K3s join
190
+ const isK3sJoin = options.k3s === true;
191
+
192
+ if (isK3sJoin) {
193
+ console.log(`Attempting to join K3s worker node ${workerNode} to control plane ${controlNode}`);
194
+ // Get K3s token from control plane
195
+ const k3sToken = shellExec(
196
+ `lxc exec ${controlNode} -- bash -c 'sudo cat /var/lib/rancher/k3s/server/node-token'`,
197
+ { stdout: true },
198
+ ).trim();
199
+ // Get control plane IP
200
+ const controlPlaneIp = shellExec(
201
+ `lxc list ${controlNode} --format json | jq -r '.[0].state.network.enp5s0.addresses[] | select(.family=="inet") | .address'`,
202
+ { stdout: true },
203
+ ).trim();
204
+
205
+ if (!k3sToken || !controlPlaneIp) {
206
+ console.error(`Failed to get K3s token or control plane IP. Cannot join worker.`);
207
+ return;
208
+ }
209
+ const k3sJoinCommand = `K3S_URL=https://${controlPlaneIp}:6443 K3S_TOKEN=${k3sToken} curl -sfL https://get.k3s.io | sh -`;
210
+ shellExec(`lxc exec ${workerNode} -- bash -c '${k3sJoinCommand}'`);
211
+ console.log(`K3s worker node ${workerNode} join command executed.`);
212
+ } else {
213
+ // Kubeadm join
214
+ console.log(`Attempting to join Kubeadm worker node ${workerNode} to control plane ${controlNode}`);
215
+ const token = shellExec(
216
+ `echo "$(lxc exec ${controlNode} -- bash -c 'sudo kubeadm token create --print-join-command')"`,
217
+ { stdout: true },
218
+ );
219
+ shellExec(`lxc exec ${workerNode} -- bash -c '${token}'`);
220
+ console.log(`Kubeadm worker node ${workerNode} join command executed.`);
221
+ }
222
+ }
223
+ if (options.infoVm && typeof options.infoVm === 'string') {
224
+ shellExec(`lxc config show ${options.infoVm}`);
225
+ shellExec(`lxc info --show-log ${options.infoVm}`);
226
+ shellExec(`lxc info ${options.infoVm}`);
227
+ shellExec(`lxc list ${options.infoVm}`);
228
+ }
229
+ if (options.expose && typeof options.expose === 'string') {
230
+ const [vmName, ports] = options.expose.split(':');
231
+ console.log({ vmName, ports });
232
+ const protocols = ['tcp']; // udp
233
+ const hostIp = getLocalIPv4Address();
234
+ const vmIp = shellExec(
235
+ `lxc list ${vmName} --format json | jq -r '.[0].state.network.enp5s0.addresses[] | select(.family=="inet") | .address'`,
236
+ { stdout: true },
237
+ ).trim();
238
+ if (!vmIp) {
239
+ console.error(`Could not get VM IP for ${vmName}. Cannot expose ports.`);
240
+ return;
241
+ }
242
+ for (const port of ports.split(',')) {
243
+ for (const protocol of protocols) {
244
+ const deviceName = `${vmName}-${protocol}-port-${port}`;
245
+ shellExec(`lxc config device remove ${vmName} ${deviceName} || true`); // Use || true to prevent error if device doesn't exist
246
+ shellExec(
247
+ `lxc config device add ${vmName} ${deviceName} proxy listen=${protocol}:${hostIp}:${port} connect=${protocol}:${vmIp}:${port} nat=true`,
248
+ );
249
+ console.log(`Manually exposed ${protocol}:${hostIp}:${port} -> ${vmIp}:${port} for ${vmName}`);
250
+ }
251
+ }
252
+ }
253
+ if (options.deleteExpose && typeof options.deleteExpose === 'string') {
254
+ const [controlNode, ports] = options.deleteExpose.split(':');
255
+ console.log({ controlNode, ports });
256
+ const protocols = ['tcp']; // udp
257
+ for (const port of ports.split(',')) {
258
+ for (const protocol of protocols) {
259
+ shellExec(`lxc config device remove ${controlNode} ${controlNode}-${protocol}-port-${port}`);
260
+ }
261
+ }
262
+ }
263
+
264
+ if (options.test && typeof options.test === 'string') {
265
+ const vmName = options.test;
266
+ console.log(`Starting comprehensive test for VM: ${vmName}`);
267
+
268
+ // 1. Monitor for IPv4 address
269
+ let vmIp = '';
270
+ let retries = 0;
271
+ const maxRetries = 10;
272
+ const delayMs = 5000; // 5 seconds
273
+
274
+ while (!vmIp && retries < maxRetries) {
275
+ try {
276
+ console.log(`Attempting to get IPv4 address for ${vmName} (Attempt ${retries + 1}/${maxRetries})...`);
277
+ vmIp = shellExec(
278
+ `lxc list ${vmName} --format json | jq -r '.[0].state.network.enp5s0.addresses[] | select(.family=="inet") | .address'`,
279
+ { stdout: true },
280
+ ).trim();
281
+ if (vmIp) {
282
+ console.log(`IPv4 address found for ${vmName}: ${vmIp}`);
283
+ } else {
284
+ console.log(`IPv4 address not yet available for ${vmName}. Retrying in ${delayMs / 1000} seconds...`);
285
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
286
+ }
287
+ } catch (error) {
288
+ console.error(`Error getting IPv4 address: ${error.message}`);
289
+ console.log(`Retrying in ${delayMs / 1000} seconds...`);
290
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
291
+ }
292
+ retries++;
293
+ }
294
+
295
+ if (!vmIp) {
296
+ console.error(`Failed to get IPv4 address for ${vmName} after ${maxRetries} attempts. Aborting tests.`);
297
+ return;
298
+ }
299
+
300
+ // 2. Iteratively check connection to google.com
301
+ let connectedToGoogle = false;
302
+ retries = 0;
303
+ while (!connectedToGoogle && retries < maxRetries) {
304
+ try {
305
+ console.log(`Checking connectivity to google.com from ${vmName} (Attempt ${retries + 1}/${maxRetries})...`);
306
+ const curlOutput = shellExec(
307
+ `lxc exec ${vmName} -- bash -c 'curl -s -o /dev/null -w "%{http_code}" http://google.com'`,
308
+ { stdout: true },
309
+ );
310
+ if (curlOutput.startsWith('2') || curlOutput.startsWith('3')) {
311
+ console.log(`Successfully connected to google.com from ${vmName}.`);
312
+ connectedToGoogle = true;
313
+ } else {
314
+ console.log(`Connectivity to google.com not yet verified. Retrying in ${delayMs / 1000} seconds...`);
315
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
316
+ }
317
+ } catch (error) {
318
+ console.error(`Error checking connectivity to google.com: ${error.message}`);
319
+ console.log(`Retrying in ${delayMs / 1000} seconds...`);
320
+ await new Promise((resolve) => setTimeout(resolve, delayMs));
321
+ }
322
+ retries++;
323
+ }
324
+
325
+ if (!connectedToGoogle) {
326
+ console.error(
327
+ `Failed to connect to google.com from ${vmName} after ${maxRetries} attempts. Aborting further tests.`,
328
+ );
329
+ return;
330
+ }
331
+
332
+ // 3. Check other connectivity, network, and VM health parameters
333
+ console.log(`\n--- Comprehensive Health Report for ${vmName} ---`);
334
+
335
+ // VM Status
336
+ console.log('\n--- VM Status ---');
337
+ try {
338
+ const vmStatus = shellExec(`lxc list ${vmName} --format json`, { stdout: true, silent: true });
339
+ console.log(JSON.stringify(JSON.parse(vmStatus), null, 2));
340
+ } catch (error) {
341
+ console.error(`Error getting VM status: ${error.message}`);
342
+ }
343
+
344
+ // CPU Usage
345
+ console.log('\n--- CPU Usage ---');
346
+ try {
347
+ const cpuUsage = shellExec(`lxc exec ${vmName} -- bash -c 'top -bn1 | grep "Cpu(s)"'`, { stdout: true });
348
+ console.log(cpuUsage.trim());
349
+ } catch (error) {
350
+ console.error(`Error getting CPU usage: ${error.message}`);
351
+ }
352
+
353
+ // Memory Usage
354
+ console.log('\n--- Memory Usage ---');
355
+ try {
356
+ const memoryUsage = shellExec(`lxc exec ${vmName} -- bash -c 'free -m'`, { stdout: true });
357
+ console.log(memoryUsage.trim());
358
+ } catch (error) {
359
+ console.error(`Error getting memory usage: ${error.message}`);
360
+ }
361
+
362
+ // Disk Usage
363
+ console.log('\n--- Disk Usage (Root Partition) ---');
364
+ try {
365
+ const diskUsage = shellExec(`lxc exec ${vmName} -- bash -c 'df -h /'`, { stdout: true });
366
+ console.log(diskUsage.trim());
367
+ } catch (error) {
368
+ console.error(`Error getting disk usage: ${error.message}`);
369
+ }
370
+
371
+ // Network Interface Status
372
+ console.log('\n--- Network Interface Status (ip a) ---');
373
+ try {
374
+ const ipA = shellExec(`lxc exec ${vmName} -- bash -c 'ip a'`, { stdout: true });
375
+ console.log(ipA.trim());
376
+ } catch (error) {
377
+ console.error(`Error getting network interface status: ${error.message}`);
378
+ }
379
+
380
+ // DNS Resolution (resolv.conf)
381
+ console.log('\n--- DNS Configuration (/etc/resolv.conf) ---');
382
+ try {
383
+ const resolvConf = shellExec(`lxc exec ${vmName} -- bash -c 'cat /etc/resolv.conf'`, { stdout: true });
384
+ console.log(resolvConf.trim());
385
+ } catch (error) {
386
+ console.error(`Error getting DNS configuration: ${error.message}`);
387
+ }
388
+
389
+ console.log(`\nComprehensive test for VM: ${vmName} completed.`);
14
390
  }
15
391
  },
16
392
  };
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';
@@ -11,6 +13,7 @@ import UnderpostDeploy from './cli/deploy.js';
11
13
  import UnderpostRootEnv from './cli/env.js';
12
14
  import UnderpostFileStorage from './cli/fs.js';
13
15
  import UnderpostImage from './cli/image.js';
16
+ import UnderpostLxd from './cli/lxd.js';
14
17
  import UnderpostMonitor from './cli/monitor.js';
15
18
  import UnderpostRepository from './cli/repository.js';
16
19
  import UnderpostScript from './cli/script.js';
@@ -30,98 +33,121 @@ class Underpost {
30
33
  * @type {String}
31
34
  * @memberof Underpost
32
35
  */
33
- static version = 'v2.8.78';
36
+ static version = 'v2.8.82';
34
37
  /**
35
38
  * Repository cli API
36
39
  * @static
37
- * @type {UnderpostRepository.API}
40
+ * @type {UnderpostRepository}
38
41
  * @memberof Underpost
39
42
  */
40
43
  static repo = UnderpostRepository.API;
41
44
  /**
42
45
  * Root Env cli API
43
46
  * @static
44
- * @type {UnderpostRootEnv.API}
47
+ * @type {UnderpostRootEnv}
45
48
  * @memberof Underpost
46
49
  */
47
50
  static env = UnderpostRootEnv.API;
48
51
  /**
49
52
  * Test cli API
50
53
  * @static
51
- * @type {UnderpostTest.API}
54
+ * @type {UnderpostTest}
52
55
  * @memberof Underpost
53
56
  */
54
57
  static test = UnderpostTest.API;
55
58
  /**
56
59
  * Underpost Start Up cli API
57
60
  * @static
58
- * @type {UnderpostStartUp.API}
61
+ * @type {UnderpostStartUp}
59
62
  * @memberof Underpost
60
63
  */
61
64
  static start = UnderpostStartUp.API;
62
65
  /**
63
66
  * Cluster cli API
64
67
  * @static
65
- * @type {UnderpostCluster.API}
68
+ * @type {UnderpostCluster}
66
69
  * @memberof Underpost
67
70
  */
68
71
  static cluster = UnderpostCluster.API;
69
72
  /**
70
73
  * Image cli API
71
74
  * @static
72
- * @type {UnderpostImage.API}
75
+ * @type {UnderpostImage}
73
76
  * @memberof Underpost
74
77
  */
75
78
  static image = UnderpostImage.API;
76
79
  /**
77
80
  * Secrets cli API
78
81
  * @static
79
- * @type {UnderpostSecret.API}
82
+ * @type {UnderpostSecret}
80
83
  * @memberof Underpost
81
84
  */
82
85
  static secret = UnderpostSecret.API;
83
86
  /**
84
87
  * Scripts cli API
85
88
  * @static
86
- * @type {UnderpostScript.API}
89
+ * @type {UnderpostScript}
87
90
  * @memberof Underpost
88
91
  */
89
92
  static script = UnderpostScript.API;
90
93
  /**
91
94
  * Database cli API
92
95
  * @static
93
- * @type {UnderpostDB.API}
96
+ * @type {UnderpostDB}
94
97
  * @memberof Underpost
95
98
  */
96
99
  static db = UnderpostDB.API;
97
100
  /**
98
101
  * Deployment cli API
99
102
  * @static
100
- * @type {UnderpostDeploy.API}
103
+ * @type {UnderpostDeploy}
101
104
  * @memberof Underpost
102
105
  */
103
106
  static deploy = UnderpostDeploy.API;
104
107
  /**
105
108
  * Cron cli API
106
109
  * @static
107
- * @type {UnderpostCron.API}
110
+ * @type {UnderpostCron}
108
111
  * @memberof Underpost
109
112
  */
110
113
  static cron = UnderpostCron.API;
111
114
  /**
112
115
  * File Storage cli API
113
116
  * @static
114
- * @type {UnderpostFileStorage.API}
117
+ * @type {UnderpostFileStorage}
115
118
  * @memberof Underpost
116
119
  */
117
120
  static fs = UnderpostFileStorage.API;
118
121
  /**
119
122
  * Monitor cli API
120
123
  * @static
121
- * @type {UnderpostMonitor.API}
124
+ * @type {UnderpostMonitor}
122
125
  * @memberof Underpost
123
126
  */
124
127
  static monitor = UnderpostMonitor.API;
128
+ /**
129
+ * LXD cli API
130
+ * @static
131
+ * @type {UnderpostLxd}
132
+ * @memberof Underpost
133
+ */
134
+ static lxd = UnderpostLxd.API;
135
+
136
+ /**
137
+ * Cloud Init cli API
138
+ * @static
139
+ * @type {UnderpostCloudInit}
140
+ * @memberof Underpost
141
+ */
142
+ static cloudInit = UnderpostCloudInit.API;
143
+
144
+ /**
145
+ * Baremetal cli API
146
+ * @static
147
+ * @type {UnderpostBaremetal}
148
+ * @memberof Underpost
149
+ */
150
+ static baremetal = UnderpostBaremetal.API;
125
151
  }
126
152
 
127
153
  const up = Underpost;
@@ -1,65 +1,59 @@
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
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
- RUN bash -c './xampp-linux-installer.run'
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
- # 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
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'/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
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. 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
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
- # 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
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