From 7deca9af2c19554780a1ae6598a3a4b83b98914c Mon Sep 17 00:00:00 2001 From: Lucy Wyman Date: Tue, 9 Jun 2020 11:56:25 -0700 Subject: [PATCH] (GH-1846) Wrap all powershell commands in a script Powershell will [exit 1](PowerShell/PowerShell#11461) whenever the $LASTEXITCODE is greater than 0, regardless of what the code is, whenever running a bare command. Powershell exits with the correct exit code when executing files, or when `exit $LASTEXITCODE` is appended to the command being run (as in the [execute_process snippet](https://github.com/puppetlabs/bolt/blob/0d44ce739d4dafcb6d27abd894e230894fdd50e0/lib/bolt/shell/powershell/snippets.rb#L19), meaning this is only an issue when running commands using the local transport through Bolt. This appends a Powershell snippet to exit with the correct exit code to commands running on Windows using the local transport. Closes #1846 !bug * **Return correct exit code when running commands in powershell** ([1846](#1846)) Bolt will now display the correct exit code when running commands in powershell that exit with code > 1. --- lib/bolt/shell/powershell/snippets.rb | 8 ++++++++ lib/bolt/transport/local/connection.rb | 3 ++- spec/integration/local_spec.rb | 6 ++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/bolt/shell/powershell/snippets.rb b/lib/bolt/shell/powershell/snippets.rb index 7fd5486520..c1412c014b 100644 --- a/lib/bolt/shell/powershell/snippets.rb +++ b/lib/bolt/shell/powershell/snippets.rb @@ -20,6 +20,14 @@ def execute_process(command) PS end + def exit_with_code(command) + <<~PS + #{command} + if (-not $? -and ($LASTEXITCODE -eq $null)) { exit 1 } + exit $LASTEXITCODE + PS + end + def make_tmpdir(parent) <<~PS $parent = #{parent} diff --git a/lib/bolt/transport/local/connection.rb b/lib/bolt/transport/local/connection.rb index 76f4951daf..f5e71d55ef 100644 --- a/lib/bolt/transport/local/connection.rb +++ b/lib/bolt/transport/local/connection.rb @@ -50,7 +50,8 @@ def execute(command) # If it's already a powershell command then invoke it normally. # Otherwise, wrap it in powershell.exe. unless command.start_with?('powershell.exe') - command = ['powershell.exe', *Bolt::Shell::Powershell::PS_ARGS, '-Command', command] + cmd = Bolt::Shell::Powershell::Snippets.exit_with_code(command) + command = ['powershell.exe', *Bolt::Shell::Powershell::PS_ARGS, '-Command', cmd] end end diff --git a/spec/integration/local_spec.rb b/spec/integration/local_spec.rb index a4509eed25..a1970e7433 100644 --- a/spec/integration/local_spec.rb +++ b/spec/integration/local_spec.rb @@ -33,6 +33,12 @@ expect(result[0]['_error']).to be end + it 'returns correct exit code' do + result = run_failed_nodes(%W[command run exit(2) -t #{uri}]).first + expect(result['_error']['msg']).to eq('The command failed with exit code 2') + expect(result['_error']['details']['exit_code']).to eq(2) + end + it 'runs a ruby task using bolt ruby', :reset_puppet_settings do result = run_one_node(%w[task run sample::bolt_ruby message=somemessage] + config_flags) expect(result['env']).to match(/somemessage/)