Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute task (or handler) if any task failed

Tags:

I am using Ansible to deploy a Django website into my servers (production, staging, etc), and I would like to get a notification (via slack in this case) if and only if any task fails.

I can only figure out how to do it if a specified task fails (so I guess I could add a handler to all tasks), but intuition tells me there has to be an easier and more elegant option.

Basically what I am thinking of is:

--- - hosts: "{{hosts_to_deploy}}"  - tasks:      [...]    - name: notify slack of deploy failure     local_action:       module: slack       token: "{{slack_token}}"       msg: "Deploy failed on {{inventory_hostname}}"     when: # any task failed 

I have been diving into the Ansible documentation, specially in the error handling section, and answers here at SO, but I'm struggling to find an answer to my question. So any help will be much appreciated.

like image 446
vabada Avatar asked Mar 09 '16 13:03

vabada


People also ask

What happens when one task is failed in playbook?

Handlers and failure If a task notifies a handler but another task fails later in the play, by default the handler does not run on that host, which may leave the host in an unexpected state. For example, a task could update a configuration file and notify a handler to restart some service.

How can Error Handling be done in Ansible?

Ansible normally has defaults that make sure to check the return codes of commands and modules and it fails fast – forcing an error to be dealt with unless you decide otherwise. Sometimes a command that returns different than 0 isn't an error.

How do you fail a task in Ansible?

In ansible, fail module is avialble to fail ansible playbook with custom message. fail module is used to exit the progress when certain condition is met. msg parameter is used to specify the custome message. msg parameter is mandatory and default value is 'Failed as requested from task.

In which order do tasks executed inside plays or roles?

When you execute a playbook, in each play, all roles will be executed first, followed by the tasks, top down in the order that they are written.


1 Answers

I don't think a handler is a solution, because a handler will only be notified if the task reports a changed state. On a failed state the handler will not be notified.

Also, handlers by default will not be fired if the playbook failed. But that can be changed. For that you will need to set this in your ansible.cfg:

force_handlers = True 

But yes, there are better options available.

If you use Ansible 2 you can use the new blocks feature. Blocks group tasks together and have a rescue section which will be only triggered if any of the tasks have failed.

tasks:   - block:       - here       - go       - all       - your       - tasks     rescue:       - name: notify slack of deploy failure         local_action:           module: slack           token: "{{slack_token}}"           msg: "Deploy failed on {{inventory_hostname}}" 

Another option and especially interesting if you're using Ansible 1.x might be callback plugins. As the name suggests with these kind of plugins you can write callbacks which can be fired on various events.

Again, if you're using Ansible 2 you're lucky, because there already is a slack callback plugin available: https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/callback/slack.py

To use this plugin you need to enable it in your ansible.cfg:

callback_whitelist = slack 

And define some environment variables on your system for configuration:

 This plugin makes use of the following environment variables:     SLACK_WEBHOOK_URL (required): Slack Webhook URL     SLACK_CHANNEL     (optional): Slack room to post in. Default: #ansible     SLACK_USERNAME    (optional): Username to post as. Default: ansible     SLACK_INVOCATION  (optional): Show command line invocation                                   details. Default: False 

That plugin might need some modifications to fit your needs. If that's the case copy the source and store it relative to your playbook as callback_plugins/custom_slack.py and then enable it in your ansible.cfg:

callback_whitelist = custom_slack 

If you use Ansible 1.x you'll have to see how you can convert it. The API is different, examples for the old API can be found here: https://github.com/ansible/ansible/tree/v1.9.4-1/plugins/callbacks

like image 57
udondan Avatar answered Sep 21 '22 00:09

udondan