I'm using programatically generated Ansible playbooks. In general, because playbooks are just YAML, this is straightforward. However, when using the "simple" key=value form, playbooks aren't pure YAML -- they include content embedded a shlex-parsable form.

To avoid the ambiguity in this form (is that key=value pair an argument to the command or an argument for ansible?), and have only a single format to parse and generate, I'm unconditionally using the complex args mechanism demonstrated by example in the ansible-examples repository.

This uses a syntax of the following kind:

action: module-name
  key1: value1
  key2: value2

...which is well and good. However, when trying to use this form for the shell or command modules (whose documentation describes the actual command as being passed in an argument named free_form), this doesn't work so well:

action: shell
  free_form: echo hello_world >/tmp/something
  creates: /tmp/something

When invoked, this runs the following:

/bin/sh -c " free_form='echo hello_world >/tmp/something'  "

...which is very much not what I'm trying to accomplish.

What's the right way to use Ansible modules taking "free-form" commands using pure YAML syntax?

2 Answers 2


Short answer: Don't use the command, raw, script, or shell modules. Write your own module that accepts the command as a "normal" argument.

Long answer:

In most cases, you can do this:

- shell: echo hello_world > /tmp/something
    creates: /tmp/something

However, this fails in some edge cases:

- shell: echo hello_world > creates=something
    creates: creates=something  # The file is named "creates=something"

I don't know of a general way to handle this, but a bash-specific solution is:

- shell: echo hello_world > "creates=something"
    creates: creates=something
  • Is there a data structure I can pass to any compliant YAML generator to make it emit - shell: ...? If this structure is something that can only be reliably generated by hand, that somewhat defeats the point of the question. Jun 13, 2014 at 17:50
  • @CharlesDuffy: I don't think you can escape the ... part in general. If you look at library/commands/command, you'll find a pretty generous regex matching creates=, removes=, chdir=, and so on. If you need to guarantee any command can be passed through, you'll have to write your own module.
    – Snowball
    Jun 13, 2014 at 19:30
  • Fair 'nuff. This is, in my mind, a significant design misfeature... but, well, is what it is. Jun 13, 2014 at 19:33

This is addressed in the Ansible documentation now.

# You can also use the 'args' form to provide the options. This command
# will change the working directory to somedir/ and will only run when
# /path/to/database doesn't exist.
- command: /usr/bin/make_database.sh arg1 arg2
    chdir: somedir/
    creates: /path/to/database

Note that there is no parameter named 'free_form'.

  • Does presence of args prevents k=v pairs from being parsed out from command, should any exist? (If so, this addresses the ambiguity cleanly; otherwise, it would seem to still exist). Apr 19, 2016 at 20:05

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .