There are a number of ways to handle fatal errors.
- Use fail to end a play and return "failed"
- Use the --check command line flag to run the playbook in a dry run mode
- Use check_mode to determine if any fatal errors would be returned
- Use failed_when to continue based on the task return code (this article)
- Use ignore_errors to ignore errors returned by a task
- Use meta: clear_host_errors to clear errors so that subsequent tasks are run
- Use meta: end_play to end a play for all hosts
- Use meta: end_host to end a play for certain hosts and return "skipped"
- Use block rescue always to run tasks even after a fatal error is returned
- Use stat to determine if /tmp/foo.txt exists and the when parameter to skip the lineinfile module if /tmp/foo.txt does not exist.
- Use stat to determine if /tmp/foo.txt exists and then use the file module and the when parameter to create /tmp/foo.txt if the file does not exist
There are a number of different Ansible tasks that can cause a playbook to cease execution, typically when the return code of a task is anything other than 0. As an example, let's say /tmp/foo.txt does not exist, and you attempt to append "Hello World" to /tmp/foo.txt using the lineinfile module.
---
- hosts: localhost
tasks:
- lineinfile:
path: /tmp/foo.txt
line: Hello World
- debug:
msg: "I am here"
...
Invoking this playbook will return fatal, like this, and the playbook would cease to move onto the remaining tasks. Notice in this example that the return code is 257. More on this in a moment.
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Destination /tmp/foo.txt does not exist !", "rc": 257}
Here is how the failed_when parameter and the register module could be used. In this example, the playbook will continue as long as the return code is greater than 1, which means if the return code is 0 or 1, the playbook will continue. However, in this example, the return code is 257, which is greater than 1, which means the playbook will fail at the lineinfile task.
---
- hosts: localhost
tasks:
- lineinfile:
path: /tmp/foo.txt
line: Hello World
register: out
failed_when: out.rc > 1
- debug:
msg: "I am here"
...
For this reason, here is how the failed_when parameter and the register module could be used to continue execution of the playbook. In this example, the playbook will continue as long as the return code is 0 or 1 or 257, since return code 257 is being returned in this example.
---
- hosts: localhost
tasks:
- lineinfile:
path: /tmp/foo.txt
line: Hello World
register: out
failed_when: out.rc not in [ 0, 1, 257 ]
- debug:
msg: "I am here"
...
Invoking the playbook should now return the following. Notice the lineinfile task contains ...ignoring and the debug task is processed and the play recap has ignore=1.
TASK [lineinfile]
ok: [localhost]
TASK [debug]
ok: [localhost] => {
"msg": "I am here"
}
PLAY RECAP
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Did you find this article helpful?
If so, consider buying me a coffee over at