# Run handler on failed task

**URL:** <https://forum.ansible.com/t/run-handler-on-failed-task/15015>\
**Category:** Ansible Project\
**Created:** [April 15, 2014, 8:24am UTC](https://forum.ansible.com/t/run-handler-on-failed-task/15015 "2014-04-15T08:24:26Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Joachim\_Friberg](https://avatars.discourse-cdn.com/v4/letter/j/6a8cbe/32.png) [@Joachim\_Friberg](https://forum.ansible.com/u/Joachim_Friberg)\
**Post date:** [April 15, 2014, 8:24am UTC](https://forum.ansible.com/t/run-handler-on-failed-task/15015/1 "2014-04-15T08:24:26Z")

</div>

Hi,

So what I want to do, and have not yet found a way todo yet, is to run a handler if a taks fails rather then if it succeeds.  
For example I want to do a yum install mysql on a server, but this server does not have python-simplejson and/or other packages that is neccesary for Ansible.  
How do I then trigger a “fix” and then preferably rerun the failed task. Is this possible?

Something similar to:

- hosts: mysql  
user: admin  
vars:  
passwd: VeryHardPasswd  
user: analytics  
tasks:
- name: create user Analytics  
mysql\_user: name={{ user }}  
password={{ passwd }}  
priv=_._:SELECT,‘SHOW DATABASES’  
state=present  
login\_user=ROOT  
login\_password=PASSWORD  
register: mysql\_result  
ignore\_errors: True  
notify\_on\_fail: install mysqldb-python  
handlers:
- name: Install mysqldb-python  
raw: sudo yum install -y MySQL-python

---

<div class="post-metadata">

**Author:** ![Dick\_Davies](https://avatars.discourse-cdn.com/v4/letter/d/b9e5f3/32.png) [@Dick\_Davies](https://forum.ansible.com/u/Dick_Davies)\
**Post date:** [April 15, 2014, 3:34pm UTC](https://forum.ansible.com/t/run-handler-on-failed-task/15015/2 "2014-04-15T15:34:01Z")

</div>

In this specific case you'd just assert the python-simplejson package  
exists right?  
If it's already installed then nothing happens, and you'll be able to  
skip on to the  
other tasks.

If of course you're in a catch-22 situation (can't run ansible to set  
up ansible pre-requisites),  
then you'll need to seed your base image with what's required.

For example, my kickstarts bring up a machine with

\* SSHd enabled and tcp/22 inbound permitted on the local firewall  
\* an 'ansible' account with a pre-defined list of SSH keys in its  
authorised\_keys file  
\* passwordless sudo configured for that account

Everything else is managed by Ansible.

This general approach also applies to CM with puppet, chef, etc.  
(which typically  
have much more requirements).

---

<div class="post-metadata">

**Author:** ![Christian\_Rusa](https://avatars.discourse-cdn.com/v4/letter/c/f0a364/32.png) [@Christian\_Rusa](https://forum.ansible.com/u/Christian_Rusa)\
**Post date:** [April 16, 2014, 5:36am UTC](https://forum.ansible.com/t/run-handler-on-failed-task/15015/3 "2014-04-16T05:36:40Z")

</div>

To be honest, I would also be interested in a solution to this.

Of course all the machines, that I install myself (preseed, kickstart, ...) meet the requirements for ansible.

For already existing machines which should be managed by us, the requirements are somewhere in the middle of met or unmet.

To my knowledge python-simplejson (required on Python 2.4 boxes) can only be installed using the raw module and not with the apt or yum module.  
Therefore this is a task which I'd not like to be executed on every run.

Maybe the first task in the list could be an ansible ping and if it fails do some brute-force raw commands.  
....  
And as writing this I answered my question 🙂

My prototype looks like this:

- hosts: all  
&nbsp;&nbsp;&nbsp;user: root  
&nbsp;&nbsp;&nbsp;tasks:  
&nbsp;&nbsp;&nbsp;- name: ping  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ping:  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;register: result  
&nbsp;&nbsp;&nbsp;- name: conditional task  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;raw: here\_your\_command  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;when: result|failed

Cheers  
Christian

---

<div class="post-metadata">

**Author:** ![Joachim\_Friberg](https://avatars.discourse-cdn.com/v4/letter/j/6a8cbe/32.png) [@Joachim\_Friberg](https://forum.ansible.com/u/Joachim_Friberg)\
**Post date:** [April 16, 2014, 8:41am UTC](https://forum.ansible.com/t/run-handler-on-failed-task/15015/4 "2014-04-16T08:41:56Z")

</div>

Hmm -  
I have fixed it with a when statement and then notify a handler that in turns install and notifies yet another handler.  
Thou this solution does not look nice and I would really like to not relay on any other managementsystem other then Ansible.

My sollution to problem looks like this atm:

- name: something  
  
register: something  
ignore\_errors: True

- name: simplejson  
raw: “yum -y install python-simplejson”  
when: something|failed  
notify:

- somethingAgain

handlers:

- name: somethingAgain  

…

The above one works kinda but is not the best looking.

Preffered would be similar to:

- name: something  
  
register: something  
notify\_when: something|failed
- simplejson

handlers:

- name: simplejson  
raw: “yum -y install python-simplejson”

Does anyone know if something like this might be implemented in the near future or if anyone can point me to where I can suggest a “patch” 🙂

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [April 17, 2014, 2:23am UTC](https://forum.ansible.com/t/run-handler-on-failed-task/15015/5 "2014-04-17T02:23:39Z")

</div>

You are definitely overcomplicating it.

There’s no reason to need the register really.

- shell: yum -y install python-simplejson

Yum naturally is smart enough to not do anything if the package is already installed, so it takes care of the “idempotence” (I kinda still hate the over-complexity of that word, but it’s a word) for you.

---

<div class="post-metadata">

**Author:** ![Christian\_Rusa](https://avatars.discourse-cdn.com/v4/letter/c/f0a364/32.png) [@Christian\_Rusa](https://forum.ansible.com/u/Christian_Rusa)\
**Post date:** [April 17, 2014, 6:35am UTC](https://forum.ansible.com/t/run-handler-on-failed-task/15015/6 "2014-04-17T06:35:24Z")

</div>

As we have to manage a mixed environment, we do have different packagemanagers.  
So I often use when clauses like this  
when: ansible\_pkg\_mgr == "apt"  
I really like facts to be available in my playbooks.

So my goal is/was to avoid running raw yum commands against a debian or apt against Red Hat in our global site playbook.

A other thing I want to avoid is having a complicated documentation about which playbook to run against a server.  
I am dreaming of a one-size-fits-all playbook 🙂

Will the shell module work if the install of python-simplejson is required?  
At least for the install of python (Minimal debian does not have it) I need to go for raw.

---

<div class="post-metadata">

**Author:** ![Brian\_Coca1](https://avatars.discourse-cdn.com/v4/letter/b/278dde/32.png) [@Brian\_Coca1](https://forum.ansible.com/u/Brian_Coca1)\
**Post date:** [April 17, 2014, 11:46am UTC](https://forum.ansible.com/t/run-handler-on-failed-task/15015/7 "2014-04-17T11:46:57Z")

</div>

- shell: yum install python-simplejson  
&nbsp;&nbsp;ignore\_errors: true  
&nbsp;&nbsp;changed\_when: False

ugly but should work

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan1](https://avatars.discourse-cdn.com/v4/letter/m/5e9695/32.png) [@Michael\_DeHaan1](https://forum.ansible.com/u/Michael_DeHaan1)\
**Post date:** [April 17, 2014, 11:57am UTC](https://forum.ansible.com/t/run-handler-on-failed-task/15015/8 "2014-04-17T11:57:52Z")

</div>

This is also a bit weird looking, but you could abuse the "removes"  
parameter to the shell command, which does not run a command when a binary  
does not exist.

The downside is this makes your playbook look weirder.

- shell: yum install python-simplejson removes=/usr/bin/yum

referenced here: [http://docs.ansible.com/shell\_module.html](http://docs.ansible.com/shell_module.html)

Generally this is done to prevent running installers a second time, and  
will not remove the indicated file.

Another solution is usually to have the kickstart or base image slightly  
prepped in the case of those older OSes, but we definitely don't require it.
