Blocks, rescue and always
A block groups tasks so that rescue can catch their failure and always can run whatever happened. Keywords on the block apply to every task inside it.
- block: - name: Deploy the new release command: /opt/app/deploy.sh rescue: - name: Roll back command: /opt/app/rollback.sh - debug: msg: "{{ ansible_failed_task.name }} failed: {{ ansible_failed_result.msg | default('') }}" always: - name: Clear the maintenance flag command: rm -f /srv/app/MAINTENANCEWhen a task fails
Section titled “When a task fails”flowchart TD
F[a task fails] --> Q{an enclosing block<br/>has a rescue?}
Q -- yes --> R[run the nearest rescue]
Q -- no --> A[run each enclosing always,<br/>innermost first]
R --> OK[host is counted rescued<br/>and stays in the play]
A --> OUT[host leaves the play]
class R,OK key
The host looks outward for the nearest enclosing block with a non-empty rescue and enters it. Inside that rescue, two facts are set on the host: ansible_failed_task, the task as it was written, and ansible_failed_result, the result that failed. Both stay readable after the block and in later plays.
A host that recovers this way is counted as rescued in the recap and stays in the play. Only a failure that nobody rescued removes a host from the set of live hosts.
A failure inside a rescue is not caught by the same block. It goes to the next rescue further out.
always
Section titled “always”always runs whether the body succeeded, failed or was rescued. On the way out of an unrescued failure it runs too, innermost block first.
A failure inside an always ends that section: the rest of it is skipped, and the host keeps going outward, running the always of every block that still encloses it.
What is never rescued
Section titled “What is never rescued”- A host that never entered a rescue skips every step inside it, including a flush point and the handlers behind it.
- A host that cannot be reached leaves the play. There is nothing left to run a rescue on.
- When a
run_oncetask fails, the hosts that were waiting on it leave the play, even if a rescue keeps the host that ran it.
Differences from Ansible
Section titled “Differences from Ansible”- In
ansible_failed_task, a keyword this release does not execute reads asnullrather than as the reference’s default. A default such asconnection: "ssh"would describe something Volant does not honor. ansible_failed_taskhas one key per keyword and leaves out the six the reference keeps for itself (uuid,finalized,squashed,_resolved_action,async_val,loop_with). Itsargsholds what the playbook wrote, without the nineteen_ansible_*keys the reference adds.- A host whose
ansible_connectionnames a transport this release does not have is reported unreachable, so a rescue does not catch it. Ansible treats that as an ordinary task failure and rescues it.