@milaboratories/pl-deployments 2.3.3 → 2.4.0
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/index.js +34 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +683 -585
- package/dist/index.mjs.map +1 -1
- package/dist/ssh/connection_info.d.ts +52 -1
- package/dist/ssh/connection_info.d.ts.map +1 -1
- package/dist/ssh/pl.d.ts +22 -7
- package/dist/ssh/pl.d.ts.map +1 -1
- package/dist/ssh/supervisord.d.ts +4 -2
- package/dist/ssh/supervisord.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/ssh/__tests__/pl-docker.test.ts +13 -10
- package/src/ssh/connection_info.ts +8 -0
- package/src/ssh/pl.ts +268 -138
- package/src/ssh/supervisord.ts +47 -8
package/dist/index.js
CHANGED
|
@@ -1,16 +1,37 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
cmd: ${JSON.stringify([
|
|
3
|
-
wd: ${
|
|
4
|
-
URL: ${
|
|
5
|
-
Save to: ${e}`);const{body:i,statusCode:o}=await
|
|
6
|
-
Archive: ${
|
|
7
|
-
Target dir: ${
|
|
8
|
-
`}})})}static extractAuthMethods(
|
|
1
|
+
"use strict";var at=Object.defineProperty;var ct=(n,t,e)=>t in n?at(n,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):n[t]=e;var w=(n,t,e)=>ct(n,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const lt=require("node:child_process"),p=require("@milaboratories/ts-helpers"),x=require("node:fs"),y=require("node:fs/promises"),u=require("upath"),dt=require("undici"),U=require("node:stream"),ut=require("node:stream/consumers"),ht=require("tar"),pt=require("decompress"),P=require("node:os"),C=require("ssh2"),H=require("node:net"),wt=require("node:dns"),b=require("node:crypto"),g=require("@milaboratories/pl-config"),f=require("zod");function q(n){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(n){for(const e in n)if(e!=="default"){const r=Object.getOwnPropertyDescriptor(n,e);Object.defineProperty(t,e,r.get?r:{enumerable:!0,get:()=>n[e]})}}return t.default=n,Object.freeze(t)}const ft=q(ht),mt=q(P);function yt(n,t){return n.info(`Running:
|
|
2
|
+
cmd: ${JSON.stringify([t.cmd,...t.args])}
|
|
3
|
+
wd: ${t.opts.cwd}`),n.info(" spawning child process"),lt.spawn(t.cmd,t.args,t.opts)}async function k(n){try{return process.kill(n,0),!0}catch{return!1}}function G(n){return process.kill(n,"SIGINT")}async function z(n,t){let r=0;for(;await k(n);)if(await p.sleep(100),r+=100,r>t)throw new Error(`The process did not stopped after ${t} ms.`)}const gt=["linux","macos","windows"];function R(n){switch(n.toLowerCase()){case"darwin":return"macos";case"linux":return"linux";case"win32":return"windows";default:throw new Error(`operating system '${n}' is not currently supported by Platforma ecosystem. The list of OSes supported: `+JSON.stringify(gt))}}const vt=["amd64","arm64"];function S(n){switch(n){case"aarch64":case"aarch64_be":case"arm64":return"arm64";case"x86_64":case"x64":return"amd64";default:throw new Error(`processor architecture '${n}' is not currently supported by Platforma ecosystem. The list of architectures supported: `+JSON.stringify(vt))}}const $t="https://cdn.platforma.bio/software",St="https://cdn-ga.pl-open.science/software";async function Ct(n,t,e,r,i,o){const s=J(e,r,t,S(i),R(o)),{archiveUrl:a,alternativeArchiveGAUrl:c,archivePath:l}=s;try{await F(n,a,l),s.wasDownloadedFrom=a}catch{await F(n,c,l),s.wasDownloadedFrom=c}return s}async function Et(n,t,e,r,i,o){const s=J(e,r,t,S(i),R(o)),{archiveUrl:a,alternativeArchiveGAUrl:c,archivePath:l,archiveType:d,targetFolder:h}=s;try{await F(n,a,l),s.wasDownloadedFrom=a}catch{await F(n,c,l),s.wasDownloadedFrom=c}return await bt(n,l,d,h),s}function J(n,t,e,r,i){const o=`${t}-${r}`,s=Ft[i],a=`${o}.${s}`,c=`${$t}/${n}/${i}/${a}`,l=`${St}/${n}/${i}/${a}`,d=u.join(e,a),h=u.join(e,o);return{archiveUrl:c,alternativeArchiveGAUrl:l,archivePath:d,archiveType:s,targetFolder:h,baseName:o}}async function F(n,t,e){const r={};r.dstArchive=e;try{if(r.fileExisted=await p.fileExists(e),r.fileExisted)return n.info(`Platforma Backend archive download skipped: '${e}' already exists`),r;await y.mkdir(u.dirname(e),{recursive:!0}),r.dirnameCreated=!0,n.info(`Downloading archive:
|
|
4
|
+
URL: ${t}
|
|
5
|
+
Save to: ${e}`);const{body:i,statusCode:o}=await dt.request(t);if(r.statusCode=o,o!=200){const s=await ut.text(i);throw r.errorMsg=`failed to download archive: ${o}, response: ${s.slice(0,1e3)}`,n.error(r.errorMsg),new Error(r.errorMsg)}return r.tmpPath=e+".tmp",await U.Readable.toWeb(i).pipeTo(U.Writable.toWeb(x.createWriteStream(r.tmpPath))),r.wroteTmp=!0,r.tmpExisted=await p.fileExists(r.tmpPath),await y.rename(r.tmpPath,e),r.renamed=!0,r.newExisted=await p.fileExists(e),r}catch(i){const o=`downloadArchive: ${JSON.stringify(i)}, state: ${JSON.stringify(r)}`;throw n.error(o),new Error(o)}}const Pt=".ok";async function bt(n,t,e,r){if(n.info("extracting archive..."),n.info(` archive path: '${t}'`),n.info(` target dir: '${r}'`),!await p.fileExists(t)){const o=`Platforma Backend binary archive not found at '${t}'`;throw n.error(o),new Error(o)}const i=u.join(r,Pt);if(await p.fileExists(i)){n.info(`Platforma Backend binaries unpack skipped: '${r}' exists`);return}switch(await p.fileExists(r)&&(n.info(`Removing previous incompletely unpacked folder: '${r}'`),await y.rm(r,{recursive:!0})),n.info(` creating target dir '${r}'`),await y.mkdir(r,{recursive:!0}),n.info(`Unpacking Platforma Backend archive:
|
|
6
|
+
Archive: ${t}
|
|
7
|
+
Target dir: ${r}`),e){case"tgz":await ft.x({file:t,cwd:r,gzip:!0});break;case"zip":await pt(t,r);break;default:p.assertNever(e)}await y.writeFile(i,"ok"),n.info(" ... unpack done.")}const Ft={linux:"tgz",macos:"tgz",windows:"zip"};function A(){return"1.34.2"}function At(){return{type:"Download",version:A()}}async function Dt(n,t,e){switch(e.type){case"Download":const r=await Et(n,t,"pl",`pl-${e.version}`,P.arch(),P.platform());return u.join(r.baseName,"binaries",Ot[R(P.platform())]);case"Local":return e.path;default:p.assertNever(e)}}const Ot={linux:"platforma",macos:"platforma",windows:"platforma.exe"};function L(n){return u.join(n,"pl_pid")}async function xt(n){if(!await p.fileExists(n))return;const t=await y.readFile(n);return Number(t.toString())}async function kt(n,t){await y.writeFile(n,JSON.stringify(t))}function Rt(){return{}}function Nt(n,t,e){return n[t]=e,e}async function N(n,t){const e=Rt();try{return await t((i,o)=>Nt(e,i,o),e)}catch(r){throw n.error(`error ${r} while doing traced operation, state: ${JSON.stringify(e)}`),r}}const V="config-local.yaml";class W{constructor(t,e,r,i,o,s,a,c){w(this,"instance");w(this,"pid");w(this,"nRuns",0);w(this,"lastRunHistory",{});w(this,"wasStopped",!1);this.logger=t,this.workingDir=e,this.startOptions=r,this.initialStartHistory=i,this.onClose=o,this.onError=s,this.onCloseAndError=a,this.onCloseAndErrorNoStop=c}async start(){await N(this.logger,async(t,e)=>{this.wasStopped=!1;const r=yt(this.logger,this.startOptions);r.on("error",o=>{this.logger.error(`error '${o}', while running platforma, started opts: ${JSON.stringify(this.debugInfo())}`),this.onError!==void 0&&this.onError(this),this.onCloseAndError!==void 0&&this.onCloseAndError(this),this.onCloseAndErrorNoStop!==void 0&&!this.wasStopped&&this.onCloseAndErrorNoStop(this)}),r.on("close",()=>{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)}),t("started",!0);const i=t("pidFile",L(this.workingDir));t("pid",p.notEmpty(r.pid)),t("pidWritten",await kt(i,p.notEmpty(r.pid))),this.nRuns++,this.instance=r,this.pid=r.pid,this.lastRunHistory=e})}stop(){this.wasStopped=!0,G(p.notEmpty(this.pid))}async waitStopped(){await z(p.notEmpty(this.pid),15e3)}stopped(){return this.wasStopped}async isAlive(){return await k(p.notEmpty(this.pid))}debugInfo(){return{lastRunHistory:this.lastRunHistory,nRuns:this.nRuns,pid:this.pid,workingDir:this.workingDir,initialStartHistory:this.initialStartHistory,wasStopped:this.wasStopped}}}async function Bt(n,t){const e=Math.max(mt.cpus().length-2,1),r=K(t,e);return await N(n,async(i,o)=>{i("startOptions",{...r,config:"too wordy"});const s=u.resolve(r.workingDir);r.closeOld&&i("closeOld",await It(n,s));const a=u.join(s,V);n.info(`writing configuration '${a}'...`),await y.writeFile(a,r.config);const c=u.join(s,"binaries"),l=await Dt(n,c,r.plBinary),d=i("binaryPath",u.join("binaries",l)),h=Y(d,a,r,s,process.env);i("processOpts",{cmd:h.cmd,args:h.args,cwd:h.opts.cwd});const m=new W(n,r.workingDir,h,o,r.onClose,r.onError,r.onCloseAndError,r.onCloseAndErrorNoStop);return await m.start(),m})}async function It(n,t){return await N(n,async(e,r)=>{const i=e("pidFilePath",L(t)),o=e("pid",await xt(i)),s=e("wasAlive",await k(o));return o!==void 0&&s&&(e("stopped",G(o)),e("waitStopped",await z(o,1e4))),r})}function K(n,t){var i;const e={plBinary:At(),spawnOptions:{env:{GOMAXPROCS:String(t)}},closeOld:!0};if((i=n.spawnOptions)!=null&&i.env&&(e.spawnOptions.env={...e.spawnOptions.env,...n.spawnOptions.env}),n.spawnOptions){const o={...n.spawnOptions};delete o.env,e.spawnOptions={...e.spawnOptions,...o}}const r={...n};return delete r.spawnOptions,{...e,...r}}function Y(n,t,e,r,i){var a;const o={cmd:n,args:["--config",t],opts:{env:{...i},cwd:r,stdio:["pipe","ignore","inherit"],windowsHide:!0}};(a=e.spawnOptions)!=null&&a.env&&(o.opts.env={...o.opts.env,...e.spawnOptions.env});const s={...e.spawnOptions};return delete s.env,o.opts={...o.opts,...s},o}const Ut={keepaliveInterval:6e4,keepaliveCountMax:10};class D{constructor(t,e){w(this,"config");w(this,"homeDir");w(this,"forwardedServers",[]);this.logger=t,this.client=e}static async init(t,e){const r={...Ut,...e},i=new D(t,new C.Client);return await i.connect(r),i}getForwardedServers(){return this.forwardedServers}getFullHostName(){var t,e;return`${(t=this.config)==null?void 0:t.host}:${(e=this.config)==null?void 0:e.port}`}getUserName(){var t;return(t=this.config)==null?void 0:t.username}async connect(t){return this.config=t,await _t(this.client,t)}async exec(t){return new Promise((e,r)=>{this.client.exec(t,(i,o)=>{if(i)return r(new Error(`ssh.exec: ${t}: ${i}`));let s="",a="";o.on("close",c=>{c===0?e({stdout:s,stderr:a}):r(new Error(`Command ${t} exited with code ${c}, stdout: ${s}, stderr: ${a}`))}).on("data",c=>{s+=c.toString()}).stderr.on("data",c=>{a+=c.toString()})})})}static async getAuthTypes(t,e){return new Promise(r=>{let i="";const o=new C.Client;o.on("ready",()=>{o.end();const s=this.extractAuthMethods(i);r(s.length===0?["publickey","password"]:s)}),o.on("error",()=>{o.end(),r(["publickey","password"])}),o.connect({host:t,port:e,username:new Date().getTime().toString(),debug:s=>{i+=`${s}
|
|
8
|
+
`}})})}static extractAuthMethods(t){const e=t.match(/Inbound: Received USERAUTH_FAILURE \((.+)\)/);return e&&e[1]?e[1].split(",").map(r=>r.trim()):[]}async forwardPort(t,e){const r=`ssh.forward:${t.localPort}:${t.remotePort}.id_${b.randomBytes(1).toString("hex")}`;e=e??this.config;const i=new p.RetryablePromise(o=>new Promise((s,a)=>{const c=new C.Client;c.on("ready",()=>{this.logger.info(`${r}.client.ready`),s(c)}),c.on("error",l=>{this.logger.info(`${r}.client.error: ${l}`),o.reset(),a(l)}),c.on("close",()=>{this.logger.info(`${r}.client.closed`),o.reset()}),c.connect(e)}));return await i.ensure(),new Promise((o,s)=>{const a=H.createServer({pauseOnConnect:!0},async c=>{const l=`${r}.sock_${b.randomBytes(1).toString("hex")}`;let d;try{d=await i.ensure()}catch(m){this.logger.info(`${l}.persistentClient.catch: ${m}`),c.end();return}d.setNoDelay(!0),c.setNoDelay(!0);let h;try{h=await Tt(this.logger,d,"127.0.0.1",0,"127.0.0.1",t.remotePort)}catch(m){this.logger.error(`${l}.forwardOut.err: ${m}`),c.end();return}c.pipe(h),h.pipe(c),c.resume(),h.on("error",m=>{this.logger.error(`${l}.stream.error: ${m}`),c.end(),h.end()}),h.on("close",()=>{c.end(),h.end()}),c.on("close",()=>{this.logger.info(`${l}.localSocket: closed`),c.end(),h.end()})});a.listen(t.localPort,"127.0.0.1",()=>{this.logger.info(`${r}.server: started listening`),this.forwardedServers.push(a),o({server:a})}),a.on("error",c=>{a.close(),s(new Error(`${r}.server: error: ${JSON.stringify(c)}`))}),a.on("close",()=>{this.logger.info(`${r}.server: closed ${JSON.stringify(t)}`),this.forwardedServers=this.forwardedServers.filter(c=>c!==a)})})}closeForwardedPorts(){this.logger.info("[SSH] Closing all forwarded ports..."),this.forwardedServers.forEach(t=>{const e=t.address();if(e&&typeof e!="string"){const r=e;this.logger.info(`[SSH] Closing port forward for server ${r.address}:${r.port}`)}t.close()}),this.forwardedServers=[]}static async checkHostAvailability(t){return new Promise(e=>{wt.lookup(t,r=>{e(!r)})})}static async isPassphraseRequiredForKey(t){return new Promise((e,r)=>{try{return C.utils.parseKey(t)instanceof Error&&e(!0),e(!1)}catch(i){console.log("Error parsing privateKey"),r(new Error(`ssh.isPassphraseRequiredForKey: err ${i}`))}})}async uploadFile(t,e){return await this.withSftp(async r=>new Promise((i,o)=>{r.fastPut(t,e,s=>{if(s){const a=new Error(`ssh.uploadFile: err: ${s}, localPath: ${t}, remotePath: ${e}`);return o(a)}i(!0)})}))}async withSftp(t){return new Promise((e,r)=>{this.client.sftp((i,o)=>{if(i)return r(new Error(`ssh.withSftp: sftp err: ${i}`));t(o).then(e).catch(s=>{r(new Error(`ssh.withSftp.callback: err ${s}`))}).finally(()=>{o==null||o.end()})})})}async writeFileOnTheServer(t,e,r=432){return this.withSftp(async i=>this.writeFile(i,t,e,r))}async getForderStructure(t,e,r={files:[],directories:[]}){return new Promise((i,o)=>{t.readdir(e,async(s,a)=>{if(s)return o(s);for(const c of a){const l=`${e}/${c.filename}`;if(c.attrs.isDirectory()){r.directories.push(l);try{await this.getForderStructure(t,l,r)}catch(d){return o(d instanceof Error?d:new Error(String(d)))}}else r.files.push(l)}i(r)})})}rmdir(t,e){return new Promise((r,i)=>{t.rmdir(e,o=>o?i(o):r(!0))})}unlink(t,e){return new Promise((r,i)=>{t.unlink(e,o=>o?i(o):r(!0))})}async deleteFolder(t){return this.withSftp(async e=>{try{const r=await this.getForderStructure(e,t);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}`);for(const i of r.files)this.logger.info(`ssh.deleteFolder unlink file ${i}`),await this.unlink(e,i);r.directories.sort((i,o)=>o.length-i.length);for(const i of r.directories)this.logger.info(`ssh.deleteFolder rmdir ${i}`),await this.rmdir(e,i);return await this.rmdir(e,t),!0}catch(r){this.logger.error(r);const i=r instanceof Error?r.message:"";throw new Error(`ssh.deleteFolder: path: ${t}, message: ${i}`)}})}async readFile(t){return this.withSftp(async e=>new Promise((r,i)=>{e.readFile(t,(o,s)=>{if(o)return i(new Error(`ssh.readFile: ${o}`));r(s.toString())})}))}async chmod(t,e){return this.withSftp(async r=>new Promise((i,o)=>{r.chmod(t,e,s=>s?o(new Error(`ssh.chmod: ${s}, path: ${t}, mode: ${e}`)):i(void 0))}))}async checkFileExists(t){return this.withSftp(async e=>new Promise((r,i)=>{e.stat(t,(o,s)=>{if(o)return(o==null?void 0:o.code)===2?r(!1):i(new Error(`ssh.checkFileExists: err ${o}`));r(s.isFile())})}))}async checkPathExists(t){return this.withSftp(async e=>new Promise((r,i)=>{e.stat(t,(o,s)=>{if(o)return o.code===2?r({exists:!1,isFile:!1,isDirectory:!1}):i(new Error(`ssh.checkPathExists: ${o}`));r({exists:!0,isFile:s.isFile(),isDirectory:s.isDirectory()})})}))}async writeFile(t,e,r,i=432){return new Promise((o,s)=>{t.writeFile(e,r,{mode:i},a=>{if(a)return s(new Error(`ssh.writeFile: err ${a}, remotePath: ${e}`));o(!0)})})}uploadFileUsingExistingSftp(t,e,r,i=432){return new Promise((o,s)=>{y.readFile(e).then(async a=>this.writeFile(t,r,a,i).then(()=>{o(void 0)}).catch(c=>{const l=`uploadFileUsingExistingSftp: ${c}`;this.logger.error(l),s(new Error(l))}))})}async __uploadDirectory(t,e,r,i=432){return new Promise((o,s)=>{x.readdir(e,async(a,c)=>{if(a)return s(new Error(`ssh.__uploadDir: err ${a}, localDir: ${e}, remoteDir: ${r}`));try{await this.__createRemoteDirectory(t,r);for(const l of c){const d=u.join(e,l),h=`${r}/${l}`;x.lstatSync(d).isDirectory()?await this.__uploadDirectory(t,d,h,i):await this.uploadFileUsingExistingSftp(t,d,h,i)}o()}catch(l){const d=`ssh.__uploadDir: catched err ${l}`;this.logger.error(d),s(new Error(d))}})})}async uploadDirectory(t,e,r=432){return new Promise((i,o)=>{this.withSftp(async s=>{try{await this.__uploadDirectory(s,t,e,r),i()}catch(a){o(new Error(`ssh.uploadDirectory: ${a}`))}})})}__createRemoteDirectory(t,e){return new Promise((r,i)=>{const o=e.split("/");let s="";const a=c=>{if(c>=o.length)return r();s+=`${o[c]}/`,t.stat(s,l=>{l?t.mkdir(s,d=>{if(d)return i(new Error(`ssh.__createRemDir: err ${d}, remotePath: ${e}`));a(c+1)}):a(c+1)})};a(0)})}ensureRemoteDirCreated(t,e=493){return this.withSftp(async r=>{const i=t.split("/");let o="";for(const s of i){o+=`${s}/`;try{await new Promise((a,c)=>{r.stat(o,l=>{if(!l)return a();r.mkdir(o,{mode:e},d=>{if(d)return c(new Error(`ssh.createRemoteDir: err ${d}, remotePath: ${t}`));a()})})})}catch(a){throw console.error(`Failed to create directory: ${o}`,a),a}}})}async downloadFile(t,e){return this.withSftp(async r=>new Promise((i,o)=>{r.fastGet(t,e,s=>{if(s)return o(new Error(`ssh.downloadFile: err ${s}, remotePath: ${t}, localPath: ${e}`));i(!0)})}))}close(){this.closeForwardedPorts(),this.client.end()}}async function _t(n,t,e,r){return new Promise((i,o)=>{n.on("ready",()=>{i(n)}),n.on("error",s=>{o(new Error(`ssh.connect: ${s}`))}),n.on("close",()=>{}),n.connect(t),n.setNoDelay(!0)})}async function Tt(n,t,e,r,i,o){return new Promise((s,a)=>{t.forwardOut(e,r,i,o,(c,l)=>c?(n.error(`forwardOut.error: ${c}`),a(c)):s(l))})}const jt="minio-2024-12-18T13-15-44Z",Mt="supervisord-0.7.3",Ht="supervisord_0.7.3_Linux_64-bit";function $(n){return u.join(n,".platforma_ssh")}function O(n){return u.join($(n),"binaries")}function qt(n,t){return u.join(O(n),`pl-${A()}-${S(t)}`)}function Z(n,t){return u.join(qt(n,t),"binaries")}function _(n,t){return u.join(Z(n,t),"platforma")}function Gt(n,t){return u.join(Z(n,t),"free-port")}function X(n,t){return u.join(O(n),`minio-2024-12-18T13-15-44Z-${S(t)}`)}function zt(n,t){return u.join(X(n,t),"minio")}function Jt(n,t){return u.join(O(n),`supervisord-0.7.3-${S(t)}`,Ht)}function Q(n,t){return u.join(Jt(n,t),"supervisord")}function tt(n){return u.join($(n),"supervisor.conf")}function T(n){return u.join($(n),"connection.txt")}async function Lt(n,t,e){const r=await B(n,t,e,"--daemon");if(r.stderr)throw new Error(`Can not run ssh Platforma ${r.stderr}`)}async function Vt(n,t,e){const r=await B(n,t,e,"ctl shutdown");if(r.stderr)throw new Error(`Can not stop ssh Platforma ${r.stderr}`)}function E(n,t){return t?n.platforma&&n.minio:n.platforma}function Wt(n){return n.execError===void 0}async function Kt(n,t,e,r){let i;try{i=await B(t,e,r,"ctl status")}catch(c){return{execError:String(c)}}if(i.stderr)return n.info(`supervisord ctl status: stderr occurred: ${i.stderr}, stdout: ${i.stdout}`),{rawResult:i};const o=j(i.stdout,"platforma"),s=j(i.stdout,"minio"),a={rawResult:i,platforma:o,minio:s};return a.minio||n.warn("Minio is not running on the server"),a.platforma||n.warn("Platforma is not running on the server"),a}function Yt(n,t,e,r){const i=b.randomBytes(16).toString("hex"),o=n;return`
|
|
9
9
|
[supervisord]
|
|
10
10
|
logfile=${t}/supervisord.log
|
|
11
11
|
loglevel=info
|
|
12
12
|
pidfile=${t}/supervisord.pid
|
|
13
13
|
|
|
14
|
+
[inet_http_server]
|
|
15
|
+
port=127.0.0.1:${o}
|
|
16
|
+
username=default-user
|
|
17
|
+
password=${i}
|
|
18
|
+
|
|
19
|
+
[supervisorctl]
|
|
20
|
+
serverurl=http://127.0.0.1:${o}
|
|
21
|
+
username=default-user
|
|
22
|
+
password=${i}
|
|
23
|
+
|
|
24
|
+
[program:platforma]
|
|
25
|
+
autostart=true
|
|
26
|
+
command=${r} --config ${e}
|
|
27
|
+
directory=${t}
|
|
28
|
+
autorestart=true
|
|
29
|
+
`}function Zt(n,t,e,r,i,o,s){const a=Object.entries(t).map(([d,h])=>`${d}="${h}"`).join(","),c=b.randomBytes(16).toString("hex"),l=e;return`
|
|
30
|
+
[supervisord]
|
|
31
|
+
logfile=${r}/supervisord.log
|
|
32
|
+
loglevel=info
|
|
33
|
+
pidfile=${r}/supervisord.pid
|
|
34
|
+
|
|
14
35
|
[inet_http_server]
|
|
15
36
|
port=127.0.0.1:${l}
|
|
16
37
|
username=default-user
|
|
@@ -25,16 +46,16 @@ password=${c}
|
|
|
25
46
|
autostart=true
|
|
26
47
|
depends_on=minio
|
|
27
48
|
command=${s} --config ${i}
|
|
28
|
-
directory=${
|
|
49
|
+
directory=${r}
|
|
29
50
|
autorestart=true
|
|
30
51
|
|
|
31
52
|
[program:minio]
|
|
32
53
|
autostart=true
|
|
33
54
|
environment=${a}
|
|
34
55
|
command=${o} server ${n}
|
|
35
|
-
directory=${
|
|
56
|
+
directory=${r}
|
|
36
57
|
autorestart=true
|
|
37
|
-
`}async function
|
|
38
|
-
`).some(i=>{const[o,s]=i.trim().split(/\s{2,}/);return o===r&&s==="Running"})}const $=m.z.object({local:m.z.number(),remote:m.z.number()}),tt=m.z.object({grpc:$,monitoring:$,debug:$,minioPort:$,minioConsolePort:$}),et=m.z.object({plUser:m.z.string(),plPassword:m.z.string(),ports:tt,useGlobalAccess:m.z.boolean().default(!1),plVersion:m.z.string().default("1.18.3")});function rt(n,r,e,t,i){return{plUser:n,plPassword:r,ports:e,useGlobalAccess:t,plVersion:i}}function it(n){return et.parse(JSON.parse(n))}function nt(n){return JSON.stringify(n,void 0,2)}const j=2.28;class _{constructor(r,e,t){f(this,"initState",{});this.logger=r,this.sshClient=e,this.username=t}info(){return{username:this.username,initState:this.initState}}static async init(r,e){try{const t=await A.init(r,e);return new _(r,t,w.notEmpty(e.username))}catch(t){throw r.error(`Connection error in SshClient.init: ${t}`),t}}cleanUp(){this.sshClient.close()}async isAlive(){const r=await this.getArch(),e=await this.getUserHomeDirectory();return await Vt(this.logger,this.sshClient,e,r.arch)}async start(){const r=await this.getArch(),e=await this.getUserHomeDirectory();try{if(!(await this.isAlive()).allAlive)return await Jt(this.sshClient,e,r.arch),await this.checkIsAliveWithInterval()}catch(t){const i=`SshPl.start: ${t}`;throw this.logger.error(i),new Error(i)}}async stop(){const r=await this.getArch(),e=await this.getUserHomeDirectory();try{if((await this.isAlive()).allAlive)return await Lt(this.sshClient,e,r.arch),await this.checkIsAliveWithInterval(void 0,void 0,!1)}catch(t){const i=`PlSsh.stop: ${t}`;throw this.logger.error(i),new Error(i)}}async reset(){return await this.stopAndClean(),this.cleanUp(),!0}async stopAndClean(){const r=await this.getUserHomeDirectory();this.logger.info("pl.reset: Stop Platforma on the server"),await this.stop(),this.logger.info(`pl.reset: Deleting Platforma workDir ${y(r)} on the server`),await this.sshClient.deleteFolder(y(r))}async platformaInit(r){const e={localWorkdir:r.localWorkdir},{onProgress:t}=r;try{const i={...Kt,...r};if(e.plBinaryOps=i.plBinary,await(t==null?void 0:t("Detecting server architecture...")),e.arch=await this.getArch(),await(t==null?void 0:t("Server architecture detected.")),await(t==null?void 0:t("Fetching user home directory...")),e.remoteHome=await this.getUserHomeDirectory(),await(t==null?void 0:t("User home directory retrieved.")),await(t==null?void 0:t("Checking platform status...")),e.alive=await this.isAlive(),e.alive.allAlive&&await(t==null?void 0:t("All required services are running.")),e.alive.allAlive){if(e.userCredentials=await this.getUserCredentials(e.remoteHome),!e.userCredentials)throw new Error("SshPl.platformaInit: platforma is alive but userCredentials are not found");const u=e.userCredentials.useGlobalAccess==i.useGlobalAccess,d=e.userCredentials.plVersion==i.plBinary.version;if(e.needRestart=!(u&&d),this.logger.info(`SshPl.platformaInit: need restart? ${e.needRestart}`),!e.needRestart)return await(t==null?void 0:t("Server setup completed.")),e.userCredentials;await(t==null?void 0:t("Stopping services...")),await this.stop()}await(t==null?void 0:t("Downloading and uploading required binaries..."));const o=await Yt(this.logger,this.sshClient);if(o<j)throw new Error(`glibc version ${o} is too old. Version ${j} or higher is required for Platforma.`);const s=await this.downloadBinariesAndUploadToTheServer(i.localWorkdir,i.plBinary,e.remoteHome,e.arch);if(await(t==null?void 0:t("All required binaries have been downloaded and uploaded.")),e.binPaths={...s,history:void 0},e.downloadedBinaries=s.history,e.ports=await this.fetchPorts(e.remoteHome,e.arch),!e.ports.debug.remote||!e.ports.grpc.remote||!e.ports.minioPort.remote||!e.ports.minioConsolePort.remote||!e.ports.monitoring.remote)throw new Error("SshPl.platformaInit: remote ports are not defined");await(t==null?void 0:t("Generating server configuration..."));const a=await v.generateSshPlConfigs({logger:this.logger,workingDir:y(e.remoteHome),portsMode:{type:"customWithMinio",ports:{debug:e.ports.debug.remote,grpc:e.ports.grpc.remote,minio:e.ports.minioPort.remote,minioConsole:e.ports.minioConsolePort.remote,monitoring:e.ports.monitoring.remote,grpcLocal:e.ports.grpc.local,minioLocal:e.ports.minioPort.local}},licenseMode:i.license,useGlobalAccess:w.notEmpty(i.useGlobalAccess),plConfigPostprocessing:i.plConfigPostprocessing});e.generatedConfig={...a,filesToCreate:{skipped:"it is too wordy"}},await(t==null?void 0:t("Server configuration generated.")),await(t==null?void 0:t("Generating folder structure..."));for(const[u,d]of Object.entries(a.filesToCreate))await this.sshClient.writeFileOnTheServer(u,d),this.logger.info(`Created file ${u}`);for(const u of a.dirsToCreate)await this.sshClient.ensureRemoteDirCreated(u),this.logger.info(`Created directory ${u}`);await(t==null?void 0:t("Folder structure created.")),await(t==null?void 0:t("Writing supervisord configuration..."));const c=Wt(a.minioConfig.storageDir,a.minioConfig.envs,await this.getFreePortForPlatformaOnServer(e.remoteHome,e.arch),a.workingDir,a.plConfig.configPath,e.binPaths.minioRelPath,e.binPaths.downloadedPl);if(!await this.sshClient.writeFileOnTheServer(Q(e.remoteHome),c))throw new Error(`Can not write supervisord config on the server ${y(e.remoteHome)}`);return await(t==null?void 0:t("Supervisord configuration written.")),await(t==null?void 0:t("Saving connection information...")),e.connectionInfo=rt(a.plUser,a.plPassword,e.ports,w.notEmpty(i.useGlobalAccess),i.plBinary.version),await this.sshClient.writeFileOnTheServer(I(e.remoteHome),nt(e.connectionInfo)),await(t==null?void 0:t("Connection information saved.")),await(t==null?void 0:t("Starting Platforma on the server...")),await this.start(),e.started=!0,this.initState=e,await(t==null?void 0:t("Platforma has been started successfully.")),e.connectionInfo}catch(i){const o=`SshPl.platformaInit: ${i}, state: ${JSON.stringify(e)}`;throw this.logger.error(o),new Error(o)}}async downloadBinariesAndUploadToTheServer(r,e,t,i){const o=[];try{const s=await this.downloadAndUntar(r,t,i,"pl",`pl-${e.version}`);o.push(s);const a=await this.downloadAndUntar(r,t,i,"supervisord",jt);o.push(a);const c=Gt(t,i.arch),l=await this.downloadAndUntar(r,t,i,"minio",Tt);return o.push(l),await this.sshClient.chmod(c,488),{history:o,minioRelPath:c,downloadedPl:U(t,i.arch)}}catch(s){const a=`SshPl.downloadBinariesAndUploadToServer: ${s}, state: ${JSON.stringify(o)}`;throw this.logger.error(a),s}}async downloadAndUntar(r,e,t,i,o){const s={};s.binBasePath=O(e),await this.sshClient.ensureRemoteDirCreated(s.binBasePath),s.binBasePathCreated=!0;let a=null;const c=5;for(let u=1;u<=c;u++)try{a=await Pt(this.logger,r,i,o,t.arch,t.platform);break}catch(d){if(await w.sleep(300),u==c)throw new Error(`downloadAndUntar: ${c} attempts, last error: ${d}`)}s.downloadResult=w.notEmpty(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;try{await this.sshClient.exec("hash tar")}catch{throw new Error("tar is not installed on the server. Please install it before running Platforma.")}const l=await this.sshClient.exec(`tar --warning=no-all -xvf ${s.remoteArchivePath} --directory=${s.remoteDir}`);if(l.stderr)throw new Error(`downloadAndUntar: untar: stderr occurred: ${l.stderr}, stdout: ${l.stdout}`);return s.untarDone=!0,s}async needDownload(r,e){const t=X(r,e.arch),i=Z(r,e.arch),o=U(r,e.arch);return!await this.sshClient.checkFileExists(o)||!await this.sshClient.checkFileExists(i)||!await this.sshClient.checkFileExists(t)}async checkIsAliveWithInterval(r=1e3,e=15,t=!0){const i=e*r;let o=0,s=await this.isAlive();for(;t?!s.allAlive:s.allAlive;){if(await w.sleep(r),o+=r,o>i)throw new Error(`isAliveWithInterval: The process did not ${t?"started":"stopped"} after ${i} ms. Live status: ${JSON.stringify(s)}`);s=await this.isAlive()}}async getUserCredentials(r){const e=await this.sshClient.readFile(I(r));return it(e)}async fetchPorts(r,e){return{grpc:{local:await v.getFreePort(),remote:await this.getFreePortForPlatformaOnServer(r,e)},monitoring:{local:await v.getFreePort(),remote:await this.getFreePortForPlatformaOnServer(r,e)},debug:{local:await v.getFreePort(),remote:await this.getFreePortForPlatformaOnServer(r,e)},minioPort:{local:await v.getFreePort(),remote:await this.getFreePortForPlatformaOnServer(r,e)},minioConsolePort:{local:await v.getFreePort(),remote:await this.getFreePortForPlatformaOnServer(r,e)}}}async getLocalFreePort(){return new Promise(r=>{const e=q.createServer();e.listen(0,()=>{const t=e.address().port;e.close(i=>r(t))})})}async getFreePortForPlatformaOnServer(r,e){const t=Mt(r,e.arch),{stdout:i,stderr:o}=await this.sshClient.exec(`${t}`);if(o)throw new Error(`getFreePortForPlatformaOnServer: stderr is not empty: ${o}, stdout: ${i}`);return+i}async getArch(){const{stdout:r,stderr:e}=await this.sshClient.exec("uname -s && uname -m");if(e)throw new Error(`getArch: stderr is not empty: ${e}, stdout: ${r}`);const t=r.split(`
|
|
39
|
-
`);return{platform:
|
|
58
|
+
`}async function B(n,t,e,r){const i=Q(t,e),o=tt(t),s=`${i} --configuration ${o} ${r}`;return await n.exec(s)}function j(n,t){return(i=>i.replace(/\x1B\[[0-9;]*m/g,""))(n).split(`
|
|
59
|
+
`).some(i=>{const[o,s]=i.trim().split(/\s{2,}/);return o===t&&s==="Running"})}const v=f.z.object({local:f.z.number(),remote:f.z.number()}),et=f.z.object({grpc:v,http:v.optional(),monitoring:v,debug:v,minioPort:v,minioConsolePort:v}),rt=f.z.object({plUser:f.z.string(),plPassword:f.z.string(),ports:et,useGlobalAccess:f.z.boolean().default(!1),plVersion:f.z.string().default("1.18.3"),minioIsUsed:f.z.boolean().default(!0)});function it(n,t,e,r,i,o){return{plUser:n,plPassword:t,ports:e,useGlobalAccess:r,plVersion:i,minioIsUsed:o}}function nt(n){return rt.parse(JSON.parse(n))}function ot(n){return JSON.stringify(n,void 0,2)}const M=2.28;class I{constructor(t,e,r){w(this,"initState",{step:"init"});this.logger=t,this.sshClient=e,this.username=r}info(){return{username:this.username,initState:this.initState}}static async init(t,e){try{const r=await D.init(t,e);return new I(t,r,p.notEmpty(e.username))}catch(r){throw t.error(`Connection error in SshClient.init: ${r}`),r}}cleanUp(){this.sshClient.close()}async isAlive(){const t=await this.getArch(),e=await this.getUserHomeDirectory();return await Kt(this.logger,this.sshClient,e,t.arch)}async start(t){const e=await this.getArch(),r=await this.getUserHomeDirectory();try{if(!E(await this.isAlive(),t))return await Lt(this.sshClient,r,e.arch),await this.checkIsAliveWithInterval(t)}catch(i){const o=`SshPl.start: ${i}`;throw this.logger.error(o),new Error(o)}}async stop(){const t=await this.getArch(),e=await this.getUserHomeDirectory();try{const r=await this.isAlive();if(Wt(r)){await Vt(this.sshClient,e,t.arch);const i=r.minio===!0;return await this.checkIsAliveWithInterval(i,1e3,15,!1)}}catch(r){const i=`PlSsh.stop: ${r}`;throw this.logger.error(i),new Error(i)}}async reset(){return await this.stopAndClean(),this.cleanUp(),!0}async stopAndClean(){const t=await this.getUserHomeDirectory();this.logger.info("pl.reset: Stop Platforma on the server"),await this.stop(),this.logger.info(`pl.reset: Deleting Platforma workDir ${$(t)} on the server`),await this.sshClient.deleteFolder($(t))}async platformaInit(t){const e={localWorkdir:t.localWorkdir,step:"init"},{onProgress:r}=t,i={...Xt,...t};e.plBinaryOps=i.plBinary;try{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)}catch(o){const s=`SshPl.platformaInit: ${o}, state: ${JSON.stringify(this.removeSensitiveData(e))}`;throw this.logger.error(s),new Error(s)}}async doStepStopExistedPlatforma(t,e){t.step="stopExistedPlatforma",E(t.alive,t.shouldUseMinio??!1)&&(await(e==null?void 0:e("Stopping services...")),await this.stop())}removeSensitiveData(t){const e={...t};return e.generatedConfig={...e.generatedConfig,filesToCreate:{skipped:"sanitized"}},e}async doStepStartPlatforma(t,e){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."))}async doStepSaveNewConnectionInfo(t,e,r){t.step="saveNewConnectionInfo";const i=t.generatedConfig;await(e==null?void 0:e("Saving connection information...")),t.connectionInfo=it(i.plUser,i.plPassword,t.ports,p.notEmpty(r.useGlobalAccess),r.plBinary.version,t.shouldUseMinio??!1),await this.sshClient.writeFileOnTheServer(T(t.remoteHome),ot(t.connectionInfo)),await(e==null?void 0:e("Connection information saved."))}async doStepConfigureSupervisord(t,e){await(e==null?void 0:e("Writing supervisord configuration...")),t.step="configureSupervisord";const r=t.generatedConfig;let i;if(t.shouldUseMinio?i=Zt(r.minioConfig.storageDir,r.minioConfig.envs,await this.getFreePortForPlatformaOnServer(t.remoteHome,t.arch),r.workingDir,r.plConfig.configPath,t.binPaths.minioRelPath,t.binPaths.downloadedPl):i=Yt(await this.getFreePortForPlatformaOnServer(t.remoteHome,t.arch),r.workingDir,r.plConfig.configPath,t.binPaths.downloadedPl),!await this.sshClient.writeFileOnTheServer(tt(t.remoteHome),i))throw new Error(`Can not write supervisord config on the server ${$(t.remoteHome)}`);await(e==null?void 0:e("Supervisord configuration written."))}async doStepCreateFoldersAndSaveFiles(t,e){t.step="createFoldersAndSaveFiles";const r=t.generatedConfig;await(e==null?void 0:e("Generating folder structure..."));for(const[i,o]of Object.entries(r.filesToCreate))await this.sshClient.writeFileOnTheServer(i,o),this.logger.info(`Created file ${i}`);for(const i of r.dirsToCreate)await this.sshClient.ensureRemoteDirCreated(i),this.logger.info(`Created directory ${i}`);await(e==null?void 0:e("Folder structure created."))}async doStepGenerateNewConfig(t,e,r){t.step="generateNewConfig",await(e==null?void 0:e("Generating new config..."));const i=await g.generateSshPlConfigs({logger:this.logger,workingDir:$(t.remoteHome),portsMode:{type:"customWithMinio",ports:{debug:t.ports.debug.remote,grpc:t.ports.grpc.remote,http:t.ports.http.remote,minio:t.ports.minioPort.remote,minioConsole:t.ports.minioConsolePort.remote,monitoring:t.ports.monitoring.remote,httpLocal:t.ports.http.local,grpcLocal:t.ports.grpc.local,minioLocal:t.ports.minioPort.local}},licenseMode:r.license,useGlobalAccess:p.notEmpty(r.useGlobalAccess),plConfigPostprocessing:r.plConfigPostprocessing,useMinio:t.shouldUseMinio??!1});t.generatedConfig={...i},await(e==null?void 0:e("New config generated"))}async doStepFetchPorts(t){var e;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))throw new Error("SshPl.platformaInit: remote ports are not defined")}async doStepDownloadBinaries(t,e,r){t.step="downloadBinaries",await(e==null?void 0:e("Downloading and uploading required binaries..."));const i=await Qt(this.logger,this.sshClient);if(i<M)throw new Error(`glibc version ${i} is too old. Version ${M} or higher is required for Platforma.`);const o=await this.downloadBinariesAndUploadToTheServer(r.localWorkdir,r.plBinary,t.remoteHome,t.arch,t.shouldUseMinio??!1);await(e==null?void 0:e("All required binaries have been downloaded and uploaded.")),t.binPaths={...o,history:void 0},t.downloadedBinaries=o.history}async doStepDetectArch(t,e){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."))}async doStepDetectHome(t,e){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."))}async doStepReadExistedConfig(t,e,r){var s;if(t.step="checkAlive",await(r==null?void 0:r("Checking platform status...")),t.alive=await this.isAlive(),!((s=t.alive)!=null&&s.platforma))return!0;if(await(r==null?void 0:r("All required services are running.")),t.existedSettings=await this.readExistedConfig(t.remoteHome),!t.existedSettings)throw new Error("SshPl.platformaInit: platforma is alive but existed settings are not found");const i=t.existedSettings.useGlobalAccess==e.useGlobalAccess,o=t.existedSettings.plVersion==e.plBinary.version;return t.needRestart=!(i&&o),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)}async downloadBinariesAndUploadToTheServer(t,e,r,i,o){const s=[];try{const a=await this.downloadAndUntar(t,r,i,"pl",`pl-${e.version}`);s.push(a);const c=await this.downloadAndUntar(t,r,i,"supervisord",Mt);s.push(c);const l=zt(r,i.arch);if(o){const d=await this.downloadAndUntar(t,r,i,"minio",jt);s.push(d),await this.sshClient.chmod(l,488)}return{history:s,minioRelPath:o?l:void 0,downloadedPl:_(r,i.arch)}}catch(a){const c=`SshPl.downloadBinariesAndUploadToServer: ${a}, state: ${JSON.stringify(s)}`;throw this.logger.error(c),a}}async downloadAndUntar(t,e,r,i,o){const s={};s.binBasePath=O(e),await this.sshClient.ensureRemoteDirCreated(s.binBasePath),s.binBasePathCreated=!0;let a=null;const c=5;for(let d=1;d<=c;d++)try{a=await Ct(this.logger,t,i,o,r.arch,r.platform);break}catch(h){if(await p.sleep(300),d==c)throw new Error(`downloadAndUntar: ${c} attempts, last error: ${h}`)}s.downloadResult=p.notEmpty(a),s.localArchivePath=u.resolve(s.downloadResult.archivePath),s.remoteDir=u.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;try{await this.sshClient.exec("hash tar")}catch{throw new Error("tar is not installed on the server. Please install it before running Platforma.")}const l=await this.sshClient.exec(`tar --warning=no-all -xvf ${s.remoteArchivePath} --directory=${s.remoteDir}`);if(l.stderr)throw new Error(`downloadAndUntar: untar: stderr occurred: ${l.stderr}, stdout: ${l.stdout}`);return s.untarDone=!0,s}async needDownload(t,e){const r=Q(t,e.arch),i=X(t,e.arch),o=_(t,e.arch);return!await this.sshClient.checkFileExists(o)||!await this.sshClient.checkFileExists(i)||!await this.sshClient.checkFileExists(r)}async checkIsAliveWithInterval(t,e=1e3,r=15,i=!0){const o=r*e;let s=0,a=await this.isAlive();for(;i?!E(a,t):E(a,t);){if(await p.sleep(e),s+=e,s>o)throw new Error(`isAliveWithInterval: The process did not ${i?"started":"stopped"} after ${o} ms. Live status: ${JSON.stringify(a)}`);a=await this.isAlive()}}async readExistedConfig(t){const e=await this.sshClient.readFile(T(t));return nt(e)}async fetchPorts(t,e){return{grpc:{local:await g.getFreePort(),remote:await this.getFreePortForPlatformaOnServer(t,e)},monitoring:{local:await g.getFreePort(),remote:await this.getFreePortForPlatformaOnServer(t,e)},debug:{local:await g.getFreePort(),remote:await this.getFreePortForPlatformaOnServer(t,e)},http:{local:await g.getFreePort(),remote:await this.getFreePortForPlatformaOnServer(t,e)},minioPort:{local:await g.getFreePort(),remote:await this.getFreePortForPlatformaOnServer(t,e)},minioConsolePort:{local:await g.getFreePort(),remote:await this.getFreePortForPlatformaOnServer(t,e)}}}async getLocalFreePort(){return new Promise(t=>{const e=H.createServer();e.listen(0,()=>{const r=e.address().port;e.close(i=>t(r))})})}async getFreePortForPlatformaOnServer(t,e){const r=Gt(t,e.arch),{stdout:i,stderr:o}=await this.sshClient.exec(`${r}`);if(o)throw new Error(`getFreePortForPlatformaOnServer: stderr is not empty: ${o}, stdout: ${i}`);return+i}async getArch(){const{stdout:t,stderr:e}=await this.sshClient.exec("uname -s && uname -m");if(e)throw new Error(`getArch: stderr is not empty: ${e}, stdout: ${t}`);const r=t.split(`
|
|
60
|
+
`);return{platform:r[0],arch:r[1]}}async getUserHomeDirectory(){const{stdout:t,stderr:e}=await this.sshClient.exec("echo $HOME");if(e){const r=`/home/${this.username}`;return console.warn(`getUserHomeDirectory: stderr is not empty: ${e}, stdout: ${t}, will get a default home: ${r}`),r}return t.trim()}}const Xt={useGlobalAccess:!1,plBinary:{type:"Download",version:A()}};async function Qt(n,t){try{const{stdout:e,stderr:r}=await t.exec("ldd --version | head -n 1");if(r)throw new Error(`Failed to check glibc version: ${r}`);return st(e)}catch(e){throw n.error(`glibc version check failed: ${e}`),e}}function st(n){const t=n.match(/\d+\.\d+/);if(!t)throw new Error(`Could not parse glibc version from: ${n}`);return parseFloat(t[0])}exports.ConnectionInfo=rt;exports.LocalConfigYaml=V;exports.LocalPl=W;exports.PortPair=v;exports.SshClient=D;exports.SshPl=I;exports.SshPlPorts=et;exports.getDefaultPlVersion=A;exports.localPlatformaInit=Bt;exports.mergeDefaultOps=K;exports.newConnectionInfo=it;exports.parseConnectionInfo=nt;exports.parseGlibcVersion=st;exports.plProcessOps=Y;exports.stringifyConnectionInfo=ot;
|
|
40
61
|
//# sourceMappingURL=index.js.map
|