# Accessing other hosts facts works in debug task, but not anywhere else

**URL:** <https://forum.ansible.com/t/accessing-other-hosts-facts-works-in-debug-task-but-not-anywhere-else/6098>\
**Category:** Get Help\
**Tags:** variables, ansible-core\
**Created:** [May 31, 2024, 7:02am UTC](https://forum.ansible.com/t/accessing-other-hosts-facts-works-in-debug-task-but-not-anywhere-else/6098 "2024-05-31T07:02:46Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![raspbeguy](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/raspbeguy/32/3623_2.png) [@raspbeguy](https://forum.ansible.com/u/raspbeguy)\
**Post date:** [May 31, 2024, 7:02am UTC](https://forum.ansible.com/t/accessing-other-hosts-facts-works-in-debug-task-but-not-anywhere-else/6098/1 "2024-05-31T07:02:46Z")

</div>

Hello, I have a group of hosts that have to access to each others IP address. I have the following code:

```yaml
- debug:
    var: hostvars[item]['ansible_default_ipv4']['address']
  loop: "{{ groups[cluster_name] | flatten(levels=1) }}"

- name: Register private IP addresses of the cluster
  set_fact:
    cluster_ips: "{{ cluster_ips | default({}) | combine({item: hostvars[item]['ansible_default_ipv4']['address']}) }}"
  loop: "{{ groups[cluster_name] | flatten(levels=1) }}"

```

You can see that I access the same facts in `debug` and in `set_fact`. The first task works perfectly but the second one fails.

```auto
fatal: [host1]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'ansible.vars.hostvars.HostVarsVars object' has no attribute 'ansible_default_ipv4'. 'ansible.vars.hostvars.HostVarsVars object' has no attribute 'ansible_default_ipv4'\n\nThe error appears to be in '/home/raspbeguy/repo/infra/ansible/roles/myrole/tasks/main.yml': line 10, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n- name: Register private IP addresses of the cluster\n ^ here\n"}

```

before trying with `set_fact` I was trying to use it in a template, didn’t work either.

I’m using the last version of ansible available on pip:

```plaintext
ansible [core 2.16.7]
  config file = /home/raspbeguy/repo/infra/ansible/ansible.cfg
  configured module search path = ['/home/raspbeguy/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/raspbeguy/repo/infra/ansible/venv/lib/python3.10/site-packages/ansible
  ansible collection location = /home/raspbeguy/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/raspbeguy/repo/infra/ansible/venv/bin/ansible
  python version = 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] (/home/raspbeguy/repo/infra/ansible/venv/bin/python3)
  jinja version = 3.1.4
  libyaml = True

```

I don’t understand why this is happening.

---

<div class="post-metadata">

**Author:** ![chris](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/chris/32/293_2.png) [@chris](https://forum.ansible.com/u/chris)\
**Post date:** [May 31, 2024, 9:38am UTC](https://forum.ansible.com/t/accessing-other-hosts-facts-works-in-debug-task-but-not-anywhere-else/6098/2 "2024-05-31T09:38:45Z")

</div>

You need to [gather\_facts](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/gather_facts_module.html) in a loop for the all the hosts first?

---

<div class="post-metadata">

**Author:** ![raspbeguy](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/raspbeguy/32/3623_2.png) [@raspbeguy](https://forum.ansible.com/u/raspbeguy)\
**Post date:** [May 31, 2024, 12:31pm UTC](https://forum.ansible.com/t/accessing-other-hosts-facts-works-in-debug-task-but-not-anywhere-else/6098/3 "2024-05-31T12:31:14Z")

</div>

Hello @chris,

What do you mean by running it in a loop? `gather_facts` doesn’t take any host argument (I guess it gather facts from all hosts) so I don’t see how and why running it in a loop. Either way, ansible gather facts already at the playbook start, and even after I added this task manually it won’t work either.

---

<div class="post-metadata">

**Author:** ![chris](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/chris/32/293_2.png) [@chris](https://forum.ansible.com/u/chris)\
**Post date:** [May 31, 2024, 12:42pm UTC](https://forum.ansible.com/t/accessing-other-hosts-facts-works-in-debug-task-but-not-anywhere-else/6098/4 "2024-05-31T12:42:48Z")

</div>

Sorry if I misunderstood the issue, I saw this error:

> The error was: ‘ansible.vars.hostvars.HostVarsVars object’ has no attribute ‘ansible\_default\_ipv4’.

And assumed it was a result of facts not having being gathered for a host, but perhaps that isn’t the case here?

If that is the case I was thinking of something like this to ensure that the facts are gathered for all the hosts:

```yaml
- name: Gather facts for all hosts
  ansible.builtin.gather_facts:
  delegate_to: "{{ host }}"
  loop: "{{ hosts }}"
  loop_control:
    loop_var: host

```

---

<div class="post-metadata">

**Author:** ![bcoca](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bcoca/32/9269_2.png) [@bcoca](https://forum.ansible.com/u/bcoca)\
**Post date:** [May 31, 2024, 1:40pm UTC](https://forum.ansible.com/t/accessing-other-hosts-facts-works-in-debug-task-but-not-anywhere-else/6098/5 "2024-05-31T13:40:08Z")

</div>

you also want `delegate_facts: true` so each host gets the facts for itself instead of continually overwriting the facts for the `inventory_hostname`

---

<div class="post-metadata">

**Author:** ![raspbeguy](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/raspbeguy/32/3623_2.png) [@raspbeguy](https://forum.ansible.com/u/raspbeguy)\
**Post date:** [May 31, 2024, 2:19pm UTC](https://forum.ansible.com/t/accessing-other-hosts-facts-works-in-debug-task-but-not-anywhere-else/6098/6 "2024-05-31T14:19:52Z")

</div>

@bcoca @chris that works, thanks ! I had to add `delegate_facts: true` for it to work.

However, it means that each host has to initiate fact gathering about every other hosts targeted by the playbook. This makes a complexity of n^2, which is kind of problematic…

for instance let’s say my inventory is like this:

```ini
[cluster_a]
host-a-1
host-a-2
host-a-3

[cluster_a:vars]
cluster_name=cluster_a

[cluster_b]
host-b-1
host-b-2
host-b-3

[cluster_b:vars]
cluster_name=cluster_b

```

The group var `cluster_name` is here to let the hosts know what ansible group represent their cluster.

Is there a way to limit fact gathering for each host to the hosts that are in the same cluster? In the example I wish that `host-a-1` gathers facts only for the 3 hosts in its cluster, and not the 6 total hosts when I run the playbook without limit.

---

<div class="post-metadata">

**Author:** ![chris](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/chris/32/293_2.png) [@chris](https://forum.ansible.com/u/chris)\
**Post date:** [May 31, 2024, 2:33pm UTC](https://forum.ansible.com/t/accessing-other-hosts-facts-works-in-debug-task-but-not-anywhere-else/6098/7 "2024-05-31T14:33:51Z")

</div>

Can you loop on the `cluster_name`? For example:

```yaml
- name: Gather facts for all hosts
  ansible.builtin.gather_facts:
  delegate_to: "{{ host }}"
  delegate_facts: true
  loop: "{{ groups['cluster_name'] }}"
  loop_control:
    loop_var: host

```

The [example in the documentation](https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_delegation.html#delegating-facts) appears to have the answer.

---

<div class="post-metadata">

**Author:** ![raspbeguy](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/raspbeguy/32/3623_2.png) [@raspbeguy](https://forum.ansible.com/u/raspbeguy)\
**Post date:** [May 31, 2024, 2:49pm UTC](https://forum.ansible.com/t/accessing-other-hosts-facts-works-in-debug-task-but-not-anywhere-else/6098/8 "2024-05-31T14:49:42Z")

</div>

This is already what I have.  
Actually I’m not sure, because for now I have only one cluster, but I think the loop though `groups[cluster_name]` will just tell each hosts in group `cluster_name` to gather facts about all hosts in the inventory, it won’t limit the taget of the gathering.

Also I have no idea what will happen when there will be more than one cluster, so with multiple values of `cluster_name`. Will there be as many loops as there are `cluster_name` values?

I’ll setup a second test cluster next week to find out.

---

<div class="post-metadata">

**Author:** ![bcoca](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bcoca/32/9269_2.png) [@bcoca](https://forum.ansible.com/u/bcoca)\
**Post date:** [May 31, 2024, 2:52pm UTC](https://forum.ansible.com/t/accessing-other-hosts-facts-works-in-debug-task-but-not-anywhere-else/6098/9 "2024-05-31T14:52:37Z")

</div>

simpler, create a 2nd play that runs first that just gathers facts on those hosts

---

<div class="post-metadata">

**Author:** ![bcoca](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/bcoca/32/9269_2.png) [@bcoca](https://forum.ansible.com/u/bcoca)\
**Post date:** [May 31, 2024, 3:07pm UTC](https://forum.ansible.com/t/accessing-other-hosts-facts-works-in-debug-task-but-not-anywhere-else/6098/10 "2024-05-31T15:07:25Z")

</div>

You can also `run_once: true` to avoid running the task per host, if you cannot use a 2nd play
