underpost 2.8.846 → 2.8.847
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/README.md +7 -2
- package/bin/build.js +7 -1
- package/bin/deploy.js +7 -1
- package/cli.md +16 -1
- package/docker-compose.yml +1 -1
- package/manifests/deployment/dd-template-development/deployment.yaml +2 -2
- package/package.json +1 -1
- package/src/cli/cluster.js +6 -0
- package/src/cli/deploy.js +2 -1
- package/src/cli/index.js +7 -0
- package/src/cli/run.js +2 -1
- package/src/cli/ssh.js +32 -0
- package/src/client/components/core/CssCore.js +2 -3
- package/src/client/components/core/Modal.js +89 -4
- package/src/index.js +9 -1
package/README.md
CHANGED
|
@@ -39,12 +39,14 @@ template
|
|
|
39
39
|
|
|
40
40
|
|
|
41
41
|
|
|
42
|
+
|
|
43
|
+
|
|
42
44
|
|
|
43
45
|
|
|
44
46
|
<!-- badges -->
|
|
45
47
|
|
|
46
48
|
|
|
47
|
-
[](https://github.com/underpostnet/engine/actions/workflows/docker-image.yml) [](https://github.com/underpostnet/engine/actions/workflows/coverall.yml) [](https://www.npmjs.com/package/underpost) [](https://github.com/underpostnet/engine/actions/workflows/docker-image.yml) [](https://github.com/underpostnet/engine/actions/workflows/coverall.yml) [](https://www.npmjs.com/package/underpost) [](https://socket.dev/npm/package/underpost/overview/2.8.847) [](https://coveralls.io/github/underpostnet/engine?branch=master) [](https://www.npmjs.org/package/underpost) [](https://www.npmjs.com/package/underpost)
|
|
48
50
|
|
|
49
51
|
|
|
50
52
|
<!-- end-badges -->
|
|
@@ -66,6 +68,8 @@ template
|
|
|
66
68
|
|
|
67
69
|
|
|
68
70
|
|
|
71
|
+
|
|
72
|
+
|
|
69
73
|
|
|
70
74
|
|
|
71
75
|
</div>
|
|
@@ -112,7 +116,7 @@ Run dev client server
|
|
|
112
116
|
npm run dev
|
|
113
117
|
```
|
|
114
118
|
<!-- -->
|
|
115
|
-
## underpost ci/cd cli v2.8.
|
|
119
|
+
## underpost ci/cd cli v2.8.847
|
|
116
120
|
|
|
117
121
|
### Usage: `underpost [options] [command]`
|
|
118
122
|
```
|
|
@@ -142,6 +146,7 @@ Commands:
|
|
|
142
146
|
fs [options] [path] Manages file storage, defaulting to file upload operations.
|
|
143
147
|
test [options] [deploy-list] Manages and runs tests, defaulting to the current Underpost default test suite.
|
|
144
148
|
monitor [options] <deploy-id> [env] Manages health server monitoring for specified deployments.
|
|
149
|
+
ssh [options] Import and start ssh server and client based on current default deployment ID.
|
|
145
150
|
run [options] <runner-id> [path] Runs a script from the specified path.
|
|
146
151
|
lxd [options] Manages LXD containers and virtual machines.
|
|
147
152
|
baremetal [options] [workflow-id] [hostname] [ip-address] Manages baremetal server operations, including installation, database setup, commissioning, and user management.
|
package/bin/build.js
CHANGED
|
@@ -53,7 +53,9 @@ if (process.argv.includes('conf')) {
|
|
|
53
53
|
fs.removeSync(toPath);
|
|
54
54
|
fs.mkdirSync(toPath, { recursive: true });
|
|
55
55
|
fs.copySync(`./engine-private/conf/${_confName}`, toPath);
|
|
56
|
-
if (fs.existsSync(
|
|
56
|
+
if (process.argv.includes('remove-replica') && fs.existsSync(`../${privateRepoName}/replica`)) {
|
|
57
|
+
fs.removeSync(`../${privateRepoName}/replica`);
|
|
58
|
+
} else if (fs.existsSync(`./engine-private/replica`)) {
|
|
57
59
|
const replicas = await fs.readdir(`./engine-private/replica`);
|
|
58
60
|
for (const replica of replicas)
|
|
59
61
|
if (replica.match(_confName))
|
|
@@ -187,4 +189,8 @@ const { DefaultConf } = await import(`../conf.${confName}.js`);
|
|
|
187
189
|
|
|
188
190
|
fs.copyFileSync(`./.github/workflows/${repoName}.ci.yml`, `${basePath}/.github/workflows/${repoName}.ci.yml`);
|
|
189
191
|
fs.copyFileSync(`./.github/workflows/${repoName}.cd.yml`, `${basePath}/.github/workflows/${repoName}.cd.yml`);
|
|
192
|
+
|
|
193
|
+
if (fs.existsSync(`./src/ws/${confName.split('-')[1]}`)) {
|
|
194
|
+
fs.copySync(`./src/ws/${confName.split('-')[1]}`, `${basePath}/src/ws/${confName.split('-')[1]}`);
|
|
195
|
+
}
|
|
190
196
|
}
|
package/bin/deploy.js
CHANGED
|
@@ -835,6 +835,12 @@ ${shellExec(`git log | grep Author: | sort -u`, { stdout: true }).split(`\n`).jo
|
|
|
835
835
|
}
|
|
836
836
|
|
|
837
837
|
case 'ssh': {
|
|
838
|
+
// only import + start
|
|
839
|
+
// node bin/deploy ssh root@<host> <password> import
|
|
840
|
+
|
|
841
|
+
// generate + import + start
|
|
842
|
+
// node bin/deploy ssh root@<host> <password>
|
|
843
|
+
|
|
838
844
|
const host = process.argv[3] ?? `root@${await ip.public.ipv4()}`;
|
|
839
845
|
const domain = host.split('@')[1];
|
|
840
846
|
const user = 'root'; // host.split('@')[0];
|
|
@@ -907,7 +913,7 @@ EOF`);
|
|
|
907
913
|
// shellExec(`sudo echo "" > ~/.ssh/known_hosts`);
|
|
908
914
|
|
|
909
915
|
// ssh-copy-id -i ~/.ssh/id_rsa.pub -p <port_number> <username>@<host>
|
|
910
|
-
shellExec(`ssh-copy-id -i ~/.ssh/id_rsa.pub -p ${port} ${host}`);
|
|
916
|
+
// shellExec(`ssh-copy-id -i ~/.ssh/id_rsa.pub -p ${port} ${host}`);
|
|
911
917
|
// debug:
|
|
912
918
|
// shellExec(`ssh -vvv ${host}`);
|
|
913
919
|
|
package/cli.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
## underpost ci/cd cli v2.8.
|
|
1
|
+
## underpost ci/cd cli v2.8.847
|
|
2
2
|
|
|
3
3
|
### Usage: `underpost [options] [command]`
|
|
4
4
|
```
|
|
@@ -28,6 +28,7 @@ Commands:
|
|
|
28
28
|
fs [options] [path] Manages file storage, defaulting to file upload operations.
|
|
29
29
|
test [options] [deploy-list] Manages and runs tests, defaulting to the current Underpost default test suite.
|
|
30
30
|
monitor [options] <deploy-id> [env] Manages health server monitoring for specified deployments.
|
|
31
|
+
ssh [options] Import and start ssh server and client based on current default deployment ID.
|
|
31
32
|
run [options] <runner-id> [path] Runs a script from the specified path.
|
|
32
33
|
lxd [options] Manages LXD containers and virtual machines.
|
|
33
34
|
baremetal [options] [workflow-id] [hostname] [ip-address] Manages baremetal server operations, including installation, database setup, commissioning, and user management.
|
|
@@ -552,6 +553,20 @@ Options:
|
|
|
552
553
|
```
|
|
553
554
|
|
|
554
555
|
|
|
556
|
+
### `ssh` :
|
|
557
|
+
```
|
|
558
|
+
Usage: underpost ssh [options]
|
|
559
|
+
|
|
560
|
+
Import and start ssh server and client based on current default deployment ID.
|
|
561
|
+
|
|
562
|
+
Options:
|
|
563
|
+
--generate Generates new ssh credential and stores it in current private
|
|
564
|
+
keys file storage.
|
|
565
|
+
-h, --help display help for command
|
|
566
|
+
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
|
|
555
570
|
### `run` :
|
|
556
571
|
```
|
|
557
572
|
Usage: underpost run [options] <runner-id> [path]
|
package/docker-compose.yml
CHANGED
|
@@ -17,7 +17,7 @@ spec:
|
|
|
17
17
|
spec:
|
|
18
18
|
containers:
|
|
19
19
|
- name: dd-template-development-blue
|
|
20
|
-
image: localhost/rockylinux9-underpost:v2.8.
|
|
20
|
+
image: localhost/rockylinux9-underpost:v2.8.847
|
|
21
21
|
# resources:
|
|
22
22
|
# requests:
|
|
23
23
|
# memory: "124Ki"
|
|
@@ -100,7 +100,7 @@ spec:
|
|
|
100
100
|
spec:
|
|
101
101
|
containers:
|
|
102
102
|
- name: dd-template-development-green
|
|
103
|
-
image: localhost/rockylinux9-underpost:v2.8.
|
|
103
|
+
image: localhost/rockylinux9-underpost:v2.8.847
|
|
104
104
|
# resources:
|
|
105
105
|
# requests:
|
|
106
106
|
# memory: "124Ki"
|
package/package.json
CHANGED
package/src/cli/cluster.js
CHANGED
|
@@ -476,6 +476,12 @@ net.bridge.bridge-nf-call-arptables = 1
|
|
|
476
476
|
net.ipv4.ip_forward = 1' | sudo tee ${iptableConfPath}`,
|
|
477
477
|
{ silent: true },
|
|
478
478
|
);
|
|
479
|
+
|
|
480
|
+
// Increase inotify limits
|
|
481
|
+
shellExec(`sudo sysctl -w fs.inotify.max_user_watches=2099999999`);
|
|
482
|
+
shellExec(`sudo sysctl -w fs.inotify.max_user_instances=2099999999`);
|
|
483
|
+
shellExec(`sudo sysctl -w fs.inotify.max_queued_events=2099999999`);
|
|
484
|
+
|
|
479
485
|
// shellExec(`sudo sysctl --system`); // Apply sysctl changes immediately
|
|
480
486
|
// Apply NAT iptables rules.
|
|
481
487
|
shellExec(`${underpostRoot}/manifests/maas/nat-iptables.sh`, { silent: true });
|
package/src/cli/deploy.js
CHANGED
|
@@ -528,13 +528,14 @@ node bin/deploy build-full-client ${deployId}
|
|
|
528
528
|
}).trim(),
|
|
529
529
|
);
|
|
530
530
|
},
|
|
531
|
-
checkDeploymentReadyStatus(deployId, env, traffic) {
|
|
531
|
+
checkDeploymentReadyStatus(deployId, env, traffic, ignoresNames = []) {
|
|
532
532
|
const cmd = `underpost config get container-status`;
|
|
533
533
|
const pods = UnderpostDeploy.API.get(`${deployId}-${env}-${traffic}`);
|
|
534
534
|
const readyPods = [];
|
|
535
535
|
const notReadyPods = [];
|
|
536
536
|
for (const pod of pods) {
|
|
537
537
|
const { NAME } = pod;
|
|
538
|
+
if (ignoresNames && ignoresNames.find((t) => NAME.trim().toLowerCase().match(t.trim().toLowerCase()))) continue;
|
|
538
539
|
if (
|
|
539
540
|
shellExec(`sudo kubectl exec -i ${NAME} -- sh -c "${cmd}"`, { stdout: true }).match(
|
|
540
541
|
`${deployId}-${env}-running-deployment`,
|
package/src/cli/index.js
CHANGED
|
@@ -316,6 +316,13 @@ program
|
|
|
316
316
|
.description('Manages health server monitoring for specified deployments.')
|
|
317
317
|
.action(Underpost.monitor.callback);
|
|
318
318
|
|
|
319
|
+
// 'ssh' command: SSH management
|
|
320
|
+
program
|
|
321
|
+
.command('ssh')
|
|
322
|
+
.option('--generate', 'Generates new ssh credential and stores it in current private keys file storage.')
|
|
323
|
+
.description('Import and start ssh server and client based on current default deployment ID.')
|
|
324
|
+
.action(Underpost.ssh.callback);
|
|
325
|
+
|
|
319
326
|
// 'run' command: Run a script
|
|
320
327
|
program
|
|
321
328
|
.command('run')
|
package/src/cli/run.js
CHANGED
|
@@ -206,12 +206,13 @@ class UnderpostRun {
|
|
|
206
206
|
const currentTraffic = UnderpostDeploy.API.getCurrentTraffic(deployId);
|
|
207
207
|
const targetTraffic = currentTraffic === 'blue' ? 'green' : 'blue';
|
|
208
208
|
const env = 'production';
|
|
209
|
+
const ignorePods = UnderpostDeploy.API.get(`${deployId}-${env}-${targetTraffic}`).map((p) => p.NAME);
|
|
209
210
|
shellExec(`sudo kubectl rollout restart deployment/${deployId}-${env}-${targetTraffic}`);
|
|
210
211
|
|
|
211
212
|
let secondsElapsed = 0;
|
|
212
213
|
logger.info('Deployment init', { deployId, env, targetTraffic });
|
|
213
214
|
|
|
214
|
-
while (!UnderpostDeploy.API.checkDeploymentReadyStatus(deployId, env, targetTraffic).ready) {
|
|
215
|
+
while (!UnderpostDeploy.API.checkDeploymentReadyStatus(deployId, env, targetTraffic, ignorePods).ready) {
|
|
215
216
|
await timer(1000);
|
|
216
217
|
secondsElapsed++;
|
|
217
218
|
logger.info(`Deployment in progress, seconds elapsed: ${secondsElapsed}`);
|
package/src/cli/ssh.js
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { getNpmRootPath } from '../server/conf.js';
|
|
2
|
+
import { shellExec } from '../server/process.js';
|
|
3
|
+
|
|
4
|
+
class UnderpostSSH {
|
|
5
|
+
static API = {
|
|
6
|
+
/**
|
|
7
|
+
* @method callback
|
|
8
|
+
* @param {object} options
|
|
9
|
+
* @param {boolean} options.generate - Generates new ssh credential and stores it in current private keys file storage.
|
|
10
|
+
* @description Import and start ssh server and client based on current default deployment ID.
|
|
11
|
+
*/
|
|
12
|
+
callback: async (
|
|
13
|
+
options = {
|
|
14
|
+
generate: false,
|
|
15
|
+
},
|
|
16
|
+
) => {
|
|
17
|
+
// only import + start
|
|
18
|
+
// node bin/deploy ssh root@<host> <password> import
|
|
19
|
+
|
|
20
|
+
// generate + import + start
|
|
21
|
+
// node bin/deploy ssh root@<host> <password>
|
|
22
|
+
|
|
23
|
+
shellExec(
|
|
24
|
+
`node bin/deploy ssh root@${process.env.DEFAULT_DEPLOY_HOST} ${process.env.DEFAULT_DEPLOY_PASSWORD ?? `''`}${
|
|
25
|
+
options.generate === true ? '' : ' import'
|
|
26
|
+
}`,
|
|
27
|
+
);
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export default UnderpostSSH;
|
|
@@ -17,8 +17,8 @@ const CssCommonCore = async () => {
|
|
|
17
17
|
await AgGrid.RenderStyle();
|
|
18
18
|
return html`<style>
|
|
19
19
|
.top-bar-app-icon {
|
|
20
|
-
width:
|
|
21
|
-
height:
|
|
20
|
+
width: 40px;
|
|
21
|
+
height: 40px;
|
|
22
22
|
}
|
|
23
23
|
.mini-title {
|
|
24
24
|
font-size: 15px;
|
|
@@ -51,7 +51,6 @@ const CssCommonCore = async () => {
|
|
|
51
51
|
cursor: grabbing !important;
|
|
52
52
|
}
|
|
53
53
|
.btn-label-content {
|
|
54
|
-
height: 100%;
|
|
55
54
|
top: 15px;
|
|
56
55
|
}
|
|
57
56
|
.badge {
|
|
@@ -139,6 +139,71 @@ const Modal = {
|
|
|
139
139
|
case 'slide-menu-right':
|
|
140
140
|
case 'slide-menu-left':
|
|
141
141
|
(async () => {
|
|
142
|
+
if (!options.slideMenuTopBarBannerFix) {
|
|
143
|
+
options.slideMenuTopBarBannerFix = async () => {
|
|
144
|
+
let style = html``;
|
|
145
|
+
if (options.barMode === 'top-bottom-bar') {
|
|
146
|
+
style = html`<style>
|
|
147
|
+
.default-slide-menu-top-bar-fix-logo-container {
|
|
148
|
+
width: 50px;
|
|
149
|
+
height: 50px;
|
|
150
|
+
}
|
|
151
|
+
.default-slide-menu-top-bar-fix-logo {
|
|
152
|
+
width: 40px;
|
|
153
|
+
height: 40px;
|
|
154
|
+
padding: 5px;
|
|
155
|
+
}
|
|
156
|
+
.default-slide-menu-top-bar-fix-title-container-text {
|
|
157
|
+
font-size: 26px;
|
|
158
|
+
top: 8px;
|
|
159
|
+
color: ${darkTheme ? '#ffffff' : '#000000'};
|
|
160
|
+
}
|
|
161
|
+
</style>`;
|
|
162
|
+
} else {
|
|
163
|
+
style = html`<style>
|
|
164
|
+
.default-slide-menu-top-bar-fix-logo-container {
|
|
165
|
+
width: 100px;
|
|
166
|
+
height: 100px;
|
|
167
|
+
}
|
|
168
|
+
.default-slide-menu-top-bar-fix-logo {
|
|
169
|
+
width: 80px;
|
|
170
|
+
height: 80px;
|
|
171
|
+
padding: 10px;
|
|
172
|
+
}
|
|
173
|
+
.default-slide-menu-top-bar-fix-title-container-text {
|
|
174
|
+
font-size: 30px;
|
|
175
|
+
top: 30px;
|
|
176
|
+
color: ${darkTheme ? '#ffffff' : '#000000'};
|
|
177
|
+
}
|
|
178
|
+
</style>`;
|
|
179
|
+
}
|
|
180
|
+
setTimeout(() => {
|
|
181
|
+
if (s(`.top-bar-app-icon`) && s(`.top-bar-app-icon`).src) {
|
|
182
|
+
s(`.default-slide-menu-top-bar-fix-logo`).src = s(`.top-bar-app-icon`).src;
|
|
183
|
+
if (s(`.top-bar-app-icon`).classList.contains('negative-color'))
|
|
184
|
+
s(`.default-slide-menu-top-bar-fix-logo`).classList.add('negative-color');
|
|
185
|
+
htmls(
|
|
186
|
+
`.default-slide-menu-top-bar-fix-title-container`,
|
|
187
|
+
html`
|
|
188
|
+
<div class="inl default-slide-menu-top-bar-fix-title-container-text">
|
|
189
|
+
${options.RouterInstance.NameApp}
|
|
190
|
+
</div>
|
|
191
|
+
`,
|
|
192
|
+
);
|
|
193
|
+
} else
|
|
194
|
+
htmls(
|
|
195
|
+
`.default-slide-menu-top-bar-fix-logo-container`,
|
|
196
|
+
html`<div class="abs center">${s(`.action-btn-app-icon-render`).innerHTML}</div>`,
|
|
197
|
+
);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
return html`${style}
|
|
201
|
+
<div class="in fll default-slide-menu-top-bar-fix-logo-container">
|
|
202
|
+
<img class="default-slide-menu-top-bar-fix-logo in fll" />
|
|
203
|
+
</div>
|
|
204
|
+
<div class="in fll default-slide-menu-top-bar-fix-title-container"></div>`;
|
|
205
|
+
};
|
|
206
|
+
}
|
|
142
207
|
const { barConfig } = options;
|
|
143
208
|
options.style = {
|
|
144
209
|
position: 'absolute',
|
|
@@ -266,7 +331,9 @@ const Modal = {
|
|
|
266
331
|
</div>
|
|
267
332
|
</div>
|
|
268
333
|
<div
|
|
269
|
-
class="abs main-body-btn main-body-btn-bar-custom ${options?.
|
|
334
|
+
class="abs main-body-btn main-body-btn-bar-custom ${options?.slideMenuTopBarBannerFix
|
|
335
|
+
? ''
|
|
336
|
+
: 'hide'}"
|
|
270
337
|
style="top: 100px; ${true || (options.mode && options.mode.match('right'))
|
|
271
338
|
? 'right'
|
|
272
339
|
: 'left'}: 0px"
|
|
@@ -345,6 +412,7 @@ const Modal = {
|
|
|
345
412
|
);
|
|
346
413
|
}
|
|
347
414
|
};
|
|
415
|
+
Modal.setTopBannerLink();
|
|
348
416
|
});
|
|
349
417
|
|
|
350
418
|
const inputSearchBoxId = `top-bar-search-box`;
|
|
@@ -429,12 +497,12 @@ const Modal = {
|
|
|
429
497
|
})}
|
|
430
498
|
</div>
|
|
431
499
|
</div>
|
|
432
|
-
${options?.
|
|
500
|
+
${options?.slideMenuTopBarBannerFix
|
|
433
501
|
? html`<div
|
|
434
502
|
class="abs modal slide-menu-top-bar-fix"
|
|
435
503
|
style="height: ${options.heightTopBar}px; top: 0px"
|
|
436
504
|
>
|
|
437
|
-
${await options.
|
|
505
|
+
<a class="a-link-top-banner"> ${await options.slideMenuTopBarBannerFix()}</a>
|
|
438
506
|
</div>`
|
|
439
507
|
: ''}
|
|
440
508
|
</div>`,
|
|
@@ -1072,11 +1140,18 @@ const Modal = {
|
|
|
1072
1140
|
}
|
|
1073
1141
|
|
|
1074
1142
|
{
|
|
1075
|
-
ThemeEvents['action-btn-theme'] = () => {
|
|
1143
|
+
ThemeEvents['action-btn-theme'] = async () => {
|
|
1076
1144
|
htmls(
|
|
1077
1145
|
`.action-btn-theme-render`,
|
|
1078
1146
|
html` ${darkTheme ? html` <i class="fas fa-moon"></i>` : html`<i class="far fa-sun"></i>`}`,
|
|
1079
1147
|
);
|
|
1148
|
+
if (s(`.slide-menu-top-bar-fix`)) {
|
|
1149
|
+
htmls(
|
|
1150
|
+
`.slide-menu-top-bar-fix`,
|
|
1151
|
+
html`<a class="a-link-top-banner">${await options.slideMenuTopBarBannerFix()}</a>`,
|
|
1152
|
+
);
|
|
1153
|
+
Modal.setTopBannerLink();
|
|
1154
|
+
}
|
|
1080
1155
|
};
|
|
1081
1156
|
ThemeEvents['action-btn-theme']();
|
|
1082
1157
|
|
|
@@ -2138,6 +2213,16 @@ const Modal = {
|
|
|
2138
2213
|
// non-fatal: keep default placement if structure not present
|
|
2139
2214
|
}
|
|
2140
2215
|
},
|
|
2216
|
+
setTopBannerLink: function () {
|
|
2217
|
+
if (s(`.a-link-top-banner`)) {
|
|
2218
|
+
s(`.a-link-top-banner`).setAttribute('href', `${location.origin}${getProxyPath()}`);
|
|
2219
|
+
EventsUI.onClick(`.a-link-top-banner`, (e) => {
|
|
2220
|
+
if (location.pathname === '/') return location.reload();
|
|
2221
|
+
e.preventDefault();
|
|
2222
|
+
s(`.action-btn-home`).click();
|
|
2223
|
+
});
|
|
2224
|
+
}
|
|
2225
|
+
},
|
|
2141
2226
|
headerTitleHeight: 40,
|
|
2142
2227
|
actionBtnCenter: function () {
|
|
2143
2228
|
if (!s(`.btn-close-modal-menu`).classList.contains('hide')) {
|
package/src/index.js
CHANGED
|
@@ -19,6 +19,7 @@ import UnderpostRepository from './cli/repository.js';
|
|
|
19
19
|
import UnderpostRun from './cli/run.js';
|
|
20
20
|
import UnderpostScript from './cli/script.js';
|
|
21
21
|
import UnderpostSecret from './cli/secrets.js';
|
|
22
|
+
import UnderpostSSH from './cli/ssh.js';
|
|
22
23
|
import UnderpostTest from './cli/test.js';
|
|
23
24
|
import UnderpostStartUp from './server/start.js';
|
|
24
25
|
|
|
@@ -34,7 +35,7 @@ class Underpost {
|
|
|
34
35
|
* @type {String}
|
|
35
36
|
* @memberof Underpost
|
|
36
37
|
*/
|
|
37
|
-
static version = 'v2.8.
|
|
38
|
+
static version = 'v2.8.847';
|
|
38
39
|
/**
|
|
39
40
|
* Repository cli API
|
|
40
41
|
* @static
|
|
@@ -126,6 +127,13 @@ class Underpost {
|
|
|
126
127
|
* @memberof Underpost
|
|
127
128
|
*/
|
|
128
129
|
static monitor = UnderpostMonitor.API;
|
|
130
|
+
/**
|
|
131
|
+
* SSH cli API
|
|
132
|
+
* @static
|
|
133
|
+
* @type {UnderpostSSH.API}
|
|
134
|
+
* @memberof Underpost
|
|
135
|
+
*/
|
|
136
|
+
static ssh = UnderpostSSH.API;
|
|
129
137
|
/**
|
|
130
138
|
* LXD cli API
|
|
131
139
|
* @static
|