win_shell: command line execution is getting confused by ansible.windows.quote when used twice or more
Wenzel opened this issue · 3 comments
SUMMARY
win_shell
module is confused when the ansible.windows.quote
function is used twice in the command line and fails to execute the given command.
ISSUE TYPE
- Bug Report
COMPONENT NAME
win_shell
ANSIBLE VERSION
ansible [core 2.15.0]
config file = /home/mtarral/kafl/kafl/examples/templates/windows/ansible.cfg
configured module search path = ['/home/mtarral/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/mtarral/kafl/kafl/examples/venv/lib/python3.10/site-packages/ansible
ansible collection location = /home/mtarral/.ansible/collections:/usr/share/ansible/collections
executable location = /home/mtarral/kafl/kafl/examples/venv/bin/ansible
python version = 3.10.6 (main, May 29 2023, 11:10:38) [GCC 11.3.0] (/home/mtarral/kafl/kafl/examples/venv/bin/python3)
jinja version = 3.1.2
libyaml = True
COLLECTION VERSION
ansible-galaxy collection list ansible.windows
# /home/mtarral/kafl/kafl/examples/venv/lib/python3.10/site-packages/ansible_collections
Collection Version
--------------- -------
ansible.windows 1.14.0
CONFIGURATION
CONFIG_FILE() = /home/mtarral/kafl/kafl/examples/templates/windows/ansible.cfg
DEFAULT_STDOUT_CALLBACK(/home/mtarral/kafl/kafl/examples/templates/windows/ansible.cfg) = yaml
EDITOR(env: EDITOR) = vim
OS / ENVIRONMENT
- Ubuntu 22.04.1
STEPS TO REPRODUCE
- name: Deploy
hosts: default
vars:
iexplore_path: "{{ ansible_env['ProgramFiles(x86)'] }}\\Internet Explorer\\iexplore.exe"
tasks:
- name: test one ansible.windows.quote
win_shell: "{{ iexplore_path | ansible.windows.quote }} /?"
args:
executable: cmd
register: result
failed_when:
- result.rc != 0
- result.rc != 1
- name: test two ansible.windows.quote
win_shell: "{{ iexplore_path | ansible.windows.quote }} {{ iexplore_path | ansible.windows.quote }}"
args:
executable: cmd
EXPECTED RESULTS
On the second task, iexplore.exe executable should have been called.
ACTUAL RESULTS
qemu.windows: TASK [Gathering Facts] *********************************************************
qemu.windows: ok: [default]
qemu.windows:
qemu.windows: TASK [test one ansible.windows.quote] ******************************************
qemu.windows: changed: [default] => changed=true
qemu.windows: cmd: '"C:\Program Files (x86)\Internet Explorer\iexplore.exe" /?'
qemu.windows: delta: '0:00:00.187520'
qemu.windows: end: '2023-06-13 23:00:26.996222'
qemu.windows: failed_when_result: false
qemu.windows: msg: non-zero return code
qemu.windows: rc: 1
qemu.windows: start: '2023-06-13 23:00:26.808702'
qemu.windows: stderr: ''
qemu.windows: stderr_lines: <omitted>
qemu.windows: stdout: ''
qemu.windows: stdout_lines: <omitted>
qemu.windows:
qemu.windows: TASK [test two ansible.windows.quote] ******************************************
qemu.windows: fatal: [default]: FAILED! => changed=true
qemu.windows: cmd: '"C:\Program Files (x86)\Internet Explorer\iexplore.exe" "C:\Program Files (x86)\Internet Explorer\iexplore.exe"'
qemu.windows: delta: '0:00:00.093752'
qemu.windows: end: '2023-06-13 23:00:29.996204'
qemu.windows: msg: non-zero return code
qemu.windows: rc: 1
qemu.windows: start: '2023-06-13 23:00:29.902452'
qemu.windows: stderr: |-
qemu.windows: 'C:\Program' is not recognized as an internal or external command,
qemu.windows: operable program or batch file.
qemu.windows: stderr_lines: <omitted>
qemu.windows: stdout: ''
qemu.windows: stdout_lines: <omitted>
qemu.windows:
qemu.windows: PLAY RECAP *********************************************************************
qemu.windows: default : ok=2 changed=1 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
Reproduce Bug
You can find the following repo to repro the bug:
git clone https://github.com/Wenzel/kafl.targets -b bug_ansible_quote
cd templates/windows
python3 -m venv venv
source venv/bin/activate
pip install ansible==8.0.0 pywinrm
packer build -var-file win10.pkrvars.hcl -on-error=ask windows.pkr.hcl
Hi @jborean93 and thanks for your reply !
It's invalid to have 2 quoted objects in an expression without anything else in pwsh
So remember that i'm using executable: cmd
here, so it will not be interpreted as Powershell syntax.
my use case was the following.
I wanted to run the vcvars64.bat
Visual Studio script, compile a driver, and link it with ntoskrnl.lib
from the WDK.
Both the vcvars64
and ntoskrnl.lib
are located under Program Files (x86)
, so they require quoting since the path contains spaces.
This command line executes well in my cmd:
But when I try to replicate the same within Ansible:
vcvars_path: "{{ ansible_env['ProgramFiles(x86)'] }}\\Microsoft Visual Studio\\2017\\BuildTools\\VC\\Auxiliary\\Build\\vcvars64.bat"
ntoskrnllib_path: "C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.17763.0\\km\\x64\\ntoskrnl.lib"
tasks:
- name: set content
win_shell: echo "int main() {}" > main.c
args:
executable: cmd
- name: test
win_shell: "{{ vcvars_path | ansible.windows.quote }} && cl main.c && link main.obj {{ ntoskrnllib_path | ansible.windows.quote }}"
args:
executable: cmd
The command fails to vcvars64.bat
because of a quoting issue.
TASK [set content] *************************************************************
[stdout] changed: [192.168.122.55]
TASK [test] ********************************************************************
[stdout] fatal: [192.168.122.55]: FAILED! => changed=true
cmd: '"C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvars64.bat" && cl main.c && link main.obj "C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\km\x64\ntoskrnl.lib"'
delta: '0:00:00.078106'
end: '2023-06-12 19:44:32.000440'
msg: non-zero return code
rc: 1
start: '2023-06-12 19:44:31.922334'
stderr: |-
'C:\Program' is not recognized as an internal or external command,
operable program or batch file.
stderr_lines: <omitted>
stdout: ''
stdout_lines: <omitted>
I also cannot replicate your error message, I get the one shown in PowerShell which is expected
I provided a repository to reproduce the error.
Did you try to build the VM and execute the playbook ?
Thanks !
So remember that i'm using executable: cmd here, so it will not be interpreted as Powershell syntax.
My apologies I must have missed that when looking at your example
There are some really complex quotation rules for cmd
listed under https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/cmd#remarks
I can't claim to understand the escaping rules here but to get this working you need to enclose your entire command with quotes like so:
- win_shell: "\"{{ my_path | ansible.windows.quote }} {{ my_path | ansible.windows.quote }}\""
args:
executable: cmd
vars:
my_path: C:\folder with space\print_argv.exe
Some alternatives are that lead to the same raw value are:
- win_shell: '"{{ my_path | ansible.windows.quote }} {{ my_path | ansible.windows.quote }}"'
args:
executable: cmd
vars:
my_path: C:\folder with space\print_argv.exe
- win_shell: >-
"{{ my_path | ansible.windows.quote }} {{ my_path | ansible.windows.quote }}"
args:
executable: cmd
vars:
my_path: C:\folder with space\print_argv.exe
I believe you can also enclose it within ()
like so
- win_shell: ({{ my_path | ansible.windows.quote }} {{ my_path | ansible.windows.quote }})
args:
executable: cmd
vars:
my_path: C:\folder with space\print_argv.exe
Unfortunately this is the same problem as #514 where we are at the mercy of the parsing rules of cmd.exe /c {{ raw_params }}
. We can't really change it as people have been relying on the current behaviour (whether implicitly or explicitly). If you have any other suggestions that will preserve backwards compatibility then I'm happy to hear it but unfortunately I don't think there are going to be any.