1. Errors vs failures
Personally, I would like to differentiate between "errors" and "failures". Wrong playbook syntax, network connection issues are "ERRORS", which the playbook itself can do nothing about it.
On the other side, a task may fail to execute due to any reasons. I call such a failed task "FAILURE".
2. What will happen by default when a task failure occurs
By default, for any managed node, Ansible stops running remaining tasks when a task failed.
In the below example, task3 will not run.
[smstong@mk8 ansible]$ cat testbook.yml
- name: test play
hosts: localhost
tasks:
- name: task1
debug:
msg: task1 done
- name: task2
debug:
msg: task2 done
failed_when: True
# task3 will never be executed
- name: task3
debug:
msg: task3 done
3. Ignore failures
Sometimes, we want to run the remaining tasks even if a task fails. Ansible allows that by setting "ignore_errors".
[smstong@mk8 ansible]$ cat testbook.yml
- name: test play
hosts: localhost
tasks:
- name: task1
debug:
msg: task1 done
- name: task2
debug:
msg: task2 done
failed_when: True
ignore_errors: True
# tasl3 will execute even if task2 failed.
- name: task3
debug:
msg: task3 done
4. Action based on task failure status
"ignore_errors" works fine, but we may still need to know if a task failed or not, and run some tasks based on it.
Every task returns a result that contains a boolean typed property named "failed". If the task failed, this property was set to "True" by Ansible.
[smstong@mk8 ansible]$ cat testbook.yml
- name: test play
hosts: localhost
tasks:
- name: task1
debug:
msg: task1 done
- name: task2
debug:
msg: task2 done
failed_when: True
ignore_errors: True
register: task2_result
# task3 will run only if task2 failed
- name: task3
debug:
msg: task3 done
when: task2_result.failed
# task4 will run only if task2 didn't fail
- name: task4
debug:
msg: task4 done
when: not task2_result.failed
5. Overwrite the task status
Every module has its own logic to define if the task fails or not. For example, the "command" module fails based on the exit code of the command to run.
However, Ansible tasks allow you to overwrite the status of the module by setting "failed_when".
[smstong@mk8 ansible]$ cat testbook.yml
- name: test play
hosts: localhost
tasks:
# never fail
- name: task1
command: /bin/false
failed_when: false
# failed if user1 is not found
- name: task2
shell: cat /etc/passwd
register: r
failed_when: "'user1' not in r.stdout"
6. block failure handling
Checking every task is kind of tedious. Just like most programming languages' exception handling, Ansible support block/rescue/always.
[smstong@mk8 ansible]$ cat testbook.yml
- name: test play
hosts: localhost
tasks:
- name: block 1
block:
- name: task1
command: /bin/false
- name: task2
debug:
msg: task 2 will never run
rescue:
- name: task3
debug:
msg: task3 only run when task1 or task2 failed
always:
- name: task4
debug:
msg: task4 will always run
No comments:
Post a Comment