Score:0

Ansible global fail message when a task has failed on all hosts

cn flag
raw

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
Score:2
br flag

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.

cn flag
raw
Thank you ! I have another case where I need to select the facts that are blank, how could I make this to work ? `_search: "{{ _names|select('search', '')|list }}"`
Zeitounator avatar
fr flag
I think OP wants to know if all hostnames **in the host play loop** pass the test or not. Your answer is looking at the entire inventory regardless of the current targets in play.
Zeitounator avatar
fr flag
@raw other questions go in a new post, or at the very least in an edit to your current question, not in a comment. Thanks.
br flag
@Zeitounator: There are no other hosts in *hostvars* except all hosts in the play.
Zeitounator avatar
fr flag
@VladimirBotka I have to disagree on this last one: https://gist.github.com/zeitounator/3a3ac34b96ccd49998523adf7da3e1cd as you will see I created a play targetting a specific group and hostvars yet contains all entries for all targets in the entire inventory. Meanwhile I apparently misinterpreted from the question as that seem to do the job anyway ;)
br flag
@Zeitounator. I see. I updated the answer. Thank you.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.