Creating an Ansible Inventory file using Jinja templating

While there are lots of tools in Ansible for generating an inventory file dynamically, in a system like this, you might want to be able to perform additional operations against the same cluster. For example, once the cluster has been running for a few months, you might want to do a Yum update. Eventually, you want to de-provision. Thus, having a remote record of what machines make up a particular cluster can be very useful. Dynamic inventories can be OK, but often it takes time to regenerate the inventory, and that may slow down an already long process, especially during iterated development.

So, I like to generate inventory files. These are fairly simple files, but they are not one of the supported file types in Ansible. Ansible does support ini files, but the inventory files have maybe lines that are not in key=value format.

Instead, I use Jinja formatting to generate inventory files, and they are pretty simple to work with.

UPDATE: I jumped the gun on the inventory file I was generating. The template and completed inventory have been corrected.

To create the set of hosts, I use the OpenStack server (os_server) task, like this:

- name: create servers
    cloud: "{{ cloudname }}"
    state: present
    name: "{{ item }}.{{ clustername }}"
    image: rhel-guest-image-7.4-0
    key_name: ayoung-pubkey
    timeout: 200
    flavor: 2
      - "{{ securitygroupname }}"
      -  net-id:  "{{ }}"
         net-name: "{{ netname }}_network" 
      hostname: "{{ netname }}"
  with_items: "{{ cluster_hosts }}"
  register: osservers
- file:
    path: "{{ config_dir }}"
    state: directory
    mode: 0755
- file:
    path: "{{ config_dir }}/deployments"
    state: directory
    mode: 0755
- file:
    path: "{{ cluster_dir }}"
    state: directory
    mode: 0755
- template:
    src: inventory.ini.j2
    dest: "{{ cluster_dir }}/inventory.ini"
    force: yes
    backup: yes

A nice thing about this task is, whether it is creating new server or not, it produces the same output, which is a json object that has the server data in an array.

The following template is my current fragment.

{% for item in osservers.results %}
{{ item.server.interface_ip }}
{% endfor %}
{% for item in osservers.results %}
[{{ }}]
{{ item.server.interface_ip  }}
{% endfor %}
{% for item in osservers.results %}
{% if'idm')  %}
{{ item.server.interface_ip  }}
{% endif %}
{% endfor %}
ipa_server_password={{ ipa_server_password }}
ipa_domain={{ clustername }}
deployment_dir={{ cluster_dir }}
ipa_realm={{ clustername|upper }}
ipa_admin_user_password={{  ipa_admin_password }}
ipa_forwarder={{ ipa_forwarder }}
lab_nameserver1={{ lab_nameserver1 }}
lab_nameserver2={{ lab_nameserver2 }}

I keep the variable definitions in a separate file. This produces an inventory file that looks like this:


My next step is to create a host group for all of the nodes (node0 node1) based on a shared attribute. I probably will do that by converting the list of hosts to a dictionary keyed by hostname, and have the name of the groups as the value.

Leave a Reply

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