In addition to rescue, we can also use another section, named always. This section of a block will always be executed irrespective of whether there were errors. This feature is handy for ensuring that the state of a system is always left functional, irrespective of whether a block of tasks was successful. As some tasks of a block may be skipped due to an error, and a rescue section is only executed when there is an error, the always section provides the guarantee of task execution in every instance.
Let's extend our previous example and add an always section to our block:
always:
- name: most important task
debug:
msg: "Never going to let you down"
Rerunning our playbook, we see the additional task displayed:
To verify that the always section does indeed always execute, we can alter the play so that the Git task is considered successful. The first part of this modified playbook is shown in the following snippet:
---
- name: error handling
hosts: localhost
gather_facts: false
tasks:
- block:
- name: delete branch bad
command: git branch -D badfeature
args:
chdir: /srv/app
register: gitout
failed_when:
- gitout.rc != 0
- not gitout.stderr is search('branch.*not found')
Note the changed failed_when condition, which will enable the git command to run without being considered a failure. The rest of the playbook (which should, by now, have been built up in the previous examples) remains unchanged.
This time, when we execute the playbook, our rescue section is skipped over, our previously masked-by-error task is executed, and our always block is still executed:
Note also that our previously lost task is now executed, as the failure condition for the delete branch bad task was changed such that it no longer fails in this play. In a similar manner, our rescue section is no longer needed, and all other tasks (including the always section) complete as expected.