Farid Nouri Neshat
Farid Nouri Neshat

Reputation: 30430

How to catch errors in handlers in Ansible?

The handler in my code fails in some cases which then causes the whole playbook run to crash and I would like to catch those failures in the handler and do some sort of clean up.

Here's my playbook where I would ideally like the Rescue when handler fails task to run:

- hosts: localhost
  tasks:
    - name: something something
      block:
        - name: Print a message
          debug: msg='I execute normally'
          changed_when: yes
          notify: failing handler
      rescue:
        - name: Rescue when handler fails
          debug:
            msg: 'Rescue'
  handlers:
    - name: failing handler
      command: /bin/false

How can I catch the failure from this failing handler and run some tasks for cleanup?

Upvotes: 2

Views: 1483

Answers (2)

seshadri_c
seshadri_c

Reputation: 7340

By default handlers run at the end of the section (pre_tasks, tasks, etc.) from where they are notified. However it is possible to trigger the handler immediately after a task by using a meta action, i.e. - meta: flush_handlers.

Using this technique, we can trigger the handler immediately after the Print a message task. Then the playbook can continue with the next task(s).

For example:

  tasks:
    - name: Print a message
      debug:
        msg: i execute normally
      changed_when: true
      notify: failing handler

    - meta: flush_handlers

    - name: rescue when handler fails
      debug:
        msg: rescue
      when: _handler_status | default({}) is failed

  handlers:
    - name:  failing handler
      command: /bin/false
      register: _handler_status
      ignore_errors: true

As rightly pointed out by @Zeitounator, flushing handlers is fine for the above example where there is only 1 notifying task. However it may be undesirable when there are chances of other tasks notifying other handlers. In such case, the task can go under post_tasks section. Like below:

  tasks:
    - name: Print a message
      debug:
        msg: i execute normally
      changed_when: true
      notify: failing handler

  post_tasks:
    - name: rescue when failing handler fails
      debug:
        msg: rescue
      when: _handler_status | default({}) is failed

  handlers:
    - name:  failing handler
      command: /bin/false
      register: _handler_status
      ignore_errors: true

Upvotes: 2

Zeitounator
Zeitounator

Reputation: 44645

For the record, the above can't work as the time when your handler is notified and the time it will effectively run are totally distinct. You need to catch the failure when the handler runs, not when it is notified.

I would go that way.

Put your handler tasks in a file my_failing_handler.yaml

- block:
    - name: the task that might fail
      command: /bin/false
  rescue:
    - name: rescue when handler fails
      debug:
        msg: "rescue"

Then in your main playbook:

- hosts: localhost
  tasks:
    - name: Print a message
      debug: msg='I execute normally'
      changed_when: yes
      notify: failing handler

  handlers:
    - name: failing handler
      include_tasks: my_failing_handler.yaml

Upvotes: 3

Related Questions