Single quotes in Powershell Module parameters are incorrectly escaped

Hi All,

There appears to be a problem with how Ansible handles single quotes in ‘complex args’ for non native json modules. Lets start with an example: I have been working on a module to perform XPath operations on files on Windows:

  • name: Update some xml
    win_xml:
    verb: set
    path: “c:\apps\service.exe.config”
    match: //configuration/appSettings/add[@key=‘queue’]

The value of match parameter is an XPath expression and contains a single quoted string. As we can see this is valid YAML, and its de-serialised correctly.
However, when Ansible invokes the Powershell module the single quotes in the ‘match’ parameter have been unnecessarily escaped to:

//configuration/appSettings/add[@key=‘"’“‘queue’”‘"’]

If we keep files on the target host we can see the extra quotes are also in the JSON passed to the powershell module. In fact, you can also see the extra quotes appear if we enable ‘vvvv’ debugging:

ESTABLISH WINRM CONNECTION …

REMOTE_MODULE win_xml match=‘//configuration/appSettings/add[@key=’“‘"queue’”‘"’]’ verb=

EXEC (New-Item -Type Directory -Path $env:temp -Name "an…

It looks like this issue caused by a round trip, first flattening the complex_args object into a single key=value string and escaping them (I guess for bash style modules), but then later parsing them back out into the complex_args. Only, when they come back out again, the single quotes are not un-escaped as they should be.

So, during the flattening parameters are escaped with pipe.quote()
and during the parsing the ansible/module_utils/splitter.py unquote() function is used

The unquote function only handles quotes if they appear at the very beginning and end of a string, unlike pipe.quote. This happens in:

https://github.com/ansible/ansible/commit/af2fb56a10196735e57fbe95b04592efcd393405

lib/ansible/runner/init.py
complex_args.update(utils.parse_kv(args)) ← this overwrites the correct parameters in the dictionary with incorrectly escaped ones from the parsing.

Can anybody shed any light on this logic? The complex args support is clearly a tricky feature, but this really looks like a bug that slipped through to me. I’m happy to sort this out in a PR.

Thanks
Ian