Facts and limit

Use-case

It’s a common practice to loop over a group of hosts to retrieve some data (like IP address) and concatenate them in a variable that you then inject into a configuration file: you’ve probably already done this to configure a cluster.

For example, you can build a yaml configuration file with:

servers:
{% for s in groups['cluster_server'] %}
  - {{ hostvars[s]['ansible_default_ivp4']['address'] }}
{% endfor %}

Problem

Using the magic hostvars variable implies that facts has been gathered on all hosts.

But the --limit option will **only** gather facts on the listed hosts.

This could lead to some undefined variable errors or, even worse, you could end with strange values in your configuration files.

For example:

servers: [AnsibleUndefined, AnsibleUndefined, AnsibleUndefined]

Solution

The solution is to force the gathering of the facts of all the hosts you need:

- name: update facts
  setup:
  delegate_to: "{{ item }}"
  delegate_facts: True
  when: hostvars[item]['ansible_default_ivp4']['address'] is not defined # to speed up the process
  loop: "{{ groups['cluster_server'] }}"
  tags:
    - always