# Proper way to rollback an action if failed

**URL:** <https://forum.ansible.com/t/proper-way-to-rollback-an-action-if-failed/12744>\
**Category:** Ansible Project\
**Created:** [April 30, 2013, 9:45pm UTC](https://forum.ansible.com/t/proper-way-to-rollback-an-action-if-failed/12744 "2013-04-30T21:45:43Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![PePe\_Amengual](https://avatars.discourse-cdn.com/v4/letter/p/3e96dc/32.png) [@PePe\_Amengual](https://forum.ansible.com/u/PePe_Amengual)\
**Post date:** [April 30, 2013, 9:45pm UTC](https://forum.ansible.com/t/proper-way-to-rollback-an-action-if-failed/12744/1 "2013-04-30T21:45:43Z")

</div>

Hi.

I have been thinking to replace a webistrano deployment since is really slow and I don’t want to learn or ruby or capistrano so I was thinking to do all the deployment with ansible.

One nice thing that webistrano/capistrano does is the roll back but I have to say that is shitty roll back since you could run some db updates and then if one of your task is simply creating a dir after the db update the code could be rolled back but db changes were made already ( easy to fix with a temporary deployment db but it is slow) so I will like to do a better version of it.

so my questions are :

is there a way to catch an error while running a playbook ( like trap in bash) ?

Can I use the exit code on only\_if to run a a rollback playbook ?

Basically for now I just want to be able to re-link a release if one of the commands failed.

Thanks.

---

<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 30, 2013, 9:50pm UTC](https://forum.ansible.com/t/proper-way-to-rollback-an-action-if-failed/12744/2 "2013-04-30T21:50:09Z")

</div>

register: variable, gets you the return codes

ignore\_errors, lets you continue a play and deal with the errors yourself  
(normally ansible will stop the run for that host).

---

<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 30, 2013, 11:51pm UTC](https://forum.ansible.com/t/proper-way-to-rollback-an-action-if-failed/12744/3 "2013-04-30T23:51:51Z")

</div>

I’m not sure I understand what you want to do, maybe drop by irc to have a quick chat and figure out a solution.  
(por cierto, hablo Espanyol si te es mas facil).

---

<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:** [May 1, 2013, 12:01am UTC](https://forum.ansible.com/t/proper-way-to-rollback-an-action-if-failed/12744/4 "2013-05-01T00:01:07Z")

</div>

to use register add ignore errors, just to that task, that means, task  
fails but playbook continues. so if file link fails, the next task can do  
something about it

---

<div class="post-metadata">

**Author:** ![PePe\_Amengual](https://avatars.discourse-cdn.com/v4/letter/p/3e96dc/32.png) [@PePe\_Amengual](https://forum.ansible.com/u/PePe_Amengual)\
**Post date:** [May 1, 2013, 12:03am UTC](https://forum.ansible.com/t/proper-way-to-rollback-an-action-if-failed/12744/5 "2013-05-01T00:03:35Z")

</div>

Sorry My phone and the stupid autocorrection.

here is a better version of my message.

So I guess now the question is that if is possible to catch and error on an action because if I use ignore errors I could get pretty ugly.

Register is a possibility but then gain if I use it for example with the file module to create a link and it fails creating the link then that will just exit and I will not be able to do any further action, so to use a register I will have to use the command or shell module that is not that ideal.

It will be awesome to have something like if\_fail or undo\_if or something like that.

Thanks.

---

<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:** [May 1, 2013, 12:16am UTC](https://forum.ansible.com/t/proper-way-to-rollback-an-action-if-failed/12744/6 "2013-05-01T00:16:35Z")

</div>

Let me explain with example:

- hosts: 127.0.0.1  
connection: local  
gather\_facts: False  
tasks:

- file: path=/var/tmp src=/tmp state=link  
register: file\_result  
ignore\_errors: True

- debug: msg=“file failed, should do something here!”  
when\_failed: $file\_result

---

<div class="post-metadata">

**Author:** ![PePe\_Amengual](https://avatars.discourse-cdn.com/v4/letter/p/3e96dc/32.png) [@PePe\_Amengual](https://forum.ansible.com/u/PePe_Amengual)\
**Post date:** [May 1, 2013, 12:24am UTC](https://forum.ansible.com/t/proper-way-to-rollback-an-action-if-failed/12744/7 "2013-05-01T00:24:23Z")

</div>

Ohh I see that will work perfectly.

Gracias Brian.

---

<div class="post-metadata">

**Author:** ![PePe\_Amengual](https://avatars.discourse-cdn.com/v4/letter/p/3e96dc/32.png) [@PePe\_Amengual](https://forum.ansible.com/u/PePe_Amengual)\
**Post date:** [May 1, 2013, 12:29am UTC](https://forum.ansible.com/t/proper-way-to-rollback-an-action-if-failed/12744/8 "2013-05-01T00:29:41Z")

</div>

mmm now I have another question.

What If I have an action with ignore\_errors: True and then I have a when\_failed that will revert back the last action but at that point I want the playbook to stop.

can I use when\_failed to stop the playbook ?( sounds hacky, it’s like a brake and I don’t like it )

Can I use only\_if for all the rest of the tasks to check against the register variable ( of the failed action)?

Thanks.

---

<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:** [May 1, 2013, 12:30am UTC](https://forum.ansible.com/t/proper-way-to-rollback-an-action-if-failed/12744/9 "2013-05-01T00:30:58Z")

</div>

add

- fail: msg="aborting now that i tried to rollback"  
&nbsp;&nbsp;&nbsp;when\_failed: $file\_result

---

<div class="post-metadata">

**Author:** ![Michael\_DeHaan2](https://avatars.discourse-cdn.com/v4/letter/m/da6949/32.png) [@Michael\_DeHaan2](https://forum.ansible.com/u/Michael_DeHaan2)\
**Post date:** [May 1, 2013, 1:09am UTC](https://forum.ansible.com/t/proper-way-to-rollback-an-action-if-failed/12744/10 "2013-05-01T01:09:26Z")

</div>

It’s pretty common creed in the DevOps community that rollbacks are a lie 🙂

Always fail forward, fix the issue, and so on.

This is why using Ansible to work with load balancers is great… if the node fails, it fails while it is out of rotation, and your rolling update slice is smaller than your total node pool count, so you never hit outage.

Deploying the playbook to say “be at this version” is fine, but yes, database updates are always a level of complexity.

If you are using 1.2, the “when\_failed” stuff is the legacy form, it is actually a little simpler now:

when: file\_result.failed

You may wish to use “any\_errors\_fatal: True” (a 1.2 feature) in your playbook to say that the first error stops the breaks, but I think a serial update window is more appropriate.

---

<div class="post-metadata">

**Author:** ![PePe\_Amengual](https://avatars.discourse-cdn.com/v4/letter/p/3e96dc/32.png) [@PePe\_Amengual](https://forum.ansible.com/u/PePe_Amengual)\
**Post date:** [May 1, 2013, 5:57am UTC](https://forum.ansible.com/t/proper-way-to-rollback-an-action-if-failed/12744/11 "2013-05-01T05:57:09Z")

</div>

Thanks guys, this is what I need.

I will build the playbook and test it tomorrow.

---

<div class="post-metadata">

**Author:** ![Siarhei](https://avatars.discourse-cdn.com/v4/letter/s/90db22/32.png) [@Siarhei](https://forum.ansible.com/u/Siarhei)\
**Post date:** [July 3, 2014, 8:46pm UTC](https://forum.ansible.com/t/proper-way-to-rollback-an-action-if-failed/12744/12 "2014-07-03T20:46:05Z")

</div>

Sorry, but I don’t think it’s a good approach.  
I will explain why with the example.  
I have to install some “heavy environment” on cloud. In the beginning of the playbook I’m creating an instance of OracleDB (another host), and will use it for the main application which I’m installing in this playbook.  
So, if it’s “heavy environment” i will have hundreds tasks, and if something fails, I need to terminate OracleDB box as well. But how??? If I will use your suggestion I will have to set ignore\_errors after each task (!!! of hundreds), and I will duplicate the same code of termination my Oracle box after every task. It will work, but it will be the ugliest playbook.

Or bit better way (for this example): to use 2 playbooks in one shell script. If first fails second will be running for rollback actions.

But and this is not a good solution. As I see Ansible needs some tasks (like handlers) that will be executed if something breaks.

---

<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:** [July 3, 2014, 10:04pm UTC](https://forum.ansible.com/t/proper-way-to-rollback-an-action-if-failed/12744/13 "2014-07-03T22:04:49Z")

</div>

We intend to add a facility for a try/except type handler in the near future.
