A subset of the command family of modules (command, shell, and script) has a pair of special arguments that will influence whether the task work has already been done, and thus, whether or not a task will result in a change. The options are creates and removes. These two arguments expect a file path as a value. When Ansible attempts to execute a task with the creates or removes arguments, it will first check whether the referenced file path exists.
If the path exists and the creates argument was used, Ansible will consider that the work has already been completed and will return ok. Conversely, if the path does not exist and the removes argument is used, then Ansible will again consider the work to be complete, and it will return ok. Any other combination will cause the work to actually happen. The expectation is that whatever work the task is doing will result in either the creation or removal of the file that is referenced.
The convenience of creates and removes saves developers from having to do a two-task combo. Let's create a scenario where we want to run the script frobitz from the files/ subdirectory of our project root. In our scenario, we know that the frobitz script will create a path, /srv/whiskey/tango. In fact, the source of frobitz is the following:
#!/bin/bash rm -rf /srv/whiskey/tango mkdir -p /srv/whiskey/tango
We don't want this script to run twice as it can be destructive to any existing data. Replacing the existing tasks in our error.yaml playbook, the two-task combo will look like this:
- name: discover tango directory
stat: path=/srv/whiskey/tango
register: tango
- name: run frobitz
script: files/frobitz --initialize /srv/whiskey/tango
when: not tango.stat.exists
Assuming that the file already exists, the output will be as follows:
If the /srv/whiskey/tango path did not exist, the stat module would have returned far less data, and the exists key would have a value of false. Thus, our frobitz script would have been run.
Now, we'll use creates to reduce this down to a single task:
- name: run frobitz
script: files/frobitz
args:
creates: /srv/whiskey/tango
This time, our output will be slightly different:
On this occasion, we simply skipped running the script altogether as the directory already existed before the playbook was even run. This saves time during the playbook execution and also prevents any potentially destructive actions that might occur from running a script.