After executing an ansible playbook, I need the node names that were not reached. I thought about using AnsibleRunner
for running the ansible-playbook and I know of the special variables ansible_play_hosts
and ansible_play_hosts_all
which you can diff to get the unreachable nodes. But those special variables only exist in the context of ansible.
So how do I get the unreachable nodes from AnsibleRunner
(or a similar utility), without parsing ansible's output.
On Runner Objects
Currently I am creating a runner object and evaluating its variables after execution. I see that in the events I can theoretically look for unreachable nodes, but that seems to be quite sketchy.
One might also be able to write an event handler that specifically catches those events that indicate that a node is unreachable that handles those cases differently.
I also wrote a small fact registration that registers which nodes are unreachable which will be executed as a last task, but I couldn't access it yet:
- set_fact:
unreachable: "{{ ansible_play_hosts_all|difference(ansible_play_hosts) }}"
On ansible API
The ansible API has in its example a dictionary called host_unreachable
. While that sounds very promising I have two issues with it: I) I couldn't run the example II) The API will not be downwards compatible and therefore shouldn't be used externally.
What you are looking for is actually available out of the box in the Runner.stats
property once your playbook has run.
Example implementation
Given:
inv.yml
inventory ---
local_test:
vars:
ansible_connection: local
failling_hosts:
- test2
- test3
hosts:
test1:
test2:
test3:
test4:
unreachable:
hosts:
test5:
test.yml
playbook---
- hosts: all
tasks:
- name: dummy task for all
debug:
msg: task1 for all hosts
- name: blindly fail some hosts for test
assert:
that: inventory_hostname not in (failling_hosts | d([]))
- name: dummy task for survivors
debug:
msg: task2 for survivors
test.py
python scriptimport ansible_runner
runner = ansible_runner.run(
private_data_dir='.',
inventory='inv.yml',
playbook='test.yml',
quiet=False if len(sys.argv) > 1 and sys.argv[1] == '-v' else True
)
overall_failed = {
'unreachable': runner.stats['dark'].keys(),
'failed': runner.stats['failures'].keys()
}
for elem_type, elements in overall_failed.items():
for i, host in enumerate(elements):
if i == 0:
print(f'\nList of {elem_type} hosts:')
print(f'\t{host}')
We get (run with -v
if you want the playbook output too):
$ python test.py
List of unreachable hosts:
test5
List of failed hosts:
test2
test3