All documentation

Managing Ansible Inventory files with Terraform

Published July 8, 2023 Guide

The importance of effectively managing and updating Ansible inventory files has become increasingly apparent to me. This article will guide you through configuring both Ansible and Terraform to achieve the ultimate goal of managing multiple Ansible inventory files.

Community Ask: https://stackoverflow.com/questions/45489534/best-way-currently-to-create-an-ansible-inventory-from-terraform

What you will need.

  • Access to a host running Ansible
  • Access to a host running Terraform

    Ensure that the above hosts can communicate with each other.


For the purpose of this documentation, I will be using a single host running Ubuntu 22.04 with both Ansible and Terraform installed. Let's begin.

Creating Terraform Template Files:

Create a directory where Terraform will read the template files from.

  • Log into your Terraform host (which, in my case, is the same as the Ansible host).
  • Create a directory with a descriptive name:
mkdir /path/to/directory/terraformtemplatefiles

Now, you can create your Terraform template files with the .tpl extension. As an example, I'll use the template names "proxmoxhosts" and "kubehosts".

Create the template files:

touch proxmoxhosts.tpl
touch kubehosts.tpl

Make note of the path where these files reside; we will need it later.

Creating the Ansible directory:

Define a directory for the Ansible host files. This directory will be used by Terraform to create the Ansible host files.

mkdir /path/to/ansible/directory/managedhosts

Please ensure you use a valid directory and make note of the path, as we will need it later.

Adding the New Ansible Directory to the ansible.cfg File:

To instruct Ansible to look for inventory files in a directory, we need to add the path of that directory to the ansible.cfg file. Let's edit this file:

 vi /etc/ansible/ansible.cfg 

Add the following line:
inventory = /path/to/ansible/directory/managedhosts

You ansible.cfg file should look similare to this.

Save your changes. Ansible will now search for inventory files in the configured path.

Configuring the Terraform Template Files:

At this point, we should have two Terraform template files. Let's open one of them in our favorite text editor and configure it accordingly. Copy the code snippet below into one of your .tpl files.

[proxmoxhosts]
%{ for host in variablename ~}
${host.name} ansible_host=${host.default_ipv4_address} 
%{ endfor ~}

[all:vars]
ansible_python_interpreter=/usr/bin/python3

The first line represents the name of our Ansible grouped hosts.
Lines 2 to 4 define a foreach syntax that loops through a variable (which we will define later). You can replace variablename with a more descriptive name.

Configuring Your Terraform Code to Utilize the Updated Template File:

We will be using the Terraform Local_file resource & templatefile function for the following syntax.
If you define your VM's or other hosts in a separate file from your main.tf, you can loop through those created resources using terraform for expressions
In the below example, I am defining the variable variablename with the value of all resources from proxmox_vm_qemu.proxmoxvm


resource "local_file" "proxmoxhosts" {
  ## Custom Template file for proxmox ansible hosts
  content = templatefile("/path/to/directory/terraformtemplatefiles/proxmoxhosts.tpl",
  
  ## the below variablename variable equals a foreach loop of the proxmox VM's that get created. 
    {
    variablename = {for key, value in proxmox_vm_qemu.proxmoxvm: 
               key => value }
    }
  )
  filename = "/etc/ansible/managedhosts/proxmoxhosts"
}

The above terraform block can be added to your main.tf file
After a terraform apply a loop through all of the resources created will occur, and the results will be saved to variable variablename.
The Terraform template we created will then loop through this variable and define your new Ansible inventory file. the end result should be a new ansible inventory file in the directory /etc/ansible/managedhosts called proxmoxhosts for example.

lets look at our new Ansible inventory file.
cat proxmoxhosts

For example, In the Terraform template we created, we get the name server1 from the template syntax of
%{ for host in variablename ~}
${host.name}


Lets look at another example that also works for me.
In the below example, I am using a different terraform project, however, I am defining resources in the same main.tf file and using count Meta-Argument
for this reason, the variablename can equeal the resource.* value and in our terraform template file, we can loop through variablename and pick and choose our values to define our Ansible inventory file.

resource "local_file" "hosts" {
  content = templatefile("/path/to/directory/terraformtemplatefiles/kubhosts.tpl",
    {
    variablename = proxmox_vm_qemu.kube-server.*
    }
  )
  filename = "/etc/ansible/managedhosts/kubhosts"
}

The above terraform block can be used for additional terraform infrastructure management effort while still being able to dynamically managing the ansible inventory files.
A terraform apply will create a ansible inventory file called kubhosts.
the end result should be similar to the this:


Hope this helps someone out there with managing multiple Ansible inventory files via Terraform.