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.
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
alternatively, this looks simplier and more expressive
- hosts: myservers
become: true
pre_tasks:
- name: Check ALL hosts are reacheable before doing the release
assert:
that:
- ansible_play_hosts == groups.myservers
fail_msg: 1 or more host is UNREACHABLE
success_msg: ALL hosts are REACHABLE, go on
run_once: yes
roles:
- deploy
https://github.com/ansible/ansible/issues/18782#issuecomment-319409529
You could be a bit more explicit about the check:
- fail: Abort if hosts are unreachable
when: "'ansible_hostname' not in hostvars[item]"
with_items: groups['all']
I thought you could make a callback plugin to achieve this. Something like:
class CallbackModule(object):
def runner_on_unreachable(self, host, res):
raise Exception("Aborting due to unreachable host " + host)
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With