Summary: A better way for aborting ansible playbook immediately if any host is unreachable.
Is there a way to abort Ansible playbook if any one of the host is unreachable. What I find that if it cannot reach a host it will still continue on and execute all the plays/tasks in the playbook.
All my playbooks I specify the max_fail_percentage of 0, but in this case ansible does not complain since all the hosts that are reachable can execute all the plays.
Currently I have a simple but hacky solution, but seeing if there is a better answer.
My current solution:
Since the first step as part of running the playbooks, ansible gathers facts for all the hosts. And in case where a host is not reachable it will not be able to. I write a simple play at the very beginning of my playbook which will use a fact. And in case a host is unreachable that task will fail with "Undefined variable error". The task is just a dummy and will always pass if all hosts are reachable.
See below my example:
- name: Check Ansible connectivity to all hosts
hosts: host_all
user: "{{ remote_user }}"
sudo: "{{ sudo_required }}"
sudo_user: root
connection: ssh # or paramiko
max_fail_percentage: 0
tasks:
- name: check connectivity to hosts (Dummy task)
shell: echo " {{ hostvars[item]['ansible_hostname'] }}"
with_items: groups['host_all']
register: cmd_output
- name: debug ...
debug: var=cmd_output
In case a host is unreachable you will get an error as below:
TASK: [c.. *****************************************************
fatal: [172.22.191.160] => One or more undefined variables: 'dict object' has no attribute 'ansible_hostname'
fatal: [172.22.191.162] => One or more undefined variables: 'dict object' has no attribute 'ansible_hostname'
FATAL: all hosts have already failed -- aborting
Inspired from other answers.
Using ansible-playbook 2.7.8.
Checking if there are any
ansible_facts
for each required hosts feels more explicit to me.alternatively, this looks simplier and more expressive
https://github.com/ansible/ansible/issues/18782#issuecomment-319409529
You could be a bit more explicit about the check:
I thought you could make a callback plugin to achieve this. Something like:
Except I can't find any good way to abort the entire playbook from that callback (the exception doesn't work, return value is ignored and while you could probably abuse
self.playbook
to stop things, there's no public API I can see).You can combine
any_errors_fatal: true
ormax_fail_percentage: 0
withgather_facts: false
, and then run a task that will fail if the host is offline. Something like this at the top of the playbook should do what you need:A bonus is that this also works with the
-l SUBSET
option for limiting matching hosts.I found a way to use a callback to abort the play as soon as the gather_facts has completed.
By setting the _play_hosts to an empty set, there are no hosts to continue with the play.
The result is something like: