80 lines
2.5 KiB
JavaScript
80 lines
2.5 KiB
JavaScript
import { promisify } from 'util'
|
|
import to from 'await-to-js'
|
|
import { readFile } from 'fs'
|
|
import { Client } from 'ssh2'
|
|
import logger from '@uci/logger'
|
|
let log = {} // declare module wide log to be set during construction
|
|
|
|
const read = promisify(readFile)
|
|
// ssh client is already an event emitter
|
|
class Ssh extends Client {
|
|
constructor(opts={}) {
|
|
super()
|
|
this.opts = opts
|
|
log = logger({ name: 'remote-code', file:'src/ssh.js', class:'Ssh', id: opts.id })
|
|
this.ready = false
|
|
// additional options available
|
|
this.rpath = opts.rpath || '/opt' // will cd to this path upon connect
|
|
}
|
|
|
|
async connect(copts = {}) {
|
|
const opts = Object.assign({},this.opts,copts) // merge any changes pasted via connect
|
|
// log.info('connection options ', opts)
|
|
opts.readyTimeout = opts.readyTimeout | 5000 // default was 20 seconds...too long
|
|
opts.privateKey = opts.privateKey || opts.privateKeyPath ? await read(opts.privateKeyPath) : null
|
|
// log.info(opts.privateKeyPath, opts.privateKey)
|
|
super.connect(opts)
|
|
return new Promise( (resolve,reject) => {
|
|
this.on('ready', async () => {
|
|
this.ready=true
|
|
log.info(`connected to ${this.opts.host}`)
|
|
resolve(`connected to ${this.opts.host}`)
|
|
})
|
|
this.on('error', (err) => {
|
|
log.info('connection error', err)
|
|
reject(err)
|
|
})
|
|
})
|
|
}
|
|
|
|
close() {
|
|
this.ready=false
|
|
this.end()
|
|
}
|
|
|
|
async exec(command = 'ls -la', opts={}) {
|
|
if (!this.ready) {
|
|
log.info('not connected, attempting connect first')
|
|
let [err] = await to(this.connect())
|
|
if (err) return err
|
|
}
|
|
// log.info('executing command ', command)
|
|
const remote = this
|
|
let superexec = super.exec.bind(this)
|
|
return new Promise(function(resolve, reject) {
|
|
let reply=[]
|
|
let error=[]
|
|
superexec(command, function(err, stream) {
|
|
if (err) reject(err)
|
|
stream.on('finish', () => {
|
|
if (remote.opts.close || opts.close) {
|
|
log.info('closing connection')
|
|
remote.close
|
|
}
|
|
if (error.length!==0) remote.emit('client:error',error)
|
|
resolve({command:command,reply:reply,error:error})
|
|
})
|
|
.on('data', function(data) {
|
|
reply.push(data)
|
|
log.info(`${remote.opts.host}$ ${data}`)
|
|
}).stderr.on('data', function(data) {
|
|
error.push(data)
|
|
log.info(`${remote.opts.host}:ERR$ ${data}`)
|
|
})
|
|
}) // end super
|
|
}) // end Promise
|
|
}
|
|
}
|
|
|
|
export default Ssh
|