2355

How can I configure an “all or nothing” Ansible playbook?

I have a bunch of servers that need will be need frequent patching. I am planning on using Ansible to coordinate the patching process. The keep point here is that it must be an "all or nothing" patching. Either all servers are patched or none.

The tasks I was considering for my playbook would be something like: 1 - Go to all servers and take an lvm snapshot 2 - IIF task 1 works on all servers, apply the changes 3 - If one of the hosts fails for any reason, roll back the snapshot on ALL NODES.

The problem is that I am new to Ansible and I can't express this on a playbook. I have written this simple testing playbook:

--- - hosts: all strategy: linear tasks: - block: - debug: msg='Testing on {{ inventory_hostname }}...' - command: /home/amirsamary/activity.sh changed_when: false rescue: - debug: msg='Rollback of {{ inventory_hostname }}...' - debug: msg='I continued running tasks on {{ inventory_hostname }}...'

I have two hosts on my inventory. On the first node, activity.sh returns true and on the second node, activity.sh returns false. So, node2 will always fail. The problem is that the rescue tasks will only run for the failed host and not for all of them (as one would expect anyway) and the playbook keeps running the other tasks.

I have heard a lot about how good Ansible was to orchestrate complex tasks on thousands of servers. But I can't seem to find a way of safely implement an "all or nothing strategy" with it. What am I missing?

Answer1:

I bet there are many ways to implement this, here is one of them:

--- - hosts: all strategy: linear tasks: - debug: msg='Testing on {{ inventory_hostname }}...' - command: /home/amirsamary/activity.sh register: cmd_result ignore_errors: true - debug: msg='Rollback of {{ inventory_hostname }}...' when: play_hosts | map('extract', hostvars, 'cmd_result') | selectattr('failed','defined') | list | count > 0

What's done here?

    <li>we register result of script execution into cmd_result and ignore errors, if any</li> <li>with linear strategy, we will have command task completed on all hosts before next task being executed</li> <li>so we have cmd_result registered for every host</li> <li>to check if we need to rollback we extract cmd_result facts for all hosts in the current play, select those with failed defined, convert them to list and count them: if there is any, rollback.</li> </ul>

    So rollback task will be executed for all hosts if there is failed cmd_result for any of them.

    You may want to add this task after rollback task:

    - fail: msg='Patch command failed!' when: cmd_result | failed

    This way you will have your rollback tasks done and also mark problem hosts as failed.

Recommend

  • Ansible - Find max value and run action based on a result only on one host
  • Using variable in default filter in Ansible Jinja2 template
  • Conditional in Rails partial depending on the context page?
  • Microsoft.Web.Administration.ServerManager is connecting to the IIS Express instead of full IIS
  • Equivalent of every-pred, but for any of the given predicates
  • express.js can not get url's hash segment directly?
  • Using nodejs server with request package and function pipe()?
  • Cloud Functions for Firebase with custom HTTP path
  • download all file formats using angular and express JS
  • Global session variable in express.js route?
  • NodeJS - Disable JSONP on specific routes
  • Express.js : POST data as KEY of a req.body object instead of VALUE of req.body?
  • Can't connect Entity Framework to local SQL Server Express
  • How do I check if System::Collections:ArrayList is empty / nullptr / null?
  • Installing Perl6 and Panda on Ubuntu 15.10. Problems with bootstrap.pl
  • Can my PDF ping my server when it is opened?
  • C++ friend class std::vector
  • converter json to two dimensional array
  • SyntaxError: (irb):26: both block arg and actual block given
  • Why use database factory in asp.net mvc?
  • Ensure fsync did its job
  • preg_replace Double Spaces to tab (\\t) at the beginning of a line
  • Could not find rake using whenever rails
  • Android full screen on only one activity?
  • Can I check if a recipient has an automatic reply before I send an email?
  • ImageMagick, replace semi-transparent white with opaque white
  • Jenkins: How To Build multiple projects from a TFS repository?
  • Getting last autonumber in access
  • req.body is undefined - nodejs
  • jQuery show() function is not executed in Safari if submit handler returns true
  • How do I fake an specific browser client when using Java's Net library?
  • Accessing IRQ description array within a module and displaying action names
  • sending/ receiving email in Java
  • Apache 2.4 - remove | delete | uninstall
  • 0x202A in filename: Why?
  • Run Powershell script from inside other Powershell script with dynamic redirection to file
  • -fvisibility=hidden not passed by compiler for Debug builds
  • How to CLICK on IE download dialog box i.e.(Open, Save, Save As…)
  • Can Visual Studio XAML designer handle font family names with spaces as a resource?
  • How can i traverse a binary tree from right to left in java?