On Wed, 8 Nov 2023 06:22:49 -0800 (PST)
Dimitri Yioulos <[email protected]> wrote:

> ... my goal is to see if hosts are Ansible-pingable (not
> ICMP-pingable; I believe there's a difference) or not, then take
> *all* of the output, and create a report from it. Thus, i end up
> with a report of hosts that are either Ansible-pingable or not.

Dimitri, the play does what you want. The code is available also here
https://gist.github.com/vbotka/10c57962976dd1e2dd3e9411d3745c75

Let me help you to understand it step by step

>>> - hosts: test_01,test_05,test_06,test_07 
>>>   gather_facts: false 

There are 4 hosts in the play. Setup is off, hence no connections to
the remote host up till now

>>> vars: 
>>>
>>>   h_unr: "{{ dict(ansible_play_hosts_all| 
>>>                   zip(ansible_play_hosts_all| 
>>>                       map('extract', hostvars, 'unr'))) }}" 

This dictionary will be evaluated when referenced in the debug task

>>> tasks: 
>>>
>>>   - block: 
>>>       - ping: 
>>>         register: out 
>>>       - set_fact: 
>>>           unr: "{{ out.unreachable|d(false) }}" 
>>>     ignore_unreachable: true 

Here come the first connections to the remote hosts. There are 2
tasks in the block. The first one is the Ansible module ping, not the
ICMP ping. (Yes, you're right. There is a difference.) The second one
is the module set_fact. Because of the ignore statement the tasks in
the block won't fail if a host is unreachable.

If a host can be reached by ping there is no attribute *unreachable*
in the registered dictionary *out*. Therefor, the value of the
variables *unr* will be the default (alias d) value *false*.

If a host can't be reached the value of the attribute *unreachable*
is *true*.

>>>   - debug: 
>>>       var: h_unr 
>>>     run_once: true 
>>>     delegate_to: localhost 

Here is the report. Let's analyse the dictionary *h_unr*. In the
above block, all hosts created the variable *unr*. When you take the
list of all hosts in the play *ansible_play_hosts_all* [1] and *map*
the function to *extract* the *hostvars* [2] variable *unr*
  
  ansible_play_hosts_all|map('extract', hostvars, 'unr')

you get a list, for example, where only the first host was reached

  [false, true, true, true]

Then, *zip* this list with *ansible_play_hosts_all*

  [[test_01,false], [test_02,true], [test_03,true], [test_04,true]]

and apply the function *dict* [3]. Below is the expected result.
Enjoy!

>>> gives (abridged) 
>>>
>>> ok: [test_01 -> localhost] => 
>>> h_unr: 
>>>   test_01: false 
>>>   test_05: true 
>>>   test_06: true 
>>>   test_07: true 

[1]
https://docs.ansible.com/ansible/latest/reference_appendices/special_variables.html
[2]
https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_filters.html#selecting-values-from-arrays-or-hashtables
[3]
https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_filters.html#combining-items-from-multiple-lists-zip-and-zip-longest

-- 
Vladimir Botka

-- 
You received this message because you are subscribed to the Google Groups 
"Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/ansible-project/20231108220631.48c0146c%40gmail.com.

Attachment: pgprBG_jdOr9m.pgp
Description: OpenPGP digital signature

Reply via email to