On Wed, 8 Nov 2023 06:22:49 -0800 (PST)
Dimitri Yioulos <dimitri.g.yiou...@gmail.com> 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 ansible-project+unsubscr...@googlegroups.com.
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