How to use Ansible check mode with async tasks

September 25, 2020

One of the most annoying things in ansible is this error:

TASK [Some long command like backup job] ***************************
task path: /home/avd/src/ansible/playbook.yml:4
fatal: [localhost]: FAILED! => {
    "changed": false,
    "msg": "check mode and async cannot be used on same task."
}

I often see it because I check every playbook that I run with “check mode”.

Check mode in Ansible is doing everything described in the task except actually executing it. It’s like --dry-run in svn if you remember those things.

Most of the time check mode works but when the async mode is enabled it fails with the above error. Async tasks are the ones that run for a long time and when your job fails in the middle after a few hours because your variable was rendered incorrect it is very frustrating.

So what if you really need to check async task?

Today, I found a way to do this:

  async: "{{ ansible_check_mode | ternary(0, 21600) }}"

This little trick checks for check mode and if it’s set the async will be disabled because it’s set 0. If check mode is not set it will set the desired async timeout.

Here is an example playbook with this trick applied:

---
- hosts: localhost
  tasks:
    - name: Some long command like backup job
      command: >-
        echo "/usr/local/bin/backup-job {{ date }} {{ destination }}"
      async: "{{ ansible_check_mode | ternary(0, 10800) }}"

Run it and see your check mode stuff:

$ ansible-playbook -C -vvv playbook.yml -e date='2020-09-25' -e destination='s3://mybucket/backups/'
ansible-playbook 2.9.13
...

PLAYBOOK: playbook.yml **********************************************************************************
1 plays in playbook.yml

PLAY [localhost] ****************************************************************************************

TASK [Gathering Facts] **********************************************************************************
task path: /home/avd/src/ansible/playbook.yml:2
...

TASK [Some long command like backup job] ****************************************************************
task path: /home/avd/src/ansible/playbook.yml:4
...
skipping: [localhost] => {
    "changed": false,
    "invocation": {
        "module_args": {
            "_raw_params": "echo \"/usr/local/bin/backup-job 2020-09-25 s3://mybucket/backups/\"",
            "_uses_shell": false,
            "argv": null,
            "chdir": null,
            "creates": null,
            "executable": null,
            "removes": null,
            "stdin": null,
            "stdin_add_newline": true,
            "strip_empty_ends": true,
            "warn": true
        }
    },
    "msg": "skipped, running in check mode"
}
META: ran handlers
META: ran handlers

PLAY RECAP **********************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0