57

Let's say I have a host that collects some data and
it's in a group [collectors]. I also have hosts in-group [reporters].
So, I want to set a variable on reporters from groups['collectors'][0] IP address. But the playbook for setting up reporters doesn't run on [collectors] group so facts for this host are not collected. Is there a way not to hardcode the IP address?

1 Answer 1

105

You can access pretty much any inventory facts/variables by doing something like this:

{{ hostvars['foo.example.com']['ansible_eth0']['ipv4']['address'] }}

or, if you want to do it via an index into a group:

{{ hostvars[groups['collectors'][0]]['ansible_eth0']['ipv4']['address'] }}

The big trick is that you need to collect the facts for all the hosts/groups you're interested in. So you would want to modify your playbook that runs against the reporters group to include a no-op (dummy) task that is applied to the collectors group. That will cause Ansible to collect facts about the collectors hosts so that they can be accessed from the reporters group. So you might want to add something like this to the top of your reporters playbook:

- hosts: collectors
  name: Gather facts from collectors
  tasks: [ ]

The empty brackets basically mean that no tasks will be executed, but this will still force Ansible to gather facts about the collectors so that you can then reference them in the tasks that you run against your reporters.

Edit #1

It occurred to me that I should also mention that as of version 1.8 of Ansible, there is a fact-caching feature that is now available. Fact caching relies on a redis server to store facts between playbook runs. With it enabled, one playbook can reference facts that were obtained by another playbook that was run previously. The example the Ansible documentation gives:

Imagine, for instance, a very large infrastructure with thousands of hosts. Fact caching could be configured to run nightly, but configuration of a small set of servers could run ad-hoc or periodically throughout the day. With fact-caching enabled, it would not be necessary to “hit” all servers to reference variables and information about them.

7
  • 3
    Is there a way to set associative index as a variable? in example ansible localhost --extra-vars "metamorphosis_ip=172.16.3.73" -a "echo {{ hostvars[{{ metamorphosis_ip }}]['inv_domain'] }} "
    – corretge
    May 2, 2016 at 16:26
  • To add to the answer above above make sure that you reference the Ansible FAQ here: docs.ansible.com/ansible/faq.html which explains things in detail, like looping over a group of hosts or setting a variable to get an specific host in a group.
    – eco
    Jun 2, 2016 at 5:22
  • Thank you for the idea of fetching facts from a node with an empty task list.
    – pedz
    Aug 24, 2018 at 22:18
  • @corretge Yes, you can do this by simply referring to the variable directly without quotes: {{ hostvars[metamorphosis_ip]['inv_domain'] }}
    – DaVince
    Aug 5, 2020 at 15:53
  • 3
    It seems that the names of the facts have changed somewhat since this was posted. To get this work I had to change this to {{ hostvars[groups['collectors'][0]]['ansible_default_ipv4']['address'] }}
    – Bram
    Jan 5, 2021 at 13:01

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .