@milaboratories/pl-deployments 2.4.6 → 2.4.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/dist/common/os_and_arch.cjs +39 -0
- package/dist/common/os_and_arch.cjs.map +1 -0
- package/dist/common/os_and_arch.d.ts +0 -1
- package/dist/common/os_and_arch.js +34 -0
- package/dist/common/os_and_arch.js.map +1 -0
- package/dist/common/pl_binary.cjs +34 -0
- package/dist/common/pl_binary.cjs.map +1 -0
- package/dist/common/pl_binary.d.ts +0 -1
- package/dist/common/pl_binary.js +30 -0
- package/dist/common/pl_binary.js.map +1 -0
- package/dist/common/pl_binary_download.cjs +172 -0
- package/dist/common/pl_binary_download.cjs.map +1 -0
- package/dist/common/pl_binary_download.d.ts +0 -1
- package/dist/common/pl_binary_download.js +148 -0
- package/dist/common/pl_binary_download.js.map +1 -0
- package/dist/common/pl_version.cjs +11 -0
- package/dist/common/pl_version.cjs.map +1 -0
- package/dist/common/pl_version.d.ts +0 -1
- package/dist/common/pl_version.js +9 -0
- package/dist/common/pl_version.js.map +1 -0
- package/dist/index.cjs +26 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.js +5 -64
- package/dist/index.js.map +1 -1
- package/dist/local/options.d.ts +0 -1
- package/dist/local/pid.cjs +24 -0
- package/dist/local/pid.cjs.map +1 -0
- package/dist/local/pid.d.ts +0 -1
- package/dist/local/pid.js +20 -0
- package/dist/local/pid.js.map +1 -0
- package/dist/local/pl.cjs +217 -0
- package/dist/local/pl.cjs.map +1 -0
- package/dist/local/pl.d.ts +0 -1
- package/dist/local/pl.js +192 -0
- package/dist/local/pl.js.map +1 -0
- package/dist/local/process.cjs +42 -0
- package/dist/local/process.cjs.map +1 -0
- package/dist/local/process.d.ts +0 -1
- package/dist/local/process.js +37 -0
- package/dist/local/process.js.map +1 -0
- package/dist/local/trace.cjs +27 -0
- package/dist/local/trace.cjs.map +1 -0
- package/dist/local/trace.d.ts +0 -1
- package/dist/local/trace.js +23 -0
- package/dist/local/trace.js.map +1 -0
- package/dist/package.json.cjs +7 -0
- package/dist/package.json.cjs.map +1 -0
- package/dist/package.json.js +5 -0
- package/dist/package.json.js.map +1 -0
- package/dist/ssh/__tests__/common-utils.d.ts +0 -1
- package/dist/ssh/connection_info.cjs +62 -0
- package/dist/ssh/connection_info.cjs.map +1 -0
- package/dist/ssh/connection_info.d.ts +0 -1
- package/dist/ssh/connection_info.js +55 -0
- package/dist/ssh/connection_info.js.map +1 -0
- package/dist/ssh/pl.cjs +500 -0
- package/dist/ssh/pl.cjs.map +1 -0
- package/dist/ssh/pl.d.ts +0 -1
- package/dist/ssh/pl.js +497 -0
- package/dist/ssh/pl.js.map +1 -0
- package/dist/ssh/pl_paths.cjs +67 -0
- package/dist/ssh/pl_paths.cjs.map +1 -0
- package/dist/ssh/pl_paths.d.ts +0 -1
- package/dist/ssh/pl_paths.js +50 -0
- package/dist/ssh/pl_paths.js.map +1 -0
- package/dist/ssh/ssh.cjs +621 -0
- package/dist/ssh/ssh.cjs.map +1 -0
- package/dist/ssh/ssh.d.ts +0 -1
- package/dist/ssh/ssh.js +619 -0
- package/dist/ssh/ssh.js.map +1 -0
- package/dist/ssh/supervisord.cjs +149 -0
- package/dist/ssh/supervisord.cjs.map +1 -0
- package/dist/ssh/supervisord.d.ts +0 -1
- package/dist/ssh/supervisord.js +140 -0
- package/dist/ssh/supervisord.js.map +1 -0
- package/package.json +16 -14
- package/src/common/pl_version.ts +3 -2
- package/dist/common/os_and_arch.d.ts.map +0 -1
- package/dist/common/pl_binary.d.ts.map +0 -1
- package/dist/common/pl_binary_download.d.ts.map +0 -1
- package/dist/common/pl_version.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.mjs +0 -1366
- package/dist/index.mjs.map +0 -1
- package/dist/local/options.d.ts.map +0 -1
- package/dist/local/pid.d.ts.map +0 -1
- package/dist/local/pl.d.ts.map +0 -1
- package/dist/local/process.d.ts.map +0 -1
- package/dist/local/trace.d.ts.map +0 -1
- package/dist/ssh/__tests__/common-utils.d.ts.map +0 -1
- package/dist/ssh/connection_info.d.ts.map +0 -1
- package/dist/ssh/pl.d.ts.map +0 -1
- package/dist/ssh/pl_paths.d.ts.map +0 -1
- package/dist/ssh/ssh.d.ts.map +0 -1
- package/dist/ssh/supervisord.d.ts.map +0 -1
package/dist/index.mjs
DELETED
|
@@ -1,1366 +0,0 @@
|
|
|
1
|
-
var Y = Object.defineProperty;
|
|
2
|
-
var Q = (o, t, e) => t in o ? Y(o, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : o[t] = e;
|
|
3
|
-
var p = (o, t, e) => Q(o, typeof t != "symbol" ? t + "" : t, e);
|
|
4
|
-
import { spawn as tt } from "node:child_process";
|
|
5
|
-
import { sleep as x, fileExists as v, assertNever as j, notEmpty as m, RetryablePromise as et } from "@milaboratories/ts-helpers";
|
|
6
|
-
import O from "node:fs";
|
|
7
|
-
import g, { readFile as rt } from "node:fs/promises";
|
|
8
|
-
import h from "upath";
|
|
9
|
-
import { request as it } from "undici";
|
|
10
|
-
import { Readable as nt, Writable as ot } from "node:stream";
|
|
11
|
-
import { text as st } from "node:stream/consumers";
|
|
12
|
-
import * as at from "tar";
|
|
13
|
-
import ct from "decompress";
|
|
14
|
-
import * as lt from "node:os";
|
|
15
|
-
import P from "node:os";
|
|
16
|
-
import dt, { Client as D } from "ssh2";
|
|
17
|
-
import G from "node:net";
|
|
18
|
-
import ht from "node:dns";
|
|
19
|
-
import { randomBytes as F } from "node:crypto";
|
|
20
|
-
import { generateSshPlConfigs as ut, getFreePort as $ } from "@milaboratories/pl-config";
|
|
21
|
-
import { z as f } from "zod";
|
|
22
|
-
function pt(o, t) {
|
|
23
|
-
return o.info(`Running:
|
|
24
|
-
cmd: ${JSON.stringify([t.cmd, ...t.args])}
|
|
25
|
-
wd: ${t.opts.cwd}`), o.info(" spawning child process"), tt(t.cmd, t.args, t.opts);
|
|
26
|
-
}
|
|
27
|
-
async function k(o) {
|
|
28
|
-
try {
|
|
29
|
-
return process.kill(o, 0), !0;
|
|
30
|
-
} catch {
|
|
31
|
-
return !1;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
function J(o) {
|
|
35
|
-
return process.kill(o, "SIGINT");
|
|
36
|
-
}
|
|
37
|
-
async function L(o, t) {
|
|
38
|
-
let r = 0;
|
|
39
|
-
for (; await k(o); )
|
|
40
|
-
if (await x(100), r += 100, r > t)
|
|
41
|
-
throw new Error(`The process did not stopped after ${t} ms.`);
|
|
42
|
-
}
|
|
43
|
-
const ft = ["linux", "macos", "windows"];
|
|
44
|
-
function R(o) {
|
|
45
|
-
switch (o.toLowerCase()) {
|
|
46
|
-
case "darwin":
|
|
47
|
-
return "macos";
|
|
48
|
-
case "linux":
|
|
49
|
-
return "linux";
|
|
50
|
-
case "win32":
|
|
51
|
-
return "windows";
|
|
52
|
-
default:
|
|
53
|
-
throw new Error(
|
|
54
|
-
`operating system '${o}' is not currently supported by Platforma ecosystem. The list of OSes supported: ` + JSON.stringify(ft)
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
const wt = ["amd64", "arm64"];
|
|
59
|
-
function C(o) {
|
|
60
|
-
switch (o) {
|
|
61
|
-
case "aarch64":
|
|
62
|
-
case "aarch64_be":
|
|
63
|
-
case "arm64":
|
|
64
|
-
return "arm64";
|
|
65
|
-
case "x86_64":
|
|
66
|
-
case "x64":
|
|
67
|
-
return "amd64";
|
|
68
|
-
default:
|
|
69
|
-
throw new Error(
|
|
70
|
-
`processor architecture '${o}' is not currently supported by Platforma ecosystem. The list of architectures supported: ` + JSON.stringify(wt)
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
const mt = "https://cdn.platforma.bio/software", yt = "https://cdn-ga.pl-open.science/software";
|
|
75
|
-
async function gt(o, t, e, r, i, n) {
|
|
76
|
-
const s = z(e, r, t, C(i), R(n)), { archiveUrl: a, alternativeArchiveGAUrl: c, archivePath: l } = s;
|
|
77
|
-
try {
|
|
78
|
-
await A(o, a, l), s.wasDownloadedFrom = a;
|
|
79
|
-
} catch {
|
|
80
|
-
await A(o, c, l), s.wasDownloadedFrom = c;
|
|
81
|
-
}
|
|
82
|
-
return s;
|
|
83
|
-
}
|
|
84
|
-
async function vt(o, t, e, r, i, n) {
|
|
85
|
-
const s = z(e, r, t, C(i), R(n)), { archiveUrl: a, alternativeArchiveGAUrl: c, archivePath: l, archiveType: d, targetFolder: u } = s;
|
|
86
|
-
try {
|
|
87
|
-
await A(o, a, l), s.wasDownloadedFrom = a;
|
|
88
|
-
} catch {
|
|
89
|
-
await A(o, c, l), s.wasDownloadedFrom = c;
|
|
90
|
-
}
|
|
91
|
-
return await St(o, l, d, u), s;
|
|
92
|
-
}
|
|
93
|
-
function z(o, t, e, r, i) {
|
|
94
|
-
const n = `${t}-${r}`, s = Ct[i], a = `${n}.${s}`, c = `${mt}/${o}/${i}/${a}`, l = `${yt}/${o}/${i}/${a}`, d = h.join(e, a), u = h.join(e, n);
|
|
95
|
-
return {
|
|
96
|
-
archiveUrl: c,
|
|
97
|
-
alternativeArchiveGAUrl: l,
|
|
98
|
-
archivePath: d,
|
|
99
|
-
archiveType: s,
|
|
100
|
-
targetFolder: u,
|
|
101
|
-
baseName: n
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
async function A(o, t, e) {
|
|
105
|
-
const r = {};
|
|
106
|
-
r.dstArchive = e;
|
|
107
|
-
try {
|
|
108
|
-
if (r.fileExisted = await v(e), r.fileExisted)
|
|
109
|
-
return o.info(`Platforma Backend archive download skipped: '${e}' already exists`), r;
|
|
110
|
-
await g.mkdir(h.dirname(e), { recursive: !0 }), r.dirnameCreated = !0, o.info(`Downloading archive:
|
|
111
|
-
URL: ${t}
|
|
112
|
-
Save to: ${e}`);
|
|
113
|
-
const { body: i, statusCode: n } = await it(t);
|
|
114
|
-
if (r.statusCode = n, n != 200) {
|
|
115
|
-
const s = await st(i);
|
|
116
|
-
throw r.errorMsg = `failed to download archive: ${n}, response: ${s.slice(0, 1e3)}`, o.error(r.errorMsg), new Error(r.errorMsg);
|
|
117
|
-
}
|
|
118
|
-
return r.tmpPath = e + ".tmp", await nt.toWeb(i).pipeTo(ot.toWeb(O.createWriteStream(r.tmpPath))), r.wroteTmp = !0, r.tmpExisted = await v(r.tmpPath), await g.rename(r.tmpPath, e), r.renamed = !0, r.newExisted = await v(e), r;
|
|
119
|
-
} catch (i) {
|
|
120
|
-
const n = `downloadArchive: ${JSON.stringify(i)}, state: ${JSON.stringify(r)}`;
|
|
121
|
-
throw o.error(n), new Error(n);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
const $t = ".ok";
|
|
125
|
-
async function St(o, t, e, r) {
|
|
126
|
-
if (o.info("extracting archive..."), o.info(` archive path: '${t}'`), o.info(` target dir: '${r}'`), !await v(t)) {
|
|
127
|
-
const n = `Platforma Backend binary archive not found at '${t}'`;
|
|
128
|
-
throw o.error(n), new Error(n);
|
|
129
|
-
}
|
|
130
|
-
const i = h.join(r, $t);
|
|
131
|
-
if (await v(i)) {
|
|
132
|
-
o.info(`Platforma Backend binaries unpack skipped: '${r}' exists`);
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
switch (await v(r) && (o.info(`Removing previous incompletely unpacked folder: '${r}'`), await g.rm(r, { recursive: !0 })), o.info(` creating target dir '${r}'`), await g.mkdir(r, { recursive: !0 }), o.info(
|
|
136
|
-
`Unpacking Platforma Backend archive:
|
|
137
|
-
Archive: ${t}
|
|
138
|
-
Target dir: ${r}`
|
|
139
|
-
), e) {
|
|
140
|
-
case "tgz":
|
|
141
|
-
await at.x({
|
|
142
|
-
file: t,
|
|
143
|
-
cwd: r,
|
|
144
|
-
gzip: !0
|
|
145
|
-
});
|
|
146
|
-
break;
|
|
147
|
-
case "zip":
|
|
148
|
-
await ct(t, r);
|
|
149
|
-
break;
|
|
150
|
-
default:
|
|
151
|
-
j(e);
|
|
152
|
-
}
|
|
153
|
-
await g.writeFile(i, "ok"), o.info(" ... unpack done.");
|
|
154
|
-
}
|
|
155
|
-
const Ct = {
|
|
156
|
-
linux: "tgz",
|
|
157
|
-
macos: "tgz",
|
|
158
|
-
windows: "zip"
|
|
159
|
-
};
|
|
160
|
-
function N() {
|
|
161
|
-
return "1.35.2";
|
|
162
|
-
}
|
|
163
|
-
function Et() {
|
|
164
|
-
return { type: "Download", version: N() };
|
|
165
|
-
}
|
|
166
|
-
async function Ft(o, t, e) {
|
|
167
|
-
switch (e.type) {
|
|
168
|
-
case "Download":
|
|
169
|
-
const r = await vt(o, t, "pl", `pl-${e.version}`, P.arch(), P.platform());
|
|
170
|
-
return h.join(r.baseName, "binaries", At[R(P.platform())]);
|
|
171
|
-
case "Local":
|
|
172
|
-
return e.path;
|
|
173
|
-
default:
|
|
174
|
-
j(e);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
const At = {
|
|
178
|
-
linux: "platforma",
|
|
179
|
-
macos: "platforma",
|
|
180
|
-
windows: "platforma.exe"
|
|
181
|
-
};
|
|
182
|
-
function V(o) {
|
|
183
|
-
return h.join(o, "pl_pid");
|
|
184
|
-
}
|
|
185
|
-
async function bt(o) {
|
|
186
|
-
if (!await v(o))
|
|
187
|
-
return;
|
|
188
|
-
const t = await g.readFile(o);
|
|
189
|
-
return Number(t.toString());
|
|
190
|
-
}
|
|
191
|
-
async function Pt(o, t) {
|
|
192
|
-
await g.writeFile(o, JSON.stringify(t));
|
|
193
|
-
}
|
|
194
|
-
function Dt() {
|
|
195
|
-
return {};
|
|
196
|
-
}
|
|
197
|
-
function xt(o, t, e) {
|
|
198
|
-
return o[t] = e, e;
|
|
199
|
-
}
|
|
200
|
-
async function _(o, t) {
|
|
201
|
-
const e = Dt();
|
|
202
|
-
try {
|
|
203
|
-
return await t((i, n) => xt(e, i, n), e);
|
|
204
|
-
} catch (r) {
|
|
205
|
-
throw o.error(`error ${r} while doing traced operation, state: ${JSON.stringify(e)}`), r;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
const Ot = "config-local.yaml";
|
|
209
|
-
class kt {
|
|
210
|
-
constructor(t, e, r, i, n, s, a, c) {
|
|
211
|
-
p(this, "instance");
|
|
212
|
-
p(this, "pid");
|
|
213
|
-
p(this, "nRuns", 0);
|
|
214
|
-
p(this, "lastRunHistory", {});
|
|
215
|
-
p(this, "wasStopped", !1);
|
|
216
|
-
this.logger = t, this.workingDir = e, this.startOptions = r, this.initialStartHistory = i, this.onClose = n, this.onError = s, this.onCloseAndError = a, this.onCloseAndErrorNoStop = c;
|
|
217
|
-
}
|
|
218
|
-
async start() {
|
|
219
|
-
await _(this.logger, async (t, e) => {
|
|
220
|
-
this.wasStopped = !1;
|
|
221
|
-
const r = pt(this.logger, this.startOptions);
|
|
222
|
-
r.on("error", (n) => {
|
|
223
|
-
this.logger.error(
|
|
224
|
-
`error '${n}', while running platforma, started opts: ${JSON.stringify(this.debugInfo())}`
|
|
225
|
-
), this.onError !== void 0 && this.onError(this), this.onCloseAndError !== void 0 && this.onCloseAndError(this), this.onCloseAndErrorNoStop !== void 0 && !this.wasStopped && this.onCloseAndErrorNoStop(this);
|
|
226
|
-
}), r.on("close", () => {
|
|
227
|
-
this.logger.warn(`platforma was closed, started opts: ${JSON.stringify(this.debugInfo())}`), this.onClose !== void 0 && this.onClose(this), this.onCloseAndError !== void 0 && this.onCloseAndError(this), this.onCloseAndErrorNoStop !== void 0 && !this.wasStopped && this.onCloseAndErrorNoStop(this);
|
|
228
|
-
}), t("started", !0);
|
|
229
|
-
const i = t("pidFile", V(this.workingDir));
|
|
230
|
-
t("pid", m(r.pid)), t("pidWritten", await Pt(i, m(r.pid))), this.nRuns++, this.instance = r, this.pid = r.pid, this.lastRunHistory = e;
|
|
231
|
-
});
|
|
232
|
-
}
|
|
233
|
-
stop() {
|
|
234
|
-
this.wasStopped = !0, J(m(this.pid));
|
|
235
|
-
}
|
|
236
|
-
async waitStopped() {
|
|
237
|
-
await L(m(this.pid), 15e3);
|
|
238
|
-
}
|
|
239
|
-
stopped() {
|
|
240
|
-
return this.wasStopped;
|
|
241
|
-
}
|
|
242
|
-
async isAlive() {
|
|
243
|
-
return await k(m(this.pid));
|
|
244
|
-
}
|
|
245
|
-
debugInfo() {
|
|
246
|
-
return {
|
|
247
|
-
lastRunHistory: this.lastRunHistory,
|
|
248
|
-
nRuns: this.nRuns,
|
|
249
|
-
pid: this.pid,
|
|
250
|
-
workingDir: this.workingDir,
|
|
251
|
-
initialStartHistory: this.initialStartHistory,
|
|
252
|
-
wasStopped: this.wasStopped
|
|
253
|
-
};
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
async function Ee(o, t) {
|
|
257
|
-
const e = Math.max(lt.cpus().length - 2, 1), r = Nt(t, e);
|
|
258
|
-
return await _(o, async (i, n) => {
|
|
259
|
-
i("startOptions", { ...r, config: "too wordy" });
|
|
260
|
-
const s = h.resolve(r.workingDir);
|
|
261
|
-
r.closeOld && i("closeOld", await Rt(o, s));
|
|
262
|
-
const a = h.join(s, Ot);
|
|
263
|
-
o.info(`writing configuration '${a}'...`), await g.writeFile(a, r.config);
|
|
264
|
-
const c = h.join(s, "binaries"), l = await Ft(o, c, r.plBinary), d = i("binaryPath", h.join("binaries", l)), u = _t(d, a, r, s, process.env);
|
|
265
|
-
i("processOpts", {
|
|
266
|
-
cmd: u.cmd,
|
|
267
|
-
args: u.args,
|
|
268
|
-
cwd: u.opts.cwd
|
|
269
|
-
});
|
|
270
|
-
const w = new kt(
|
|
271
|
-
o,
|
|
272
|
-
r.workingDir,
|
|
273
|
-
u,
|
|
274
|
-
n,
|
|
275
|
-
r.onClose,
|
|
276
|
-
r.onError,
|
|
277
|
-
r.onCloseAndError,
|
|
278
|
-
r.onCloseAndErrorNoStop
|
|
279
|
-
);
|
|
280
|
-
return await w.start(), w;
|
|
281
|
-
});
|
|
282
|
-
}
|
|
283
|
-
async function Rt(o, t) {
|
|
284
|
-
return await _(o, async (e, r) => {
|
|
285
|
-
const i = e("pidFilePath", V(t)), n = e("pid", await bt(i)), s = e("wasAlive", await k(n));
|
|
286
|
-
return n !== void 0 && s && (e("stopped", J(n)), e("waitStopped", await L(n, 1e4))), r;
|
|
287
|
-
});
|
|
288
|
-
}
|
|
289
|
-
function Nt(o, t) {
|
|
290
|
-
var i;
|
|
291
|
-
const e = {
|
|
292
|
-
plBinary: Et(),
|
|
293
|
-
spawnOptions: {
|
|
294
|
-
env: {
|
|
295
|
-
GOMAXPROCS: String(t)
|
|
296
|
-
}
|
|
297
|
-
},
|
|
298
|
-
closeOld: !0
|
|
299
|
-
};
|
|
300
|
-
if ((i = o.spawnOptions) != null && i.env && (e.spawnOptions.env = { ...e.spawnOptions.env, ...o.spawnOptions.env }), o.spawnOptions) {
|
|
301
|
-
const n = { ...o.spawnOptions };
|
|
302
|
-
delete n.env, e.spawnOptions = { ...e.spawnOptions, ...n };
|
|
303
|
-
}
|
|
304
|
-
const r = { ...o };
|
|
305
|
-
return delete r.spawnOptions, { ...e, ...r };
|
|
306
|
-
}
|
|
307
|
-
function _t(o, t, e, r, i) {
|
|
308
|
-
var a;
|
|
309
|
-
const n = {
|
|
310
|
-
cmd: o,
|
|
311
|
-
args: ["--config", t],
|
|
312
|
-
opts: {
|
|
313
|
-
env: { ...i },
|
|
314
|
-
cwd: r,
|
|
315
|
-
stdio: ["pipe", "ignore", "inherit"],
|
|
316
|
-
windowsHide: !0
|
|
317
|
-
// hide a terminal on Windows
|
|
318
|
-
}
|
|
319
|
-
};
|
|
320
|
-
(a = e.spawnOptions) != null && a.env && (n.opts.env = { ...n.opts.env, ...e.spawnOptions.env });
|
|
321
|
-
const s = { ...e.spawnOptions };
|
|
322
|
-
return delete s.env, n.opts = { ...n.opts, ...s }, n;
|
|
323
|
-
}
|
|
324
|
-
const Ut = {
|
|
325
|
-
keepaliveInterval: 6e4,
|
|
326
|
-
keepaliveCountMax: 10
|
|
327
|
-
};
|
|
328
|
-
class U {
|
|
329
|
-
constructor(t, e) {
|
|
330
|
-
p(this, "config");
|
|
331
|
-
p(this, "homeDir");
|
|
332
|
-
p(this, "forwardedServers", []);
|
|
333
|
-
this.logger = t, this.client = e;
|
|
334
|
-
}
|
|
335
|
-
/**
|
|
336
|
-
* Initializes the SshClient and establishes a connection using the provided configuration.
|
|
337
|
-
* @param config - The connection configuration object for the SSH client.
|
|
338
|
-
* @returns A new instance of SshClient with an active connection.
|
|
339
|
-
*/
|
|
340
|
-
static async init(t, e) {
|
|
341
|
-
const r = {
|
|
342
|
-
...Ut,
|
|
343
|
-
...e
|
|
344
|
-
}, i = new U(t, new D());
|
|
345
|
-
return await i.connect(r), i;
|
|
346
|
-
}
|
|
347
|
-
getForwardedServers() {
|
|
348
|
-
return this.forwardedServers;
|
|
349
|
-
}
|
|
350
|
-
getFullHostName() {
|
|
351
|
-
var t, e;
|
|
352
|
-
return `${(t = this.config) == null ? void 0 : t.host}:${(e = this.config) == null ? void 0 : e.port}`;
|
|
353
|
-
}
|
|
354
|
-
getUserName() {
|
|
355
|
-
var t;
|
|
356
|
-
return (t = this.config) == null ? void 0 : t.username;
|
|
357
|
-
}
|
|
358
|
-
/**
|
|
359
|
-
* Connects to the SSH server using the specified configuration.
|
|
360
|
-
* @param config - The connection configuration object for the SSH client.
|
|
361
|
-
* @returns A promise that resolves when the connection is established or rejects on error.
|
|
362
|
-
*/
|
|
363
|
-
async connect(t) {
|
|
364
|
-
return this.config = t, await Bt(this.client, t);
|
|
365
|
-
}
|
|
366
|
-
/**
|
|
367
|
-
* Executes a command on the SSH server.
|
|
368
|
-
* @param command - The command to execute on the remote server.
|
|
369
|
-
* @returns A promise resolving with the command's stdout and stderr outputs.
|
|
370
|
-
*/
|
|
371
|
-
async exec(t) {
|
|
372
|
-
return new Promise((e, r) => {
|
|
373
|
-
this.client.exec(t, (i, n) => {
|
|
374
|
-
if (i)
|
|
375
|
-
return r(new Error(`ssh.exec: ${t}: ${i}`));
|
|
376
|
-
let s = "", a = "";
|
|
377
|
-
n.on("close", (c) => {
|
|
378
|
-
c === 0 ? e({ stdout: s, stderr: a }) : r(new Error(`Command ${t} exited with code ${c}, stdout: ${s}, stderr: ${a}`));
|
|
379
|
-
}).on("data", (c) => {
|
|
380
|
-
s += c.toString();
|
|
381
|
-
}).stderr.on("data", (c) => {
|
|
382
|
-
a += c.toString();
|
|
383
|
-
});
|
|
384
|
-
});
|
|
385
|
-
});
|
|
386
|
-
}
|
|
387
|
-
/**
|
|
388
|
-
* Retrieves the supported authentication methods for a given host and port.
|
|
389
|
-
* @param host - The hostname or IP address of the server.
|
|
390
|
-
* @param port - The port number to connect to on the server.
|
|
391
|
-
* @returns 'publickey' | 'password'[] A promise resolving with a list of supported authentication methods.
|
|
392
|
-
*/
|
|
393
|
-
static async getAuthTypes(t, e) {
|
|
394
|
-
return new Promise((r) => {
|
|
395
|
-
let i = "";
|
|
396
|
-
const n = new D();
|
|
397
|
-
n.on("ready", () => {
|
|
398
|
-
n.end();
|
|
399
|
-
const s = this.extractAuthMethods(i);
|
|
400
|
-
r(s.length === 0 ? ["publickey", "password"] : s);
|
|
401
|
-
}), n.on("error", () => {
|
|
402
|
-
n.end(), r(["publickey", "password"]);
|
|
403
|
-
}), n.connect({
|
|
404
|
-
host: t,
|
|
405
|
-
port: e,
|
|
406
|
-
username: (/* @__PURE__ */ new Date()).getTime().toString(),
|
|
407
|
-
debug: (s) => {
|
|
408
|
-
i += `${s}
|
|
409
|
-
`;
|
|
410
|
-
}
|
|
411
|
-
});
|
|
412
|
-
});
|
|
413
|
-
}
|
|
414
|
-
/**
|
|
415
|
-
* Extracts authentication methods from debug logs.
|
|
416
|
-
* @param log - The debug log output containing authentication information.
|
|
417
|
-
* @returns An array of extracted authentication methods.
|
|
418
|
-
*/
|
|
419
|
-
static extractAuthMethods(t) {
|
|
420
|
-
const e = t.match(/Inbound: Received USERAUTH_FAILURE \((.+)\)/);
|
|
421
|
-
return e && e[1] ? e[1].split(",").map((r) => r.trim()) : [];
|
|
422
|
-
}
|
|
423
|
-
/**
|
|
424
|
-
* Sets up port forwarding between a remote port on the SSH server and a local port.
|
|
425
|
-
* A new connection is used for this operation instead of an existing one.
|
|
426
|
-
* @param ports - An object specifying the remote and local port configuration.
|
|
427
|
-
* @param config - Optional connection configuration for the SSH client.
|
|
428
|
-
* @returns { server: net.Server } A promise resolving with the created server instance.
|
|
429
|
-
*/
|
|
430
|
-
async forwardPort(t, e) {
|
|
431
|
-
const r = `ssh.forward:${t.localPort}:${t.remotePort}.id_${F(1).toString("hex")}`;
|
|
432
|
-
e = e ?? this.config;
|
|
433
|
-
const i = new et((n) => new Promise((s, a) => {
|
|
434
|
-
const c = new D();
|
|
435
|
-
c.on("ready", () => {
|
|
436
|
-
this.logger.info(`${r}.client.ready`), s(c);
|
|
437
|
-
}), c.on("error", (l) => {
|
|
438
|
-
this.logger.info(`${r}.client.error: ${l}`), n.reset(), a(l);
|
|
439
|
-
}), c.on("close", () => {
|
|
440
|
-
this.logger.info(`${r}.client.closed`), n.reset();
|
|
441
|
-
}), c.connect(e);
|
|
442
|
-
}));
|
|
443
|
-
return await i.ensure(), new Promise((n, s) => {
|
|
444
|
-
const a = G.createServer({ pauseOnConnect: !0 }, async (c) => {
|
|
445
|
-
const l = `${r}.sock_${F(1).toString("hex")}`;
|
|
446
|
-
let d;
|
|
447
|
-
try {
|
|
448
|
-
d = await i.ensure();
|
|
449
|
-
} catch (w) {
|
|
450
|
-
this.logger.info(`${l}.persistentClient.catch: ${w}`), c.end();
|
|
451
|
-
return;
|
|
452
|
-
}
|
|
453
|
-
d.setNoDelay(!0), c.setNoDelay(!0);
|
|
454
|
-
let u;
|
|
455
|
-
try {
|
|
456
|
-
u = await It(this.logger, d, "127.0.0.1", 0, "127.0.0.1", t.remotePort);
|
|
457
|
-
} catch (w) {
|
|
458
|
-
this.logger.error(`${l}.forwardOut.err: ${w}`), c.end();
|
|
459
|
-
return;
|
|
460
|
-
}
|
|
461
|
-
c.pipe(u), u.pipe(c), c.resume(), u.on("error", (w) => {
|
|
462
|
-
this.logger.error(`${l}.stream.error: ${w}`), c.end(), u.end();
|
|
463
|
-
}), u.on("close", () => {
|
|
464
|
-
c.end(), u.end();
|
|
465
|
-
}), c.on("close", () => {
|
|
466
|
-
this.logger.info(`${l}.localSocket: closed`), c.end(), u.end();
|
|
467
|
-
});
|
|
468
|
-
});
|
|
469
|
-
a.listen(t.localPort, "127.0.0.1", () => {
|
|
470
|
-
this.logger.info(`${r}.server: started listening`), this.forwardedServers.push(a), n({ server: a });
|
|
471
|
-
}), a.on("error", (c) => {
|
|
472
|
-
a.close(), s(new Error(`${r}.server: error: ${JSON.stringify(c)}`));
|
|
473
|
-
}), a.on("close", () => {
|
|
474
|
-
this.logger.info(`${r}.server: closed ${JSON.stringify(t)}`), this.forwardedServers = this.forwardedServers.filter((c) => c !== a);
|
|
475
|
-
});
|
|
476
|
-
});
|
|
477
|
-
}
|
|
478
|
-
closeForwardedPorts() {
|
|
479
|
-
this.logger.info("[SSH] Closing all forwarded ports..."), this.forwardedServers.forEach((t) => {
|
|
480
|
-
const e = t.address();
|
|
481
|
-
if (e && typeof e != "string") {
|
|
482
|
-
const r = e;
|
|
483
|
-
this.logger.info(`[SSH] Closing port forward for server ${r.address}:${r.port}`);
|
|
484
|
-
}
|
|
485
|
-
t.close();
|
|
486
|
-
}), this.forwardedServers = [];
|
|
487
|
-
}
|
|
488
|
-
/**
|
|
489
|
-
* Checks if a specified host is available by performing a DNS lookup.
|
|
490
|
-
* @param hostname - The hostname or IP address to check.
|
|
491
|
-
* @returns A promise resolving with `true` if the host is reachable, otherwise `false`.
|
|
492
|
-
*/
|
|
493
|
-
static async checkHostAvailability(t) {
|
|
494
|
-
return new Promise((e) => {
|
|
495
|
-
ht.lookup(t, (r) => {
|
|
496
|
-
e(!r);
|
|
497
|
-
});
|
|
498
|
-
});
|
|
499
|
-
}
|
|
500
|
-
/**
|
|
501
|
-
* Determines whether a private key requires a passphrase for use.
|
|
502
|
-
* @param privateKey - The private key content to check.
|
|
503
|
-
* @returns A promise resolving with `true` if a passphrase is required, otherwise `false`.
|
|
504
|
-
*/
|
|
505
|
-
static async isPassphraseRequiredForKey(t) {
|
|
506
|
-
return new Promise((e, r) => {
|
|
507
|
-
try {
|
|
508
|
-
return dt.utils.parseKey(t) instanceof Error && e(!0), e(!1);
|
|
509
|
-
} catch (i) {
|
|
510
|
-
console.log("Error parsing privateKey"), r(new Error(`ssh.isPassphraseRequiredForKey: err ${i}`));
|
|
511
|
-
}
|
|
512
|
-
});
|
|
513
|
-
}
|
|
514
|
-
/**
|
|
515
|
-
* Uploads a local file to a remote server via SFTP.
|
|
516
|
-
* This function creates new SFTP connection
|
|
517
|
-
* @param localPath - The local file path.
|
|
518
|
-
* @param remotePath - The remote file path on the server.
|
|
519
|
-
* @returns A promise resolving with `true` if the file was successfully uploaded.
|
|
520
|
-
*/
|
|
521
|
-
async uploadFile(t, e) {
|
|
522
|
-
return await this.withSftp(async (r) => new Promise((i, n) => {
|
|
523
|
-
r.fastPut(t, e, (s) => {
|
|
524
|
-
if (s) {
|
|
525
|
-
const a = new Error(
|
|
526
|
-
`ssh.uploadFile: err: ${s}, localPath: ${t}, remotePath: ${e}`
|
|
527
|
-
);
|
|
528
|
-
return n(a);
|
|
529
|
-
}
|
|
530
|
-
i(!0);
|
|
531
|
-
});
|
|
532
|
-
}));
|
|
533
|
-
}
|
|
534
|
-
async withSftp(t) {
|
|
535
|
-
return new Promise((e, r) => {
|
|
536
|
-
this.client.sftp((i, n) => {
|
|
537
|
-
if (i)
|
|
538
|
-
return r(new Error(`ssh.withSftp: sftp err: ${i}`));
|
|
539
|
-
t(n).then(e).catch((s) => {
|
|
540
|
-
r(new Error(`ssh.withSftp.callback: err ${s}`));
|
|
541
|
-
}).finally(() => {
|
|
542
|
-
n == null || n.end();
|
|
543
|
-
});
|
|
544
|
-
});
|
|
545
|
-
});
|
|
546
|
-
}
|
|
547
|
-
async writeFileOnTheServer(t, e, r = 432) {
|
|
548
|
-
return this.withSftp(async (i) => this.writeFile(i, t, e, r));
|
|
549
|
-
}
|
|
550
|
-
async getForderStructure(t, e, r = { files: [], directories: [] }) {
|
|
551
|
-
return new Promise((i, n) => {
|
|
552
|
-
t.readdir(e, async (s, a) => {
|
|
553
|
-
if (s)
|
|
554
|
-
return n(s);
|
|
555
|
-
for (const c of a) {
|
|
556
|
-
const l = `${e}/${c.filename}`;
|
|
557
|
-
if (c.attrs.isDirectory()) {
|
|
558
|
-
r.directories.push(l);
|
|
559
|
-
try {
|
|
560
|
-
await this.getForderStructure(t, l, r);
|
|
561
|
-
} catch (d) {
|
|
562
|
-
return n(d instanceof Error ? d : new Error(String(d)));
|
|
563
|
-
}
|
|
564
|
-
} else
|
|
565
|
-
r.files.push(l);
|
|
566
|
-
}
|
|
567
|
-
i(r);
|
|
568
|
-
});
|
|
569
|
-
});
|
|
570
|
-
}
|
|
571
|
-
rmdir(t, e) {
|
|
572
|
-
return new Promise((r, i) => {
|
|
573
|
-
t.rmdir(e, (n) => n ? i(n) : r(!0));
|
|
574
|
-
});
|
|
575
|
-
}
|
|
576
|
-
unlink(t, e) {
|
|
577
|
-
return new Promise((r, i) => {
|
|
578
|
-
t.unlink(e, (n) => n ? i(n) : r(!0));
|
|
579
|
-
});
|
|
580
|
-
}
|
|
581
|
-
async deleteFolder(t) {
|
|
582
|
-
return this.withSftp(async (e) => {
|
|
583
|
-
try {
|
|
584
|
-
const r = await this.getForderStructure(e, t);
|
|
585
|
-
this.logger.info("ssh.deleteFolder list of files and directories"), this.logger.info(`ssh.deleteFolder list of files: ${r.files}`), this.logger.info(`ssh.deleteFolder list of directories: ${r.directories}`);
|
|
586
|
-
for (const i of r.files)
|
|
587
|
-
this.logger.info(`ssh.deleteFolder unlink file ${i}`), await this.unlink(e, i);
|
|
588
|
-
r.directories.sort((i, n) => n.length - i.length);
|
|
589
|
-
for (const i of r.directories)
|
|
590
|
-
this.logger.info(`ssh.deleteFolder rmdir ${i}`), await this.rmdir(e, i);
|
|
591
|
-
return await this.rmdir(e, t), !0;
|
|
592
|
-
} catch (r) {
|
|
593
|
-
this.logger.error(r);
|
|
594
|
-
const i = r instanceof Error ? r.message : "";
|
|
595
|
-
throw new Error(`ssh.deleteFolder: path: ${t}, message: ${i}`);
|
|
596
|
-
}
|
|
597
|
-
});
|
|
598
|
-
}
|
|
599
|
-
async readFile(t) {
|
|
600
|
-
return this.withSftp(async (e) => new Promise((r, i) => {
|
|
601
|
-
e.readFile(t, (n, s) => {
|
|
602
|
-
if (n)
|
|
603
|
-
return i(new Error(`ssh.readFile: ${n}`));
|
|
604
|
-
r(s.toString());
|
|
605
|
-
});
|
|
606
|
-
}));
|
|
607
|
-
}
|
|
608
|
-
async chmod(t, e) {
|
|
609
|
-
return this.withSftp(async (r) => new Promise((i, n) => {
|
|
610
|
-
r.chmod(t, e, (s) => s ? n(new Error(`ssh.chmod: ${s}, path: ${t}, mode: ${e}`)) : i(void 0));
|
|
611
|
-
}));
|
|
612
|
-
}
|
|
613
|
-
async checkFileExists(t) {
|
|
614
|
-
return this.withSftp(async (e) => new Promise((r, i) => {
|
|
615
|
-
e.stat(t, (n, s) => {
|
|
616
|
-
if (n)
|
|
617
|
-
return (n == null ? void 0 : n.code) === 2 ? r(!1) : i(new Error(`ssh.checkFileExists: err ${n}`));
|
|
618
|
-
r(s.isFile());
|
|
619
|
-
});
|
|
620
|
-
}));
|
|
621
|
-
}
|
|
622
|
-
async checkPathExists(t) {
|
|
623
|
-
return this.withSftp(async (e) => new Promise((r, i) => {
|
|
624
|
-
e.stat(t, (n, s) => {
|
|
625
|
-
if (n)
|
|
626
|
-
return n.code === 2 ? r({ exists: !1, isFile: !1, isDirectory: !1 }) : i(new Error(`ssh.checkPathExists: ${n}`));
|
|
627
|
-
r({
|
|
628
|
-
exists: !0,
|
|
629
|
-
isFile: s.isFile(),
|
|
630
|
-
isDirectory: s.isDirectory()
|
|
631
|
-
});
|
|
632
|
-
});
|
|
633
|
-
}));
|
|
634
|
-
}
|
|
635
|
-
async writeFile(t, e, r, i = 432) {
|
|
636
|
-
return new Promise((n, s) => {
|
|
637
|
-
t.writeFile(e, r, { mode: i }, (a) => {
|
|
638
|
-
if (a)
|
|
639
|
-
return s(new Error(`ssh.writeFile: err ${a}, remotePath: ${e}`));
|
|
640
|
-
n(!0);
|
|
641
|
-
});
|
|
642
|
-
});
|
|
643
|
-
}
|
|
644
|
-
uploadFileUsingExistingSftp(t, e, r, i = 432) {
|
|
645
|
-
return new Promise((n, s) => {
|
|
646
|
-
rt(e).then(async (a) => this.writeFile(t, r, a, i).then(() => {
|
|
647
|
-
n(void 0);
|
|
648
|
-
}).catch((c) => {
|
|
649
|
-
const l = `uploadFileUsingExistingSftp: ${c}`;
|
|
650
|
-
this.logger.error(l), s(new Error(l));
|
|
651
|
-
}));
|
|
652
|
-
});
|
|
653
|
-
}
|
|
654
|
-
async __uploadDirectory(t, e, r, i = 432) {
|
|
655
|
-
return new Promise((n, s) => {
|
|
656
|
-
O.readdir(e, async (a, c) => {
|
|
657
|
-
if (a)
|
|
658
|
-
return s(new Error(`ssh.__uploadDir: err ${a}, localDir: ${e}, remoteDir: ${r}`));
|
|
659
|
-
try {
|
|
660
|
-
await this.__createRemoteDirectory(t, r);
|
|
661
|
-
for (const l of c) {
|
|
662
|
-
const d = h.join(e, l), u = `${r}/${l}`;
|
|
663
|
-
O.lstatSync(d).isDirectory() ? await this.__uploadDirectory(t, d, u, i) : await this.uploadFileUsingExistingSftp(t, d, u, i);
|
|
664
|
-
}
|
|
665
|
-
n();
|
|
666
|
-
} catch (l) {
|
|
667
|
-
const d = `ssh.__uploadDir: catched err ${l}`;
|
|
668
|
-
this.logger.error(d), s(new Error(d));
|
|
669
|
-
}
|
|
670
|
-
});
|
|
671
|
-
});
|
|
672
|
-
}
|
|
673
|
-
/**
|
|
674
|
-
* Uploads a local directory and its contents (including subdirectories) to the remote server via SFTP.
|
|
675
|
-
* @param localDir - The path to the local directory to upload.
|
|
676
|
-
* @param remoteDir - The path to the remote directory on the server.
|
|
677
|
-
* @returns A promise that resolves when the directory and its contents are uploaded.
|
|
678
|
-
*/
|
|
679
|
-
async uploadDirectory(t, e, r = 432) {
|
|
680
|
-
return new Promise((i, n) => {
|
|
681
|
-
this.withSftp(async (s) => {
|
|
682
|
-
try {
|
|
683
|
-
await this.__uploadDirectory(s, t, e, r), i();
|
|
684
|
-
} catch (a) {
|
|
685
|
-
n(new Error(`ssh.uploadDirectory: ${a}`));
|
|
686
|
-
}
|
|
687
|
-
});
|
|
688
|
-
});
|
|
689
|
-
}
|
|
690
|
-
/**
|
|
691
|
-
* Ensures that a remote directory and all its parent directories exist.
|
|
692
|
-
* @param sftp - The SFTP wrapper.
|
|
693
|
-
* @param remotePath - The path to the remote directory.
|
|
694
|
-
* @returns A promise that resolves when the directory is created.
|
|
695
|
-
*/
|
|
696
|
-
__createRemoteDirectory(t, e) {
|
|
697
|
-
return new Promise((r, i) => {
|
|
698
|
-
const n = e.split("/");
|
|
699
|
-
let s = "";
|
|
700
|
-
const a = (c) => {
|
|
701
|
-
if (c >= n.length)
|
|
702
|
-
return r();
|
|
703
|
-
s += `${n[c]}/`, t.stat(s, (l) => {
|
|
704
|
-
l ? t.mkdir(s, (d) => {
|
|
705
|
-
if (d)
|
|
706
|
-
return i(new Error(`ssh.__createRemDir: err ${d}, remotePath: ${e}`));
|
|
707
|
-
a(c + 1);
|
|
708
|
-
}) : a(c + 1);
|
|
709
|
-
});
|
|
710
|
-
};
|
|
711
|
-
a(0);
|
|
712
|
-
});
|
|
713
|
-
}
|
|
714
|
-
/**
|
|
715
|
-
* Ensures that a remote directory and all its parent directories exist.
|
|
716
|
-
* @param sftp - The SFTP wrapper.
|
|
717
|
-
* @param remotePath - The path to the remote directory.
|
|
718
|
-
* @returns A promise that resolves when the directory is created.
|
|
719
|
-
*/
|
|
720
|
-
ensureRemoteDirCreated(t, e = 493) {
|
|
721
|
-
return this.withSftp(async (r) => {
|
|
722
|
-
const i = t.split("/");
|
|
723
|
-
let n = "";
|
|
724
|
-
for (const s of i) {
|
|
725
|
-
n += `${s}/`;
|
|
726
|
-
try {
|
|
727
|
-
await new Promise((a, c) => {
|
|
728
|
-
r.stat(n, (l) => {
|
|
729
|
-
if (!l) return a();
|
|
730
|
-
r.mkdir(n, { mode: e }, (d) => {
|
|
731
|
-
if (d)
|
|
732
|
-
return c(new Error(`ssh.createRemoteDir: err ${d}, remotePath: ${t}`));
|
|
733
|
-
a();
|
|
734
|
-
});
|
|
735
|
-
});
|
|
736
|
-
});
|
|
737
|
-
} catch (a) {
|
|
738
|
-
throw console.error(`Failed to create directory: ${n}`, a), a;
|
|
739
|
-
}
|
|
740
|
-
}
|
|
741
|
-
});
|
|
742
|
-
}
|
|
743
|
-
/**
|
|
744
|
-
* Downloads a file from the remote server to a local path via SFTP.
|
|
745
|
-
* @param remotePath - The remote file path on the server.
|
|
746
|
-
* @param localPath - The local file path to save the file.
|
|
747
|
-
* @returns A promise resolving with `true` if the file was successfully downloaded.
|
|
748
|
-
*/
|
|
749
|
-
async downloadFile(t, e) {
|
|
750
|
-
return this.withSftp(async (r) => new Promise((i, n) => {
|
|
751
|
-
r.fastGet(t, e, (s) => {
|
|
752
|
-
if (s)
|
|
753
|
-
return n(new Error(`ssh.downloadFile: err ${s}, remotePath: ${t}, localPath: ${e}`));
|
|
754
|
-
i(!0);
|
|
755
|
-
});
|
|
756
|
-
}));
|
|
757
|
-
}
|
|
758
|
-
/**
|
|
759
|
-
* Closes the SSH client connection and forwarded ports.
|
|
760
|
-
*/
|
|
761
|
-
close() {
|
|
762
|
-
this.closeForwardedPorts(), this.client.end();
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
async function Bt(o, t, e, r) {
|
|
766
|
-
return new Promise((i, n) => {
|
|
767
|
-
o.on("ready", () => {
|
|
768
|
-
i(o);
|
|
769
|
-
}), o.on("error", (s) => {
|
|
770
|
-
n(new Error(`ssh.connect: ${s}`));
|
|
771
|
-
}), o.on("close", () => {
|
|
772
|
-
}), o.connect(t), o.setNoDelay(!0);
|
|
773
|
-
});
|
|
774
|
-
}
|
|
775
|
-
async function It(o, t, e, r, i, n) {
|
|
776
|
-
return new Promise((s, a) => {
|
|
777
|
-
t.forwardOut(e, r, i, n, (c, l) => c ? (o.error(`forwardOut.error: ${c}`), a(c)) : s(l));
|
|
778
|
-
});
|
|
779
|
-
}
|
|
780
|
-
const Tt = "minio-2024-12-18T13-15-44Z", Mt = "supervisord-0.7.3", Ht = "supervisord_0.7.3_Linux_64-bit";
|
|
781
|
-
function y(o) {
|
|
782
|
-
return h.join(o, ".platforma_ssh");
|
|
783
|
-
}
|
|
784
|
-
function b(o) {
|
|
785
|
-
return h.join(y(o), "binaries");
|
|
786
|
-
}
|
|
787
|
-
function jt(o, t) {
|
|
788
|
-
return h.join(b(o), `pl-${N()}-${C(t)}`);
|
|
789
|
-
}
|
|
790
|
-
function q(o, t) {
|
|
791
|
-
return h.join(jt(o, t), "binaries");
|
|
792
|
-
}
|
|
793
|
-
function I(o, t) {
|
|
794
|
-
return h.join(q(o, t), "platforma");
|
|
795
|
-
}
|
|
796
|
-
function Gt(o, t) {
|
|
797
|
-
return h.join(q(o, t), "free-port");
|
|
798
|
-
}
|
|
799
|
-
function W(o, t) {
|
|
800
|
-
return h.join(b(o), `minio-2024-12-18T13-15-44Z-${C(t)}`);
|
|
801
|
-
}
|
|
802
|
-
function Jt(o, t) {
|
|
803
|
-
return h.join(W(o, t), "minio");
|
|
804
|
-
}
|
|
805
|
-
function Lt(o, t) {
|
|
806
|
-
return h.join(b(o), `supervisord-0.7.3-${C(t)}`, Ht);
|
|
807
|
-
}
|
|
808
|
-
function K(o, t) {
|
|
809
|
-
return h.join(Lt(o, t), "supervisord");
|
|
810
|
-
}
|
|
811
|
-
function Z(o) {
|
|
812
|
-
return h.join(y(o), "supervisor.conf");
|
|
813
|
-
}
|
|
814
|
-
function T(o) {
|
|
815
|
-
return h.join(y(o), "connection.txt");
|
|
816
|
-
}
|
|
817
|
-
function zt(o) {
|
|
818
|
-
return h.join(y(o), "platforma_cli_logs.log");
|
|
819
|
-
}
|
|
820
|
-
async function Vt(o, t, e) {
|
|
821
|
-
const r = await B(o, t, e, "--daemon");
|
|
822
|
-
if (r.stderr)
|
|
823
|
-
throw new Error(`Can not run ssh Platforma ${r.stderr}`);
|
|
824
|
-
}
|
|
825
|
-
async function qt(o, t, e) {
|
|
826
|
-
const r = await B(o, t, e, "ctl shutdown");
|
|
827
|
-
if (r.stderr)
|
|
828
|
-
throw new Error(`Can not stop ssh Platforma ${r.stderr}`);
|
|
829
|
-
}
|
|
830
|
-
function E(o, t) {
|
|
831
|
-
return t ? o.platforma && o.minio : o.platforma;
|
|
832
|
-
}
|
|
833
|
-
function Wt(o) {
|
|
834
|
-
return o.execError === void 0;
|
|
835
|
-
}
|
|
836
|
-
async function Kt(o, t, e, r) {
|
|
837
|
-
let i;
|
|
838
|
-
try {
|
|
839
|
-
i = await B(t, e, r, "ctl status");
|
|
840
|
-
} catch (c) {
|
|
841
|
-
return { execError: String(c) };
|
|
842
|
-
}
|
|
843
|
-
if (i.stderr)
|
|
844
|
-
return o.info(`supervisord ctl status: stderr occurred: ${i.stderr}, stdout: ${i.stdout}`), { rawResult: i };
|
|
845
|
-
const n = M(i.stdout, "platforma"), s = M(i.stdout, "minio"), a = {
|
|
846
|
-
rawResult: i,
|
|
847
|
-
platforma: n,
|
|
848
|
-
minio: s
|
|
849
|
-
};
|
|
850
|
-
return a.minio || o.warn("Minio is not running on the server"), a.platforma || o.warn("Platforma is not running on the server"), a;
|
|
851
|
-
}
|
|
852
|
-
function Zt(o, t, e, r) {
|
|
853
|
-
const i = F(16).toString("hex"), n = o;
|
|
854
|
-
return `
|
|
855
|
-
[supervisord]
|
|
856
|
-
logfile=${t}/supervisord.log
|
|
857
|
-
loglevel=info
|
|
858
|
-
pidfile=${t}/supervisord.pid
|
|
859
|
-
|
|
860
|
-
[inet_http_server]
|
|
861
|
-
port=127.0.0.1:${n}
|
|
862
|
-
username=default-user
|
|
863
|
-
password=${i}
|
|
864
|
-
|
|
865
|
-
[supervisorctl]
|
|
866
|
-
serverurl=http://127.0.0.1:${n}
|
|
867
|
-
username=default-user
|
|
868
|
-
password=${i}
|
|
869
|
-
|
|
870
|
-
[program:platforma]
|
|
871
|
-
autostart=true
|
|
872
|
-
command=${r} --config ${e}
|
|
873
|
-
directory=${t}
|
|
874
|
-
autorestart=true
|
|
875
|
-
stdout_logfile=${t}/platforma_cli_logs.log
|
|
876
|
-
stdout_logfile_maxbytes=10000
|
|
877
|
-
stdout_logfile_backups=10
|
|
878
|
-
redirect_stderr=true
|
|
879
|
-
`;
|
|
880
|
-
}
|
|
881
|
-
function Xt(o, t, e, r, i, n, s) {
|
|
882
|
-
const a = Object.entries(t).map(([d, u]) => `${d}="${u}"`).join(","), c = F(16).toString("hex"), l = e;
|
|
883
|
-
return `
|
|
884
|
-
[supervisord]
|
|
885
|
-
logfile=${r}/supervisord.log
|
|
886
|
-
loglevel=info
|
|
887
|
-
pidfile=${r}/supervisord.pid
|
|
888
|
-
|
|
889
|
-
[inet_http_server]
|
|
890
|
-
port=127.0.0.1:${l}
|
|
891
|
-
username=default-user
|
|
892
|
-
password=${c}
|
|
893
|
-
|
|
894
|
-
[supervisorctl]
|
|
895
|
-
serverurl=http://127.0.0.1:${l}
|
|
896
|
-
username=default-user
|
|
897
|
-
password=${c}
|
|
898
|
-
|
|
899
|
-
[program:platforma]
|
|
900
|
-
autostart=true
|
|
901
|
-
depends_on=minio
|
|
902
|
-
command=${s} --config ${i}
|
|
903
|
-
directory=${r}
|
|
904
|
-
autorestart=true
|
|
905
|
-
|
|
906
|
-
[program:minio]
|
|
907
|
-
autostart=true
|
|
908
|
-
environment=${a}
|
|
909
|
-
command=${n} server ${o}
|
|
910
|
-
directory=${r}
|
|
911
|
-
autorestart=true
|
|
912
|
-
`;
|
|
913
|
-
}
|
|
914
|
-
async function B(o, t, e, r) {
|
|
915
|
-
const i = K(t, e), n = Z(t), s = `${i} --configuration ${n} ${r}`;
|
|
916
|
-
return await o.exec(s);
|
|
917
|
-
}
|
|
918
|
-
function M(o, t) {
|
|
919
|
-
return ((i) => i.replace(/\x1B\[[0-9;]*m/g, ""))(o).split(`
|
|
920
|
-
`).some((i) => {
|
|
921
|
-
const [n, s] = i.trim().split(/\s{2,}/);
|
|
922
|
-
return n === t && s === "Running";
|
|
923
|
-
});
|
|
924
|
-
}
|
|
925
|
-
const S = f.object({
|
|
926
|
-
local: f.number(),
|
|
927
|
-
remote: f.number()
|
|
928
|
-
}), Yt = f.object({
|
|
929
|
-
grpc: S,
|
|
930
|
-
http: S.optional(),
|
|
931
|
-
monitoring: S,
|
|
932
|
-
debug: S,
|
|
933
|
-
/** @deprecated */
|
|
934
|
-
minioPort: S,
|
|
935
|
-
/** @deprecated */
|
|
936
|
-
minioConsolePort: S
|
|
937
|
-
}), Qt = f.object({
|
|
938
|
-
plUser: f.string(),
|
|
939
|
-
plPassword: f.string(),
|
|
940
|
-
ports: Yt,
|
|
941
|
-
// It's false by default because it was added later,
|
|
942
|
-
// and in some deployments there won't be useGlobalAccess flag in the file.
|
|
943
|
-
useGlobalAccess: f.boolean().default(!1),
|
|
944
|
-
// We added the field afterwards, the pl backend was this version.
|
|
945
|
-
plVersion: f.string().default("1.18.3"),
|
|
946
|
-
// It's true by default because it was added later and previous installation use minio.
|
|
947
|
-
minioIsUsed: f.boolean().default(!0)
|
|
948
|
-
});
|
|
949
|
-
function te(o, t, e, r, i, n) {
|
|
950
|
-
return {
|
|
951
|
-
plUser: o,
|
|
952
|
-
plPassword: t,
|
|
953
|
-
ports: e,
|
|
954
|
-
useGlobalAccess: r,
|
|
955
|
-
plVersion: i,
|
|
956
|
-
minioIsUsed: n
|
|
957
|
-
};
|
|
958
|
-
}
|
|
959
|
-
function ee(o) {
|
|
960
|
-
return Qt.parse(JSON.parse(o));
|
|
961
|
-
}
|
|
962
|
-
function re(o) {
|
|
963
|
-
return JSON.stringify(o, void 0, 2);
|
|
964
|
-
}
|
|
965
|
-
const H = 2.28;
|
|
966
|
-
class X {
|
|
967
|
-
constructor(t, e, r) {
|
|
968
|
-
p(this, "initState", { step: "init" });
|
|
969
|
-
this.logger = t, this.sshClient = e, this.username = r;
|
|
970
|
-
}
|
|
971
|
-
info() {
|
|
972
|
-
return {
|
|
973
|
-
username: this.username,
|
|
974
|
-
initState: this.initState
|
|
975
|
-
};
|
|
976
|
-
}
|
|
977
|
-
static async init(t, e) {
|
|
978
|
-
try {
|
|
979
|
-
const r = await U.init(t, e);
|
|
980
|
-
return new X(t, r, m(e.username));
|
|
981
|
-
} catch (r) {
|
|
982
|
-
throw t.error(`Connection error in SshClient.init: ${r}`), r;
|
|
983
|
-
}
|
|
984
|
-
}
|
|
985
|
-
cleanUp() {
|
|
986
|
-
this.sshClient.close();
|
|
987
|
-
}
|
|
988
|
-
/** Provides an info if the platforma and minio are running along with the debug info. */
|
|
989
|
-
async isAlive() {
|
|
990
|
-
const t = await this.getArch(), e = await this.getUserHomeDirectory();
|
|
991
|
-
return await Kt(this.logger, this.sshClient, e, t.arch);
|
|
992
|
-
}
|
|
993
|
-
/** Starts all the services on the server.
|
|
994
|
-
* Idempotent semantic: we could call it several times. */
|
|
995
|
-
async start(t) {
|
|
996
|
-
const e = await this.getArch(), r = await this.getUserHomeDirectory();
|
|
997
|
-
try {
|
|
998
|
-
if (!E(await this.isAlive(), t))
|
|
999
|
-
return await Vt(this.sshClient, r, e.arch), await this.checkIsAliveWithInterval(t);
|
|
1000
|
-
} catch (i) {
|
|
1001
|
-
let n = `SshPl.start: ${i}`, s = "";
|
|
1002
|
-
try {
|
|
1003
|
-
s = await this.sshClient.readFile(zt(r)), n += `, platforma cli logs: ${s}`;
|
|
1004
|
-
} catch (a) {
|
|
1005
|
-
n += `, Can not read platforma cli logs: ${a}`;
|
|
1006
|
-
}
|
|
1007
|
-
throw this.logger.error(n), new Error(n);
|
|
1008
|
-
}
|
|
1009
|
-
}
|
|
1010
|
-
/** Stops all the services on the server.
|
|
1011
|
-
* Idempotent semantic: we could call it several times. */
|
|
1012
|
-
async stop() {
|
|
1013
|
-
const t = await this.getArch(), e = await this.getUserHomeDirectory();
|
|
1014
|
-
try {
|
|
1015
|
-
const r = await this.isAlive();
|
|
1016
|
-
if (Wt(r)) {
|
|
1017
|
-
await qt(this.sshClient, e, t.arch);
|
|
1018
|
-
const i = r.minio === !0;
|
|
1019
|
-
return await this.checkIsAliveWithInterval(i, 1e3, 15, !1);
|
|
1020
|
-
}
|
|
1021
|
-
} catch (r) {
|
|
1022
|
-
const i = `PlSsh.stop: ${r}`;
|
|
1023
|
-
throw this.logger.error(i), new Error(i);
|
|
1024
|
-
}
|
|
1025
|
-
}
|
|
1026
|
-
/** Stops the services, deletes a directory with the state and closes SSH connection. */
|
|
1027
|
-
async reset() {
|
|
1028
|
-
return await this.stopAndClean(), this.cleanUp(), !0;
|
|
1029
|
-
}
|
|
1030
|
-
/** Stops platforma and deletes its state. */
|
|
1031
|
-
async stopAndClean() {
|
|
1032
|
-
const t = await this.getUserHomeDirectory();
|
|
1033
|
-
this.logger.info("pl.reset: Stop Platforma on the server"), await this.stop(), this.logger.info(`pl.reset: Deleting Platforma workDir ${y(t)} on the server`), await this.sshClient.deleteFolder(y(t));
|
|
1034
|
-
}
|
|
1035
|
-
/** Downloads binaries and untar them on the server,
|
|
1036
|
-
* generates all the configs, creates necessary dirs,
|
|
1037
|
-
* and finally starts all the services. */
|
|
1038
|
-
async platformaInit(t) {
|
|
1039
|
-
const e = { localWorkdir: t.localWorkdir, step: "init" }, { onProgress: r } = t, i = {
|
|
1040
|
-
...ie,
|
|
1041
|
-
...t
|
|
1042
|
-
};
|
|
1043
|
-
e.plBinaryOps = i.plBinary;
|
|
1044
|
-
try {
|
|
1045
|
-
return await this.doStepDetectArch(e, r), await this.doStepDetectHome(e, r), await this.doStepReadExistedConfig(e, i, r) ? (await this.doStepStopExistedPlatforma(e, r), await (r == null ? void 0 : r("Installation platforma...")), await this.doStepDownloadBinaries(e, r, i), await this.doStepFetchPorts(e), await this.doStepGenerateNewConfig(e, r, i), await this.doStepCreateFoldersAndSaveFiles(e, r), await this.doStepConfigureSupervisord(e, r), await this.doStepSaveNewConnectionInfo(e, r, i), await this.doStepStartPlatforma(e, r), e.connectionInfo) : (await (r == null ? void 0 : r("Platforma is already running. Skipping initialization.")), e.existedSettings);
|
|
1046
|
-
} catch (n) {
|
|
1047
|
-
const s = `SshPl.platformaInit: ${n}, state: ${JSON.stringify(this.removeSensitiveData(e))}`;
|
|
1048
|
-
throw this.logger.error(s), new Error(s);
|
|
1049
|
-
}
|
|
1050
|
-
}
|
|
1051
|
-
async doStepStopExistedPlatforma(t, e) {
|
|
1052
|
-
t.step = "stopExistedPlatforma", E(t.alive, t.shouldUseMinio ?? !1) && (await (e == null ? void 0 : e("Stopping services...")), await this.stop());
|
|
1053
|
-
}
|
|
1054
|
-
removeSensitiveData(t) {
|
|
1055
|
-
const e = { ...t };
|
|
1056
|
-
return e.generatedConfig = { ...e.generatedConfig, filesToCreate: { skipped: "sanitized" } }, e;
|
|
1057
|
-
}
|
|
1058
|
-
async doStepStartPlatforma(t, e) {
|
|
1059
|
-
t.step = "startPlatforma", await (e == null ? void 0 : e("Starting Platforma on the server...")), await this.start(t.shouldUseMinio ?? !1), t.started = !0, this.initState = t, await (e == null ? void 0 : e("Platforma has been started successfully."));
|
|
1060
|
-
}
|
|
1061
|
-
async doStepSaveNewConnectionInfo(t, e, r) {
|
|
1062
|
-
t.step = "saveNewConnectionInfo";
|
|
1063
|
-
const i = t.generatedConfig;
|
|
1064
|
-
await (e == null ? void 0 : e("Saving connection information...")), t.connectionInfo = te(
|
|
1065
|
-
i.plUser,
|
|
1066
|
-
i.plPassword,
|
|
1067
|
-
t.ports,
|
|
1068
|
-
m(r.useGlobalAccess),
|
|
1069
|
-
r.plBinary.version,
|
|
1070
|
-
t.shouldUseMinio ?? !1
|
|
1071
|
-
), await this.sshClient.writeFileOnTheServer(
|
|
1072
|
-
T(t.remoteHome),
|
|
1073
|
-
re(t.connectionInfo)
|
|
1074
|
-
), await (e == null ? void 0 : e("Connection information saved."));
|
|
1075
|
-
}
|
|
1076
|
-
async doStepConfigureSupervisord(t, e) {
|
|
1077
|
-
await (e == null ? void 0 : e("Writing supervisord configuration...")), t.step = "configureSupervisord";
|
|
1078
|
-
const r = t.generatedConfig;
|
|
1079
|
-
let i;
|
|
1080
|
-
if (t.shouldUseMinio ? i = Xt(
|
|
1081
|
-
r.minioConfig.storageDir,
|
|
1082
|
-
r.minioConfig.envs,
|
|
1083
|
-
await this.getFreePortForPlatformaOnServer(t.remoteHome, t.arch),
|
|
1084
|
-
r.workingDir,
|
|
1085
|
-
r.plConfig.configPath,
|
|
1086
|
-
t.binPaths.minioRelPath,
|
|
1087
|
-
t.binPaths.downloadedPl
|
|
1088
|
-
) : i = Zt(
|
|
1089
|
-
await this.getFreePortForPlatformaOnServer(t.remoteHome, t.arch),
|
|
1090
|
-
r.workingDir,
|
|
1091
|
-
r.plConfig.configPath,
|
|
1092
|
-
t.binPaths.downloadedPl
|
|
1093
|
-
), !await this.sshClient.writeFileOnTheServer(Z(t.remoteHome), i))
|
|
1094
|
-
throw new Error(`Can not write supervisord config on the server ${y(t.remoteHome)}`);
|
|
1095
|
-
await (e == null ? void 0 : e("Supervisord configuration written."));
|
|
1096
|
-
}
|
|
1097
|
-
async doStepCreateFoldersAndSaveFiles(t, e) {
|
|
1098
|
-
t.step = "createFoldersAndSaveFiles";
|
|
1099
|
-
const r = t.generatedConfig;
|
|
1100
|
-
await (e == null ? void 0 : e("Generating folder structure..."));
|
|
1101
|
-
for (const [i, n] of Object.entries(r.filesToCreate))
|
|
1102
|
-
await this.sshClient.writeFileOnTheServer(i, n), this.logger.info(`Created file ${i}`);
|
|
1103
|
-
for (const i of r.dirsToCreate)
|
|
1104
|
-
await this.sshClient.ensureRemoteDirCreated(i), this.logger.info(`Created directory ${i}`);
|
|
1105
|
-
await (e == null ? void 0 : e("Folder structure created."));
|
|
1106
|
-
}
|
|
1107
|
-
async doStepGenerateNewConfig(t, e, r) {
|
|
1108
|
-
t.step = "generateNewConfig", await (e == null ? void 0 : e("Generating new config..."));
|
|
1109
|
-
const i = await ut({
|
|
1110
|
-
logger: this.logger,
|
|
1111
|
-
workingDir: y(t.remoteHome),
|
|
1112
|
-
portsMode: {
|
|
1113
|
-
type: "customWithMinio",
|
|
1114
|
-
ports: {
|
|
1115
|
-
debug: t.ports.debug.remote,
|
|
1116
|
-
grpc: t.ports.grpc.remote,
|
|
1117
|
-
http: t.ports.http.remote,
|
|
1118
|
-
minio: t.ports.minioPort.remote,
|
|
1119
|
-
minioConsole: t.ports.minioConsolePort.remote,
|
|
1120
|
-
monitoring: t.ports.monitoring.remote,
|
|
1121
|
-
httpLocal: t.ports.http.local,
|
|
1122
|
-
grpcLocal: t.ports.grpc.local,
|
|
1123
|
-
minioLocal: t.ports.minioPort.local
|
|
1124
|
-
}
|
|
1125
|
-
},
|
|
1126
|
-
licenseMode: r.license,
|
|
1127
|
-
useGlobalAccess: m(r.useGlobalAccess),
|
|
1128
|
-
plConfigPostprocessing: r.plConfigPostprocessing,
|
|
1129
|
-
useMinio: t.shouldUseMinio ?? !1
|
|
1130
|
-
});
|
|
1131
|
-
t.generatedConfig = { ...i }, await (e == null ? void 0 : e("New config generated"));
|
|
1132
|
-
}
|
|
1133
|
-
async doStepFetchPorts(t) {
|
|
1134
|
-
var e;
|
|
1135
|
-
if (t.step = "fetchPorts", t.ports = await this.fetchPorts(t.remoteHome, t.arch), !t.ports.debug.remote || !t.ports.grpc.remote || !t.ports.minioPort.remote || !t.ports.minioConsolePort.remote || !t.ports.monitoring.remote || !((e = t.ports.http) != null && e.remote))
|
|
1136
|
-
throw new Error("SshPl.platformaInit: remote ports are not defined");
|
|
1137
|
-
}
|
|
1138
|
-
async doStepDownloadBinaries(t, e, r) {
|
|
1139
|
-
t.step = "downloadBinaries", await (e == null ? void 0 : e("Downloading and uploading required binaries..."));
|
|
1140
|
-
const i = await ne(this.logger, this.sshClient);
|
|
1141
|
-
if (i < H)
|
|
1142
|
-
throw new Error(`glibc version ${i} is too old. Version ${H} or higher is required for Platforma.`);
|
|
1143
|
-
const n = await this.downloadBinariesAndUploadToTheServer(
|
|
1144
|
-
r.localWorkdir,
|
|
1145
|
-
r.plBinary,
|
|
1146
|
-
t.remoteHome,
|
|
1147
|
-
t.arch,
|
|
1148
|
-
t.shouldUseMinio ?? !1
|
|
1149
|
-
);
|
|
1150
|
-
await (e == null ? void 0 : e("All required binaries have been downloaded and uploaded.")), t.binPaths = { ...n, history: void 0 }, t.downloadedBinaries = n.history;
|
|
1151
|
-
}
|
|
1152
|
-
async doStepDetectArch(t, e) {
|
|
1153
|
-
t.step = "detectArch", await (e == null ? void 0 : e("Detecting server architecture...")), t.arch = await this.getArch(), await (e == null ? void 0 : e("Server architecture detected."));
|
|
1154
|
-
}
|
|
1155
|
-
async doStepDetectHome(t, e) {
|
|
1156
|
-
t.step = "detectHome", await (e == null ? void 0 : e("Fetching user home directory...")), t.remoteHome = await this.getUserHomeDirectory(), await (e == null ? void 0 : e("User home directory retrieved."));
|
|
1157
|
-
}
|
|
1158
|
-
async doStepReadExistedConfig(t, e, r) {
|
|
1159
|
-
var s;
|
|
1160
|
-
if (t.step = "checkAlive", await (r == null ? void 0 : r("Checking platform status...")), t.alive = await this.isAlive(), !((s = t.alive) != null && s.platforma))
|
|
1161
|
-
return !0;
|
|
1162
|
-
if (await (r == null ? void 0 : r("All required services are running.")), t.existedSettings = await this.readExistedConfig(t.remoteHome), !t.existedSettings)
|
|
1163
|
-
throw new Error("SshPl.platformaInit: platforma is alive but existed settings are not found");
|
|
1164
|
-
const i = t.existedSettings.useGlobalAccess == e.useGlobalAccess, n = t.existedSettings.plVersion == e.plBinary.version;
|
|
1165
|
-
return t.needRestart = !(i && n), this.logger.info(`SshPl.platformaInit: need restart? ${t.needRestart}`), t.shouldUseMinio = t.existedSettings.minioIsUsed, t.shouldUseMinio ? this.logger.info("SshPl.platformaInit: minio is used") : this.logger.info("SshPl.platformaInit: minio is not used"), t.needRestart ? (await (r == null ? void 0 : r("Stopping services...")), await this.stop(), !0) : (await (r == null ? void 0 : r("Server setup completed.")), !1);
|
|
1166
|
-
}
|
|
1167
|
-
async downloadBinariesAndUploadToTheServer(t, e, r, i, n) {
|
|
1168
|
-
const s = [];
|
|
1169
|
-
try {
|
|
1170
|
-
const a = await this.downloadAndUntar(
|
|
1171
|
-
t,
|
|
1172
|
-
r,
|
|
1173
|
-
i,
|
|
1174
|
-
"pl",
|
|
1175
|
-
`pl-${e.version}`
|
|
1176
|
-
);
|
|
1177
|
-
s.push(a);
|
|
1178
|
-
const c = await this.downloadAndUntar(
|
|
1179
|
-
t,
|
|
1180
|
-
r,
|
|
1181
|
-
i,
|
|
1182
|
-
"supervisord",
|
|
1183
|
-
Mt
|
|
1184
|
-
);
|
|
1185
|
-
s.push(c);
|
|
1186
|
-
const l = Jt(r, i.arch);
|
|
1187
|
-
if (n) {
|
|
1188
|
-
const d = await this.downloadAndUntar(
|
|
1189
|
-
t,
|
|
1190
|
-
r,
|
|
1191
|
-
i,
|
|
1192
|
-
"minio",
|
|
1193
|
-
Tt
|
|
1194
|
-
);
|
|
1195
|
-
s.push(d), await this.sshClient.chmod(l, 488);
|
|
1196
|
-
}
|
|
1197
|
-
return {
|
|
1198
|
-
history: s,
|
|
1199
|
-
minioRelPath: n ? l : void 0,
|
|
1200
|
-
downloadedPl: I(r, i.arch)
|
|
1201
|
-
};
|
|
1202
|
-
} catch (a) {
|
|
1203
|
-
const c = `SshPl.downloadBinariesAndUploadToServer: ${a}, state: ${JSON.stringify(s)}`;
|
|
1204
|
-
throw this.logger.error(c), a;
|
|
1205
|
-
}
|
|
1206
|
-
}
|
|
1207
|
-
/** We have to extract pl in the remote server,
|
|
1208
|
-
* because Windows doesn't support symlinks
|
|
1209
|
-
* that are found in Linux pl binaries tgz archive.
|
|
1210
|
-
* For this reason, we extract all to the remote server.
|
|
1211
|
-
* It requires `tar` to be installed on the server
|
|
1212
|
-
* (it's not installed for Rocky Linux for example). */
|
|
1213
|
-
async downloadAndUntar(t, e, r, i, n) {
|
|
1214
|
-
const s = {};
|
|
1215
|
-
s.binBasePath = b(e), await this.sshClient.ensureRemoteDirCreated(s.binBasePath), s.binBasePathCreated = !0;
|
|
1216
|
-
let a = null;
|
|
1217
|
-
const c = 5;
|
|
1218
|
-
for (let d = 1; d <= c; d++)
|
|
1219
|
-
try {
|
|
1220
|
-
a = await gt(
|
|
1221
|
-
this.logger,
|
|
1222
|
-
t,
|
|
1223
|
-
i,
|
|
1224
|
-
n,
|
|
1225
|
-
r.arch,
|
|
1226
|
-
r.platform
|
|
1227
|
-
);
|
|
1228
|
-
break;
|
|
1229
|
-
} catch (u) {
|
|
1230
|
-
if (await x(300), d == c)
|
|
1231
|
-
throw new Error(`downloadAndUntar: ${c} attempts, last error: ${u}`);
|
|
1232
|
-
}
|
|
1233
|
-
s.downloadResult = m(a), s.localArchivePath = h.resolve(s.downloadResult.archivePath), s.remoteDir = h.join(s.binBasePath, s.downloadResult.baseName), s.remoteArchivePath = s.remoteDir + ".tgz", await this.sshClient.ensureRemoteDirCreated(s.remoteDir), await this.sshClient.uploadFile(s.localArchivePath, s.remoteArchivePath), s.uploadDone = !0;
|
|
1234
|
-
try {
|
|
1235
|
-
await this.sshClient.exec("hash tar");
|
|
1236
|
-
} catch {
|
|
1237
|
-
throw new Error("tar is not installed on the server. Please install it before running Platforma.");
|
|
1238
|
-
}
|
|
1239
|
-
const l = await this.sshClient.exec(
|
|
1240
|
-
`tar --warning=no-all -xvf ${s.remoteArchivePath} --directory=${s.remoteDir}`
|
|
1241
|
-
);
|
|
1242
|
-
if (l.stderr)
|
|
1243
|
-
throw new Error(`downloadAndUntar: untar: stderr occurred: ${l.stderr}, stdout: ${l.stdout}`);
|
|
1244
|
-
return s.untarDone = !0, s;
|
|
1245
|
-
}
|
|
1246
|
-
async needDownload(t, e) {
|
|
1247
|
-
const r = K(t, e.arch), i = W(t, e.arch), n = I(t, e.arch);
|
|
1248
|
-
return !await this.sshClient.checkFileExists(n) || !await this.sshClient.checkFileExists(i) || !await this.sshClient.checkFileExists(r);
|
|
1249
|
-
}
|
|
1250
|
-
async checkIsAliveWithInterval(t, e = 1e3, r = 15, i = !0) {
|
|
1251
|
-
const n = r * e;
|
|
1252
|
-
let s = 0, a = await this.isAlive();
|
|
1253
|
-
for (; i ? !E(a, t) : E(a, t); ) {
|
|
1254
|
-
if (await x(e), s += e, s > n)
|
|
1255
|
-
throw new Error(`isAliveWithInterval: The process did not ${i ? "started" : "stopped"} after ${n} ms. Live status: ${JSON.stringify(a)}`);
|
|
1256
|
-
a = await this.isAlive();
|
|
1257
|
-
}
|
|
1258
|
-
}
|
|
1259
|
-
async readExistedConfig(t) {
|
|
1260
|
-
const e = await this.sshClient.readFile(T(t));
|
|
1261
|
-
return ee(e);
|
|
1262
|
-
}
|
|
1263
|
-
async fetchPorts(t, e) {
|
|
1264
|
-
return {
|
|
1265
|
-
grpc: {
|
|
1266
|
-
local: await $(),
|
|
1267
|
-
remote: await this.getFreePortForPlatformaOnServer(t, e)
|
|
1268
|
-
},
|
|
1269
|
-
monitoring: {
|
|
1270
|
-
local: await $(),
|
|
1271
|
-
remote: await this.getFreePortForPlatformaOnServer(t, e)
|
|
1272
|
-
},
|
|
1273
|
-
debug: {
|
|
1274
|
-
local: await $(),
|
|
1275
|
-
remote: await this.getFreePortForPlatformaOnServer(t, e)
|
|
1276
|
-
},
|
|
1277
|
-
http: {
|
|
1278
|
-
local: await $(),
|
|
1279
|
-
remote: await this.getFreePortForPlatformaOnServer(t, e)
|
|
1280
|
-
},
|
|
1281
|
-
minioPort: {
|
|
1282
|
-
local: await $(),
|
|
1283
|
-
remote: await this.getFreePortForPlatformaOnServer(t, e)
|
|
1284
|
-
},
|
|
1285
|
-
minioConsolePort: {
|
|
1286
|
-
local: await $(),
|
|
1287
|
-
remote: await this.getFreePortForPlatformaOnServer(t, e)
|
|
1288
|
-
}
|
|
1289
|
-
};
|
|
1290
|
-
}
|
|
1291
|
-
async getLocalFreePort() {
|
|
1292
|
-
return new Promise((t) => {
|
|
1293
|
-
const e = G.createServer();
|
|
1294
|
-
e.listen(0, () => {
|
|
1295
|
-
const r = e.address().port;
|
|
1296
|
-
e.close((i) => t(r));
|
|
1297
|
-
});
|
|
1298
|
-
});
|
|
1299
|
-
}
|
|
1300
|
-
async getFreePortForPlatformaOnServer(t, e) {
|
|
1301
|
-
const r = Gt(t, e.arch), { stdout: i, stderr: n } = await this.sshClient.exec(`${r}`);
|
|
1302
|
-
if (n)
|
|
1303
|
-
throw new Error(`getFreePortForPlatformaOnServer: stderr is not empty: ${n}, stdout: ${i}`);
|
|
1304
|
-
return +i;
|
|
1305
|
-
}
|
|
1306
|
-
async getArch() {
|
|
1307
|
-
const { stdout: t, stderr: e } = await this.sshClient.exec("uname -s && uname -m");
|
|
1308
|
-
if (e)
|
|
1309
|
-
throw new Error(`getArch: stderr is not empty: ${e}, stdout: ${t}`);
|
|
1310
|
-
const r = t.split(`
|
|
1311
|
-
`);
|
|
1312
|
-
return {
|
|
1313
|
-
platform: r[0],
|
|
1314
|
-
arch: r[1]
|
|
1315
|
-
};
|
|
1316
|
-
}
|
|
1317
|
-
async getUserHomeDirectory() {
|
|
1318
|
-
const { stdout: t, stderr: e } = await this.sshClient.exec("echo $HOME");
|
|
1319
|
-
if (e) {
|
|
1320
|
-
const r = `/home/${this.username}`;
|
|
1321
|
-
return console.warn(`getUserHomeDirectory: stderr is not empty: ${e}, stdout: ${t}, will get a default home: ${r}`), r;
|
|
1322
|
-
}
|
|
1323
|
-
return t.trim();
|
|
1324
|
-
}
|
|
1325
|
-
}
|
|
1326
|
-
const ie = {
|
|
1327
|
-
useGlobalAccess: !1,
|
|
1328
|
-
plBinary: {
|
|
1329
|
-
type: "Download",
|
|
1330
|
-
version: N()
|
|
1331
|
-
}
|
|
1332
|
-
};
|
|
1333
|
-
async function ne(o, t) {
|
|
1334
|
-
try {
|
|
1335
|
-
const { stdout: e, stderr: r } = await t.exec("ldd --version | head -n 1");
|
|
1336
|
-
if (r)
|
|
1337
|
-
throw new Error(`Failed to check glibc version: ${r}`);
|
|
1338
|
-
return oe(e);
|
|
1339
|
-
} catch (e) {
|
|
1340
|
-
throw o.error(`glibc version check failed: ${e}`), e;
|
|
1341
|
-
}
|
|
1342
|
-
}
|
|
1343
|
-
function oe(o) {
|
|
1344
|
-
const t = o.match(/\d+\.\d+/);
|
|
1345
|
-
if (!t)
|
|
1346
|
-
throw new Error(`Could not parse glibc version from: ${o}`);
|
|
1347
|
-
return parseFloat(t[0]);
|
|
1348
|
-
}
|
|
1349
|
-
export {
|
|
1350
|
-
Qt as ConnectionInfo,
|
|
1351
|
-
Ot as LocalConfigYaml,
|
|
1352
|
-
kt as LocalPl,
|
|
1353
|
-
S as PortPair,
|
|
1354
|
-
U as SshClient,
|
|
1355
|
-
X as SshPl,
|
|
1356
|
-
Yt as SshPlPorts,
|
|
1357
|
-
N as getDefaultPlVersion,
|
|
1358
|
-
Ee as localPlatformaInit,
|
|
1359
|
-
Nt as mergeDefaultOps,
|
|
1360
|
-
te as newConnectionInfo,
|
|
1361
|
-
ee as parseConnectionInfo,
|
|
1362
|
-
oe as parseGlibcVersion,
|
|
1363
|
-
_t as plProcessOps,
|
|
1364
|
-
re as stringifyConnectionInfo
|
|
1365
|
-
};
|
|
1366
|
-
//# sourceMappingURL=index.mjs.map
|