ansible icon indicating copy to clipboard operation
ansible copied to clipboard

Feature Idea: Ability to fail entire playbook if one of included plays fail.

Open jamesongithub opened this issue 7 years ago • 12 comments

ISSUE TYPE
  • Feature Idea
COMPONENT NAME
  • ansible_playbook
ANSIBLE VERSION
ansible --version
ansible 2.2.0.0
  config file = 
  configured module search path = Default w/o overrides
CONFIGURATION
OS / ENVIRONMENT
SUMMARY

Non trivial playbooks can contain many plays. Sometimes downstream plays depend on previous plays being run first. It would be useful to be able to fail the entire playbook early if earlier plays in a playbook fail and not try to execute the rest of the playbook. In the example below, play 2 should not execute if play 1 fails. Currently play 2 will execute as long as it has hosts. This helps in a testing and production scenario. Perhaps make it configurable in ansible.cfg

STEPS TO REPRODUCE
# play 1
- hosts: localhost
  connection: local
  gather_facts: false
  become: false
  tasks:
    - include: roles/role1/tasks/stuff.yml

# play2 depends on play1
- hosts: hosts
  become: true
  pre_tasks:
    - include: roles/role2/tasks/stuff.yml
  roles:
    - role2
EXPECTED RESULTS
ACTUAL RESULTS

jamesongithub avatar Mar 10 '17 01:03 jamesongithub

@jamesongithub this sounds a lot like blocks + include ...

- hosts: foo
   tasks
       - block:
             - include: tasks1.yml
         rescue:
             - include: recovery_tasks.yml

Is that what you are going for or did I miss something?

needs_info

jctanner avatar Mar 10 '17 13:03 jctanner

Sorry, i updated the description to make it more clear. If play 1 fails, play 2 requires resources from play 1, so we want the playbook to fail early.

jamesongithub avatar Mar 10 '17 16:03 jamesongithub

Is there anyone working on this issue? Otherwise I would like to do this.

ankity10 avatar May 07 '17 07:05 ankity10

i dont think so @ankity10

jamesongithub avatar May 09 '17 01:05 jamesongithub

isn't it the purpose of http://docs.ansible.com/ansible/playbooks_error_handling.html#aborting-the-play ?

PhilEv avatar May 09 '17 16:05 PhilEv

@PhilEv it fails the current play, not the playbook

jamesongithub avatar May 09 '17 17:05 jamesongithub

+1 to this idea. We use a series of plays as it makes dealing with multiple inventory groups and roles with a large number of combinations of which groups need which roles, that made running multiple plays in the same playbook the easiest way to do this. But we also have requirements that if certain tasks fail for any host, we need a full stop on the entire playbook. I could set a fact and call the end_play meta as the first task of every subsequent play if that variable turns out to be true, but just having a playbook_fail meta to call would be much easier and cleaner.

ubermug avatar Apr 03 '19 20:04 ubermug

I would like to end the playbook without fail. Currently using end_play meta in the last play surely a meta for the whole playbook is welcomed.

kimonoki avatar May 20 '19 01:05 kimonoki

I have a use case that requires this functionality. If a failure happens on a play all the following plays must not run.

My use case is upgrades where certain groups of hosts must be upgraded before other groups. i.e group a, b, c, d, ect...

- hosts:  group_a
  strategy: host_pinned
  serial: 1
  any_errors_fatal: true
  become: true
  become_user: root
  roles:
    - upgrade

- hosts:  group_b
  strategy: host_pinned
  serial: 1
  any_errors_fatal: true
  become: true
  become_user: root
  roles:
    - upgrade

- hosts:  group_c
  strategy: host_pinned
  serial: 1
  any_errors_fatal: true
  become: true
  become_user: root
  roles:
    - upgrade

- hosts:  group_d
  strategy: host_pinned
  serial: 1
  any_errors_fatal: true
  become: true
  become_user: root
  roles:
    - upgrade

If any host in group b fails, the play for group c and d should not run. I've been trying to figure out a solution since ansible lacks a "fail the whole playbook" feature but I can't really find anything that works.

rmb938 avatar Jul 07 '20 14:07 rmb938

@jamesongithub: Greetings! Thanks for taking the time to open this issue. In order for the community to handle your issue effectively, we need a bit more information.

Here are the items we could not find in your description:

  • component name

Please set the description of this issue with an appropriate template from: https://github.com/ansible/ansible/tree/devel/.github/ISSUE_TEMPLATE

click here for bot help

ansibot avatar Oct 11 '20 15:10 ansibot

Is there a workaround for this?

Kevin-De-Koninck avatar Feb 12 '21 12:02 Kevin-De-Koninck

I used - fail: and any_errors_fatal: true as a workaround. Obviously it exits with status failed

OmarOdaini avatar Apr 21 '21 18:04 OmarOdaini

The ability to fail an entire playbook if an included play fails can be implemented via a subsequent play that compares ansible_play_hosts_all and ansible_play_batch variables. An example is presented below.

# play 1
- hosts: localhost
  connection: local
  gather_facts: false
  become: false
  tasks:
    - include: roles/role1/tasks/stuff.yml

####
# Assess whether the playbook can proceed
- hosts: ['all', 'localhost']
  gather_facts: no
  any_errors_fatal: yes
  run_once: yes
  tasks:
    - fail:
      when: '(ansible_play_hosts_all | difference(ansible_play_batch) | length) > 0'
####

# play2 depends on play1
- hosts: hosts
  become: true
  pre_tasks:
    - include: roles/role2/tasks/stuff.yml
  roles:
    - role2

If localhost doesn't succeed on running the tasks from the first play, ansible_play_hosts_all variable will include localhost and ansible_play_batch will not. Combined with run_once: yes and any_errors_fatal: yes, the forced fail will remove all targeted hosts from subsequent plays and abort the playbook.

amg1127 avatar Mar 22 '24 08:03 amg1127