You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

78 lines
2.1 KiB

import {Host} from './Host'
import {Application, Awaitable, Filesystem, SSHFilesystem} from '@extollo/lib'
import {ExecutionResult} from './ExecutionResult'
import {ShellCommand} from './types'
import * as ssh2 from 'ssh2'
export class SSHHost extends Host {
private sshClient?: ssh2.Client
private filesystem?: Filesystem
constructor(
protected readonly config: ssh2.ConnectConfig,
) {
super()
}
async close() {
this.sshClient?.end()
this.sshClient?.destroy()
this.sshClient = undefined
this.filesystem?.close()
this.filesystem = undefined
}
async execute(command: ShellCommand): Promise<ExecutionResult>{
const client = await this.getSSH()
const result = new ExecutionResult()
return new Promise<ExecutionResult>((res, rej) => {
client.exec(command, (err, stream) => {
if ( err ) {
return rej(err)
}
stream
.on('close', (code: number) => {
result.exit(code)
res(result)
})
.on('data', (data: any) => {
result.out(data)
})
.stderr.on('data', (data: any) => {
result.error(data)
})
})
})
}
getFilesystem(): Awaitable<Filesystem> {
if ( !this.filesystem ) {
this.filesystem = Application.getContainer().makeNew<SSHFilesystem>(SSHFilesystem, {
ssh: this.config,
baseDir: '/',
})
}
return this.filesystem
}
protected async getSSH(): Promise<ssh2.Client> {
if ( this.sshClient ) {
return this.sshClient
}
return new Promise((res, rej) => {
const client = new ssh2.Client()
client.on('ready', () => {
this.sshClient = client
res(client)
}).connect(this.config)
client.on('error', rej)
})
}
}