Skip Ansible task when running in check mode?
AnsibleAnsible PlaybookAnsible Problem Overview
I'm writing an Ansible playbook and have a task which will always fail in check mode:
hosts: ...
tasks:
- set_fact: filename="{{ansible_date_time.iso8601}}"
- file: state=touch name={{filename}}
- file: state=link src={{filename}} dest=latest
In check mode, the file will not be created so the link
task will always fail. Is there a way to mark such a task to be skipped when running in check mode? Something like:
- file: state=link src={{filename}} dest=latest
when: not check_mode
Ansible Solutions
Solution 1 - Ansible
Ansible 2.1 supports ansible_check_mode
magic variable which is set to True
in check mode (official docs). This means you will be able to do this:
- file:
state: link
src: '{{ filename }}'
dest: latest
when: not ansible_check_mode
or
- file:
state: link
src: '{{ filename }}'
dest: latest
ignore_errors: '{{ ansible_check_mode }}'
whichever you like more.
Solution 2 - Ansible
Here is a sort of hacky solution:
hosts: ...
tasks:
- command: /bin/true
register: noop_result
- set_fact: check_mode={{ noop_result|skipped }}
- set_fact: filename="{{ansible_date_time.iso_8601}}"
- file: state=touch name={{filename}}
- file: state=link src={{filename}} dest=latest
when: not check_mode
In check mode, the command
task will be skipped so check_mode
will be set to true
. When not in check mode, the task should always succeed and check_mode
will be set to false
.
Solution 3 - Ansible
I had the same kind of situation with unarchive
:
unarchive
fails in check mode if the archive doesn't exist and also if the destination directory doesn't exist (both done in the steps prior to unarchive
).
I solved this problem by setting always_run: true
to the preparation steps so that they are also executed in check mode:
---
- name: create artifact directory
file: {{ artifact_dest_dir }} state=directory
always_run: true
- name: download artifact on the remote host
get_url:
url={{ artifact_url }}
dest={{ artifact_dest_dir }}/{{ artifact_filename }}
force=yes
always_run: true
- name: unpack build artifact
unarchive: src={{ artifact_dest_dir }}/{{ artifact_filename }}
dest={{ artifact_dest_dir }}
copy=no
It works in my case, but with time dependent directories, this might not be a good solution.
Solution 4 - Ansible
Although there is an accepted answer already, I wanted to mention that the solution mentioned by augurar did not work for me as I kept getting the following error: skipped expects a dictionary
What ended working for me was a slightly less hacky solution by passing and extra variable with the -e
flag as follow:
# On the terminal
ansible-playbook [...] --check -e '{"check_mode":true}'
# In the playbook or role
when: [...] and not check_mode
# In the proper `group_vars/` file
check_mode: false
Let me know what you guys think!
Solution 5 - Ansible
Other options to be aware of are tags or the --step
option.
Tags
tasks:
- set_fact: filename="{{ansible_date_time.iso8601}}"
- file: state=touch name={{filename}}
- file: state=link src={{filename}} dest=latest
tags:
- test
Then the Ansible command to use would be:
ansible-playbook example.yml --skip-tags "test" --check
There are other examples for skipping/specifying the tasks you would like to run using tags in the Ansible tags documentation.
Start and Step
Ansible also provides a nice step-by-step debugging mode with the --step
option.
Running ansible-playbook example.yml --step --check
will interactively take you through each task in your playbook
From the "Start and Step" section of the Ansible documentation:
> This will cause ansible to stop on each task, and ask if it should execute that task. Say you had a task called “configure ssh”, the playbook run will stop and ask:
>
> Perform task: configure ssh (y/n/c):
>
> Answering “y” will execute the task, answering “n” will skip the task, and answering “c” will continue executing all the remaining tasks without asking.
Solution 6 - Ansible
You probably could just set a when: filename is defined
to all tasks. Downside is, you can not fail in normal mode if filename
would not be defined.
hosts: ...
tasks:
- set_fact: filename="{{ansible_date_time.iso_8601}}"
- file: state=present name={{filename}}
when: filename is defined
- file: state=link src={{filename}} dest=latest
when: filename is defined