Skip Ansible task when running in check mode?

AnsibleAnsible Playbook

Ansible 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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionaugurarView Question on Stackoverflow
Solution 1 - AnsibleStrahinja KustudicView Answer on Stackoverflow
Solution 2 - AnsibleaugurarView Answer on Stackoverflow
Solution 3 - AnsiblealmightyDataView Answer on Stackoverflow
Solution 4 - AnsibleMichael LooView Answer on Stackoverflow
Solution 5 - AnsibleBen.12View Answer on Stackoverflow
Solution 6 - AnsibleudondanView Answer on Stackoverflow