Ansible: Use hostvars to Generate Hosts File

There are cases when you need to access variables for another host, including facts that have been gathered about that host.

The Problem

I have 5 Ansible managed hosts in my homelab that I use for testing. I want to use a template to generate the /etc/hosts file for each managed node. The content of the file that I want to end up with is below:

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

10.11.1.62 ansible2.hl.local ansible2
10.11.1.63 ansible3.hl.local ansible3
10.11.1.64 ansible4.hl.local ansible4
10.11.1.65 ansible5.hl.local ansible5
10.11.1.66 ansible6.hl.local ansible6

While I can easily retrieve facts about the host the playbook is run on, I need a way of accessing facts that have been gathered about other hosts as well.

The Solution: Magic Variables

The hostvars magic variable allows you access variables for another host, including facts that have been gathered about that host. You can access host variables at any point in a playbook.

If a server needs to use the value of a “fact” from another node, it’s easy to do so within a template templates/hosts.j2:

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

{{ hostvars['ansible2.hl.local']['ansible_default_ipv4']['address'] }} {{ hostvars['ansible2.hl.local']['ansible_fqdn'] }} {{ hostvars['ansible2.hl.local']['ansible_hostname'] }}
{{ hostvars['ansible3.hl.local']['ansible_default_ipv4']['address'] }} {{ hostvars['ansible3.hl.local']['ansible_fqdn'] }} {{ hostvars['ansible3.hl.local']['ansible_hostname'] }}
{{ hostvars['ansible4.hl.local']['ansible_default_ipv4']['address'] }} {{ hostvars['ansible4.hl.local']['ansible_fqdn'] }} {{ hostvars['ansible4.hl.local']['ansible_hostname'] }}
{{ hostvars['ansible5.hl.local']['ansible_default_ipv4']['address'] }} {{ hostvars['ansible5.hl.local']['ansible_fqdn'] }} {{ hostvars['ansible5.hl.local']['ansible_hostname'] }}
{{ hostvars['ansible6.hl.local']['ansible_default_ipv4']['address'] }} {{ hostvars['ansible6.hl.local']['ansible_fqdn'] }} {{ hostvars['ansible6.hl.local']['ansible_hostname'] }}

The playbook:

---
- name: Generate Hosts File
  hosts: all
  become: true
  gather_facts: true
  vars:
    my_file: /etc/hosts
    my_template: templates/hosts.j2
  tasks:
    - name: Create "{{ my_file }}"
      template:
        src: "{{ my_template }}"
        dest: "{{ my_file }}"
        owner: root
        group: root
        mode: "0644"

Leave a Reply

Your email address will not be published. Required fields are marked *