From e9b6aaf5d8836ce7ffdca855e006c2131fe19632 Mon Sep 17 00:00:00 2001 From: Chris Church Date: Sun, 23 Nov 2014 22:53:10 -0500 Subject: [PATCH] Update PowerShell command line processing to handle parameters passed via splatting. --- .../runner/connection_plugins/winrm.py | 2 +- .../runner/shell_plugins/powershell.py | 8 +++-- .../roles/test_win_script/defaults/main.yml | 5 +++ .../files/test_script_with_splatting.ps1 | 6 ++++ .../roles/test_win_script/tasks/main.yml | 32 +++++++++++++++++++ 5 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 test/integration/roles/test_win_script/defaults/main.yml create mode 100644 test/integration/roles/test_win_script/files/test_script_with_splatting.ps1 diff --git a/lib/ansible/runner/connection_plugins/winrm.py b/lib/ansible/runner/connection_plugins/winrm.py index d6e51710b5f..32b630bc42c 100644 --- a/lib/ansible/runner/connection_plugins/winrm.py +++ b/lib/ansible/runner/connection_plugins/winrm.py @@ -143,7 +143,7 @@ class Connection(object): vvv("EXEC %s" % cmd, host=self.host) # For script/raw support. if cmd_parts and cmd_parts[0].lower().endswith('.ps1'): - script = powershell._build_file_cmd(cmd_parts) + script = powershell._build_file_cmd(cmd_parts, quote_args=False) cmd_parts = powershell._encode_script(script, as_list=True) try: result = self._winrm_exec(cmd_parts[0], cmd_parts[1:], from_exec=True) diff --git a/lib/ansible/runner/shell_plugins/powershell.py b/lib/ansible/runner/shell_plugins/powershell.py index 7254df6f7ea..93761d321d4 100644 --- a/lib/ansible/runner/shell_plugins/powershell.py +++ b/lib/ansible/runner/shell_plugins/powershell.py @@ -53,9 +53,11 @@ def _encode_script(script, as_list=False): return cmd_parts return ' '.join(cmd_parts) -def _build_file_cmd(cmd_parts): +def _build_file_cmd(cmd_parts, quote_args=True): '''Build command line to run a file, given list of file name plus args.''' - return ' '.join(_common_args + ['-ExecutionPolicy', 'Unrestricted', '-File'] + ['"%s"' % x for x in cmd_parts]) + if quote_args: + cmd_parts = ['"%s"' % x for x in cmd_parts] + return ' '.join(['&'] + cmd_parts) class ShellModule(object): @@ -110,7 +112,7 @@ class ShellModule(object): cmd_parts = shlex.split(cmd, posix=False) if not cmd_parts[0].lower().endswith('.ps1'): cmd_parts[0] = '%s.ps1' % cmd_parts[0] - script = _build_file_cmd(cmd_parts) + script = _build_file_cmd(cmd_parts, quote_args=False) if rm_tmp: rm_tmp = _escape(rm_tmp) script = '%s; Remove-Item "%s" -Force -Recurse;' % (script, rm_tmp) diff --git a/test/integration/roles/test_win_script/defaults/main.yml b/test/integration/roles/test_win_script/defaults/main.yml new file mode 100644 index 00000000000..a2c6475e751 --- /dev/null +++ b/test/integration/roles/test_win_script/defaults/main.yml @@ -0,0 +1,5 @@ +--- + +# Parameters to pass to test scripts. +test_win_script_value: VaLuE +test_win_script_splat: "@{This='THIS'; That='THAT'; Other='OTHER'}" diff --git a/test/integration/roles/test_win_script/files/test_script_with_splatting.ps1 b/test/integration/roles/test_win_script/files/test_script_with_splatting.ps1 new file mode 100644 index 00000000000..429a9a3b7a1 --- /dev/null +++ b/test/integration/roles/test_win_script/files/test_script_with_splatting.ps1 @@ -0,0 +1,6 @@ +# Test script to make sure the Ansible script module works when arguments are +# passed via splatting (http://technet.microsoft.com/en-us/magazine/gg675931.aspx) + +Write-Host $args.This +Write-Host $args.That +Write-Host $args.Other diff --git a/test/integration/roles/test_win_script/tasks/main.yml b/test/integration/roles/test_win_script/tasks/main.yml index 1edfd0b006d..e1e5f25611d 100644 --- a/test/integration/roles/test_win_script/tasks/main.yml +++ b/test/integration/roles/test_win_script/tasks/main.yml @@ -46,6 +46,38 @@ - "not test_script_with_args_result|failed" - "test_script_with_args_result|changed" +- name: run test script that takes parameters passed via splatting + script: test_script_with_splatting.ps1 "@{ This = 'this'; That = '{{ test_win_script_value }}'; Other = 'other'}" + register: test_script_with_splatting_result + +- name: check that script ran and received parameters via splatting + assert: + that: + - "test_script_with_splatting_result.rc == 0" + - "test_script_with_splatting_result.stdout" + - "test_script_with_splatting_result.stdout_lines[0] == 'this'" + - "test_script_with_splatting_result.stdout_lines[1] == test_win_script_value" + - "test_script_with_splatting_result.stdout_lines[2] == 'other'" + - "not test_script_with_splatting_result.stderr" + - "not test_script_with_splatting_result|failed" + - "test_script_with_splatting_result|changed" + +- name: run test script that takes splatted parameters from a variable + script: test_script_with_splatting.ps1 {{ test_win_script_splat|quote }} + register: test_script_with_splatting2_result + +- name: check that script ran and received parameters via splatting from a variable + assert: + that: + - "test_script_with_splatting2_result.rc == 0" + - "test_script_with_splatting2_result.stdout" + - "test_script_with_splatting2_result.stdout_lines[0] == 'THIS'" + - "test_script_with_splatting2_result.stdout_lines[1] == 'THAT'" + - "test_script_with_splatting2_result.stdout_lines[2] == 'OTHER'" + - "not test_script_with_splatting2_result.stderr" + - "not test_script_with_splatting2_result|failed" + - "test_script_with_splatting2_result|changed" + - name: run test script that has errors script: test_script_with_errors.ps1 register: test_script_with_errors_result