Ansible global fail message when a task has failed on all hosts
I need a fail message when a task has failed on all hosts. For example:
- ios_facts:
gather_subset: min
failed_when: "{{ ansible_net_hostname }} contains 123"
where all of the hostnames contains 123 so it triggers a fail task
- fail:
msg: all of the hostnames contains 123
when: xxxxx
For example, given the inventory for testing
shell> cat hosts
host1 ansible_net_hostname=host_123_A
host2 ansible_net_hostname=host_123_B
host3 ansible_net_hostname=host_123_C
The play below shows how to find the lists
- hosts: all
gather_facts: false
tasks:
- debug:
var: ansible_net_hostname
- debug:
msg: |
All names: {{ _names }}
Search names: {{ _search }}
vars:
_names: "{{ hostvars|json_query('*.ansible_net_hostname') }}"
_search: "{{ _names|select('search', '123')|list }}"
run_once: true
gives
TASK [debug] ***********************************************************
ok: [host1] =>
ansible_net_hostname: host_123_A
ok: [host2] =>
ansible_net_hostname: host_123_B
ok: [host3] =>
ansible_net_hostname: host_123_C
TASK [debug] ***********************************************************
ok: [host1] =>
msg: |-
All names: ['host_123_A', 'host_123_B', 'host_123_C']
Search names: ['host_123_A', 'host_123_B', 'host_123_C']
Compare the length of the lists
- debug:
msg: all of the hostnames contains 123
vars:
_names: "{{ hostvars|json_query('*.ansible_net_hostname') }}"
_search: "{{ _names|select('search', '123')|list }}"
when: _names|length == _search|length
run_once: true
(Credit @Zeitounator for pointing to this option.)
The query above works if you target all hosts in the inventory. If you'd like to target a group of hosts use the special variable ansible_play_hosts_all and extract the variables from the hostvars. For example, given the inventory
shell> cat hosts
[test_123]
host[0001:1024]
[test_123:vars]
ansible_net_hostname=host_123_A
The play
- hosts: test_123
gather_facts: false
tasks:
- debug:
msg: |
All names: {{ _names|length }}
Search names: {{ _search|length }}
vars:
_names: "{{ ansible_play_hosts_all|
map('extract', hostvars, 'ansible_net_hostname')|
list }}"
_search: "{{ _names|select('search', '123')|list }}"
run_once: true
gives
TASK [debug] *****************************************************
ok: [host0001] =>
msg: |-
All names: 1024
Search names: 1024
To evaluate the condition compare the length of the lists as before.