Show command when remote execution fail
This commit is contained in:
parent
8168e68a2d
commit
0db2d90b72
@ -37,3 +37,15 @@ Feature: `sh' task action
|
|||||||
"""
|
"""
|
||||||
When I execute the recipe
|
When I execute the recipe
|
||||||
Then the output must not contain "after_fail"
|
Then the output must not contain "after_fail"
|
||||||
|
|
||||||
|
Scenario: prints command when execution fail
|
||||||
|
Given a recipe with:
|
||||||
|
"""
|
||||||
|
target 'some_host.test'
|
||||||
|
|
||||||
|
task :some_task do
|
||||||
|
sh '\false'
|
||||||
|
end
|
||||||
|
"""
|
||||||
|
When I execute the recipe
|
||||||
|
Then the output must match /\A\w+Error:\s+\\false/
|
||||||
|
@ -5,18 +5,22 @@ module Producer
|
|||||||
|
|
||||||
USAGE = "Usage: #{File.basename $0} [-v] [-n] recipe_file".freeze
|
USAGE = "Usage: #{File.basename $0} [-v] [-n] recipe_file".freeze
|
||||||
|
|
||||||
EX_USAGE = 64
|
EX_USAGE = 64
|
||||||
|
EX_SOFTWARE = 70
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
def run!(arguments, output: $stderr)
|
def run!(arguments, output: $stderr)
|
||||||
|
cli = new(arguments)
|
||||||
begin
|
begin
|
||||||
cli = new(arguments)
|
|
||||||
cli.parse_arguments!
|
cli.parse_arguments!
|
||||||
|
cli.run
|
||||||
rescue ArgumentError
|
rescue ArgumentError
|
||||||
output.puts USAGE
|
output.puts USAGE
|
||||||
exit EX_USAGE
|
exit EX_USAGE
|
||||||
|
rescue RuntimeError => e
|
||||||
|
output.puts "#{e.class.name.split('::').last}: #{e.message}"
|
||||||
|
exit EX_SOFTWARE
|
||||||
end
|
end
|
||||||
cli.run
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
module Producer
|
module Producer
|
||||||
module Core
|
module Core
|
||||||
Error = Class.new(StandardError)
|
Error = Class.new(StandardError)
|
||||||
|
RuntimeError = Class.new(RuntimeError)
|
||||||
ConditionNotMetError = Class.new(Error)
|
ConditionNotMetError = Class.new(Error)
|
||||||
RemoteCommandExecutionError = Class.new(Error)
|
RemoteCommandExecutionError = Class.new(RuntimeError)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -32,7 +32,7 @@ module Producer
|
|||||||
|
|
||||||
ch.on_request 'exit-status' do |c, data|
|
ch.on_request 'exit-status' do |c, data|
|
||||||
exit_status = data.read_long
|
exit_status = data.read_long
|
||||||
raise RemoteCommandExecutionError if exit_status != 0
|
raise RemoteCommandExecutionError, command if exit_status != 0
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -17,35 +17,33 @@ module Producer::Core
|
|||||||
let(:output) { StringIO.new }
|
let(:output) { StringIO.new }
|
||||||
subject(:run) { described_class.run! arguments, output: output }
|
subject(:run) { described_class.run! arguments, output: output }
|
||||||
|
|
||||||
|
before { allow(described_class).to receive(:new) { cli } }
|
||||||
|
|
||||||
it 'builds a new CLI with given arguments' do
|
it 'builds a new CLI with given arguments' do
|
||||||
expect(described_class)
|
expect(described_class).to receive(:new).with(arguments)
|
||||||
.to receive(:new).with(arguments).and_call_original
|
|
||||||
run
|
run
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'runs the CLI' do
|
it 'runs the CLI' do
|
||||||
allow(described_class).to receive(:new) { cli }
|
|
||||||
expect(cli).to receive :run
|
expect(cli).to receive :run
|
||||||
run
|
run
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'parses CLI arguments' do
|
it 'parses CLI arguments' do
|
||||||
allow(described_class).to receive(:new) { cli }
|
|
||||||
expect(cli).to receive :parse_arguments!
|
expect(cli).to receive :parse_arguments!
|
||||||
run
|
run
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when an argument error is raised' do
|
context 'when an argument error is raised' do
|
||||||
before do
|
before do
|
||||||
allow(described_class).to receive(:new) { cli }
|
|
||||||
allow(cli).to receive(:parse_arguments!)
|
allow(cli).to receive(:parse_arguments!)
|
||||||
.and_raise described_class::ArgumentError
|
.and_raise described_class::ArgumentError
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'exits with a return status of 64' do
|
it 'exits with a return status of 64' do
|
||||||
expect { run }.to raise_error(SystemExit) { |e|
|
expect { run }.to raise_error(SystemExit) do |e|
|
||||||
expect(e.status).to eq 64
|
expect(e.status).to eq 64
|
||||||
}
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'prints the usage' do
|
it 'prints the usage' do
|
||||||
@ -53,6 +51,24 @@ module Producer::Core
|
|||||||
expect(output.string).to match /\AUsage: .+/
|
expect(output.string).to match /\AUsage: .+/
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when a runtime error is raised' do
|
||||||
|
before do
|
||||||
|
allow(cli).to receive(:run)
|
||||||
|
.and_raise RuntimeError, 'some message'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'exits with a return status of 70' do
|
||||||
|
expect { run }.to raise_error(SystemExit) do |e|
|
||||||
|
expect(e.status).to eq 70
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'prints exception name and message' do
|
||||||
|
trap_exit { run }
|
||||||
|
expect(output.string).to match /\ARuntimeError: some message/
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#initialize' do
|
describe '#initialize' do
|
||||||
|
@ -106,14 +106,23 @@ module Producer::Core
|
|||||||
expect(output.string).to eq arguments
|
expect(output.string).to eq arguments
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'raises an exception when the exit status code is not 0' do
|
context 'when command execution fails' do
|
||||||
story_with_new_channel do |ch|
|
before do
|
||||||
ch.sends_exec command
|
story_with_new_channel do |ch|
|
||||||
ch.gets_data arguments
|
ch.sends_exec command
|
||||||
ch.gets_exit_status 1
|
ch.gets_data arguments
|
||||||
|
ch.gets_exit_status 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'raises an exception' do
|
||||||
|
expect { remote.execute command }
|
||||||
|
.to raise_error(RemoteCommandExecutionError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'includes the command in the exception message' do
|
||||||
|
expect { remote.execute command }.to raise_error /#{command}/
|
||||||
end
|
end
|
||||||
expect { remote.execute command }
|
|
||||||
.to raise_error(RemoteCommandExecutionError)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user