ansible/ansible — pull request #8043 by anoutsider (2014-07-06 13:09:23+00:00)
Title: on_failure error handlers

Added `on_failure` error handlers similar to notify handlers except these will run after each task/host they are attached to.

this could be considered a simple interface for error handling similar to `ignore_errors/register/when` except it allows for a cleaner playbooks, by grouping error handling tasks in separate files, it also supports inclusion in roles auto loading directory structure under the `role/errors` folder, it works with `failed_when` as well.

`role handlers go into an /errors directory inside the role main directory and are loaded from main.* file with the ability to use includes just like normal tasks/handlers`

**Things to note:**
`*ignore_errors*` i thought about making ignore_errors the default behavior when using on_failure with any task, it kinda makes sense since it's required for the feature to run properly, but need to look into it further..

`*using includes and handlers names*` unlike notify handlers there is no unique name checking for previously triggered handlers, need to consider if this is the right way to go or should we add the same checks present in notify handlers to ensure "an error handler is only ran once"

**Final thoughts**
i'd love to hear what you guys think about this? i am fairly new to ansible been using it for about a month and i love it, but felt like i need a cleaner way to handle errors, my use case for this is single host deployment.. for instance deploying a new appserver in a cloud cluster and wanting a way to rollback on failure without filling the playbook with error catch/handling tasks.

this is also the first time i have worked with python, so be gentle :) and please let me know if there is a better way to do this.

**Examples :**

**Single error handler in a playbook**
```
- name: test error handlers in playbook
hosts: all
gather_facts: False
connection: local
tasks:
- name: test the error handlers with a single handler
shell: wall 'beep'
ignore_errors: yes
on_failure:
- playbook error handler
error_handlers:
- name: playbook error handler
debug: msg="Play Failed"
```

**Multiple error handler in a playbook**
```
- name: test multiple error handlers in playbook
hosts: all
gather_facts: False
connection: local
tasks:
- name: test the error handlers with multiple handler
shell: wall 'beep'
ignore_errors: yes
on_failure:
- playbook error handler 1
- playbook error handler 2
- playbook error handler 3
error_handlers:
- name: playbook error handler 1
debug: msg="Play Failed"
- name: playbook error handler 2
debug: msg="Do something here"
- name: playbook error handler 3
debug: msg="Do something else.. fire fail?"
```

**Error handlers in roles, Conditional handlers, when_failed**
**in a role tasks file...**
```
- name: test the error handlers with multi conditional error handlers and failed_when
shell: echo 'test'
register: result
failed_when: result is defined
ignore_errors: yes
on_failure:
- 1st error handler
- 2nd error handler
- 3rd conditional error handler
```
**in a role error handlers file(s)...**
`role_dir\errors\main.yml`
```
- name: 1st error handler
set_fact:
error_handler_called: True

- name: 2nd error handler
debug: msg="2nd error handler called"

- name: 3rd conditional error handler
debug: msg="3rd error handler will never be called"
when: inventory_hostname == none

- include: include_handler.yml
```
`role_dir\errors\include_handler.yml`
```
- name: include 1st error handler
set_fact:
error_handler_called: True

- name: include 2nd error handler
debug: msg="include error handler called"

- name: 3rd conditional error handler
debug: msg="another include error handler"
```