ansible
ansible copied to clipboard
Feature Idea: Ability to fail entire playbook if one of included plays fail.
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 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
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.
Is there anyone working on this issue? Otherwise I would like to do this.
i dont think so @ankity10
isn't it the purpose of http://docs.ansible.com/ansible/playbooks_error_handling.html#aborting-the-play ?
@PhilEv it fails the current play, not the playbook
+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.
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.
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.
@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
Is there a workaround for this?
I used - fail:
and any_errors_fatal: true
as a workaround. Obviously it exits with status failed
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.