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
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)
|
|
})
|
|
}
|
|
}
|