Execute task (or handler) if any task failed

Viewed 35495

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.

2 Answers

I wrote up a full example on how to use Block/Rescue and the Slack module (not callback plugin) that provides meaningful error output with formatting:

The first answer here got me part of the way, but just for anyone else that comes this way struggling with the same thing!

A simple playbook example looks as follows:

playbooks/playbook.yml

- hosts: "{{ target_host | default('127.0.0.1') }}"
  gather_facts: true

  tasks:
  - block:
    - include_role:
        name: install_app
    - name: Greet the world
      shell: echo "hello world!"
    - fail:
       msg: "I've gone and failed the play!"
    rescue:
      - include_role:
          name: slack_handler
          tasks_from: failure

And in my slack_handler role (for reusability):

roles/slack_handler/tasks/failure.yml

- name: Notify Slack of Playbook Failure
  slack:
    username: 'Ansible'
    color: danger
    token: "{{ slack_webhook.split('https://hooks.slack.com/services/')[1] }}"
    channel: "#deployment-alerts"
    msg: "Ansible failed on *{{ ansible_hostname }} ({{ inventory_hostname }})* \n
    *Task*: {{ ansible_failed_task.name }} \n
    *Action*: {{ ansible_failed_task.action }} \n
    *Error Message*: \n ```{{ ansible_failed_result | to_nice_json }}``` "
  delegate_to: localhost

Ref: http://www.petewilcock.com/ansible-slack-failure-handler/

Related