Ah ok, don't use content in this case without quoting it, and you should
be fine.
It's also preferred you use "src" anyway, content was a recent addition.
The problem is not specific to module copy with the content arg. I used
this just as an example. The problem happens with all Python modules. When
args are "injected" in the Python module before being uploaded to the
server, they should be escaped but are not.
Here is another example with lineinfile:
- hosts: all
tasks:
- copy: content='hello' dest=/vagrant/test.txt
- lineinfile: dest=/vagrant/test.txt regexp='^hello' line='hello\nworld'
After running this playbook, test.txt should contain :
$ cat test.txt
hello\nworld
Instead, I got:
$ cat test.txt
hello
world
The reason why is because "\n" is not escaped before being "injected" in
MODULE_ARGS and thus is interpreted by Python as a newline instead of just
two characters "\" and "n".
This behavior is undocumented, and I understand that Ansible tries hard to
not be Python specific. For most use cases, one should just need to write
YAML playbooks and use the built-in modules. But this small problem makes
the playbook implicitly dependent on Python literal string escaping rules.
What would you think of a patch trying to replace (in Runner._copy_file):
encoded_args = "\"\"\"%s\"\"\"" % module_args.replace("\"","\\\"")
by something like this:
encoded_args = repr(module_args)
An example to illustrate the difference:
$ python
module_args = r'regexp="hello\nworld"'
print "\"\"\"%s\"\"\"" % module_args.replace("\"","\\\"")
"""regexp=\"hello\nworld\""""
print repr(module_args)
'regexp="hello\\nworld"'
This is the end of this long message. Sorry!