spec/support/helpers.rb in engineyard-1.3.13 vs spec/support/helpers.rb in engineyard-1.3.14
- old
+ new
@@ -1,8 +1,11 @@
+require 'engineyard/cli'
+
require 'realweb'
-require "rest_client"
+require 'rest_client'
require 'open4'
+require 'stringio'
module Spec
module Helpers
class UnexpectedExit < StandardError
def initialize(stdout, stderr)
@@ -14,10 +17,60 @@
end
end
NonzeroExitStatus = Class.new(UnexpectedExit)
ZeroExitStatus = Class.new(UnexpectedExit)
+ def fast_ey(args)
+ err, out = StringIO.new, StringIO.new
+ capture_stderr_into(err) do
+ capture_stdout_into(out) do
+ with_env('DEBUG' => 'true') do
+ EY::CLI.start(args)
+ end
+ end
+ end
+ ensure
+ @err, @out = err.string, out.string
+ @raw_ssh_commands, @ssh_commands = extract_ssh_commands(@out)
+ end
+
+ def fast_failing_ey(*args)
+ begin
+ fast_ey(*args)
+ raise ZeroExitStatus
+ rescue SystemExit => exit_status
+ # SystemExit typically indicates a bogus command, which we
+ # here in expected-to-fail land are entirely happy with.
+ nil
+ rescue EY::Error => e
+ more_err, more_out = StringIO.new, StringIO.new
+
+ capture_stderr_into(more_err) do
+ capture_stdout_into(more_out) do
+ EY.ui.print_exception(e)
+ end
+ end
+
+ @err << more_err.string
+ @out << more_out.string
+ end
+ end
+
+ def capture_stderr_into(stream)
+ $stderr = stream
+ yield
+ ensure
+ $stderr = STDERR
+ end
+
+ def capture_stdout_into(stream)
+ $stdout = stream
+ yield
+ ensure
+ $stdout = STDOUT
+ end
+
def ey(cmd = nil, options = {}, &block)
hide_err = options.has_key?(:hide_err) ? options[:hide_err] : options[:expect_failure]
path_prepends = options[:prepend_to_path]
ey_env = {'DEBUG' => 'true'}
@@ -52,29 +105,40 @@
elsif exit_status.success? && options[:expect_failure]
raise ZeroExitStatus.new(@out, @err)
end
end
- @raw_ssh_commands = @out.split(/\n/).find_all do |line|
- line =~ /^ssh/
+ @raw_ssh_commands, @ssh_commands = extract_ssh_commands(@out)
+
+ puts @err unless @err.empty? || hide_err
+ @out
+ end
+
+ def extract_ssh_commands(output)
+ raw_ssh_commands = @out.split(/\n/).find_all do |line|
+ line =~ /^bash -lc/ || line =~ /^ssh/
end
- @ssh_commands = @raw_ssh_commands.map do |cmd|
+ ssh_commands = raw_ssh_commands.map do |cmd|
# Strip off everything up to and including user@host, leaving
# just the command that the remote system would run
- ssh_prefix_removed = cmd.gsub(/^.*?\w+@\S*\s*/, '')
+ #
+ # XXX: this is a really icky icky.
+ # engineyard gem was written as if shelling out to run serverside
+ # and running an ssh command will always be the same. This is a nasty
+ # hack to get it working with Net::SSH for now so we can repair 1.9.2.
+ ssh_prefix_removed = cmd.gsub(/^bash -lc /, '').gsub(/^ssh .*?\w+@\S*\s*/, '')
# Its arguments have been double-escaped: one layer is to get
# them through our local shell and into ssh, and the other
# layer is to get them through the remote system's shell.
#
# Strip off one layer by running it through the shell.
just_the_remote_command = ssh_prefix_removed.gsub(/>\s*\/dev\/null.*$/, '')
`echo #{just_the_remote_command}`.strip
end
- puts @err unless @err.empty? || hide_err
- @out
+ [raw_ssh_commands, ssh_commands]
end
def api_scenario(scenario, remote = "user@git.host:path/to/repo.git")
response = ::RestClient.put(EY.fake_awsm + '/scenario', {"scenario" => scenario, "remote" => remote}, {})
raise "Setting scenario failed: #{response.inspect}" unless response.code == 200