lib/datacenter/shell/remote.rb
module Datacenter
module Shell
class Remote
def initialize(*args)
@args = args
end
def open
@session ||= Net::SSH.start(*args)
end
def close
if session && !session.closed?
session.close
@session = nil
end
end
def run(command, options={})
if session
run! command, options
else
self.class.open(*args) { |shell| shell.run command, options }
end
end
def self.open(*args)
shell = new(*args)
shell.open
yield shell
ensure
shell.close
end
private
attr_reader :args, :session
def run!(command, options={})
Datacenter.logger.debug(self.class) { command }
result = ''
error = ''
out = options[:out] || StringIO.new
err = options[:err] || StringIO.new
exit_code = nil
session.open_channel do |channel|
channel.exec(command) do |ch, success|
abort "FAILED: couldn't execute command (ssh.channel.exec)" unless success
channel.on_data do |ch, data|
out << data
result << data
end
channel.on_extended_data do |ch, type, data|
err << data
error << data
end
channel.on_request('exit-status') do |ch, data|
exit_code = data.read_long
end
end
end
session.loop
raise CommandError.new(command, error) unless exit_code == 0
result
end
end
end
end