This post was originally published in June 2021 and was updated in February 2025.

Creating and maintaining Ansible inventory files is essential, but manually handling them for large or dynamic infrastructure created by tools like Terraform can be complex and error-prone. While cloud provider plugins exist, this post demonstrates a powerful alternative: how to generate Ansible inventory files directly using Terraform itself.

There are some plugins available to automatically generate inventory files by interacting with most cloud providers’ APIs. We’ll focus on leveraging Terraform’s built-in capabilities to automate Ansible inventory creation, ensuring your inventory always reflects your provisioned infrastructure.

To illustrate this, we will generate an Ansible inventory file to deploy a MongoDB sharded cluster on the Google Cloud Platform.

Defining the Target Ansible Inventory Structure

The format of the inventory file is closely related to the actual Ansible code that is used to deploy the software. The structure we need is defined as follows:

We have to specify groups for each shard’s replicaset (shardN), as well as the config servers (cfg) and mongos routers (mongos).

The mongodb_primary tag is used to designate a primary server by giving it higher priority in the replicaset configuration.

Now that we know the structure we need, let’s start by provisioning our hardware resources with Terraform.

Step 1: Provisioning Resources with Terraform (GCP Example)

Here is an example of a Terraform script to generate some instances for the shards. The Terraform count directive is used to create many copies of a given resource, so we define it dynamically.

The above code shuffles the instances through the available zones within a region for high availability. As you can see, there are some expressions used to generate the name and the labels. I will get to this shortly. We can use similar scripts for creating the instances for the config servers and the mongos nodes.

This is an example of the variables file:

Step 2: Using Terraform Labels for Inventory Metadata

We need an easy way to identify our resources to work with them effectively. One way is to define labels on our Terraform code that is used to create the instances. We could also use instance tagging instead.

For the shards, the key part is that we need to generate a group for each shard dynamically, depending on how many shards we are provisioning. We need some extra information:

  • the group names (i.e. shard0, shard1) for each host
  • which member within a group we are working with

We define two labels for the purpose of iterating through the resources:

For the ansible-group, the variable shardsvr_replicas defines how many members each shard’s replica set has (e.g. 3). So for 2 shards, the expression above gives us the following output:

These values will be useful for matching each host with the corresponding group.

Now let’s see how to generate the list of servers per group. For the ansible-index, the expression gives us the following output:

For mongos and config servers, it is easier:

So with the above, we should have every piece of information we need.

Generating the Inventory File with local_file

Terraform provides the local_file resource to generate a file. We will use this to render our inventory file, based on the contents of the inventory.tmpl template.

We have to pass the values we need as arguments to the template, as it is not possible to reference outside variables from within it. In addition to the counters we had defined, we need the actual hostnames and the total number of shards. This is what it looks like:

The output will be a file called inventory, stored on the machine where we are running Terraform.

Step 4: Using templatefile to Format the Ansible Inventory

On the template, we need to loop through the different groups and print the information we have in the proper format.

To figure out whether to print the mongodb_primary attribute, we test the loop index for the first value and print the empty string otherwise. For the actual shards, we can generate the group name easily using our previously defined variable, and check if a host should be included in the group.

Anything between %{} contains a directive, while the ${} are used to substitute the arguments we fed the template. The ~ is used to remove the extra newlines.

Final Words

Generating your Ansible inventory directly with Terraform, using resources like local_file and the templatefile function, provides a powerful way to automate infrastructure provisioning and configuration management end-to-end. This method ensures consistency between your Terraform-managed resources and your Ansible targets without relying on external plugins. While crafting the template requires care, the result is a fully automated inventory solution directly integrated with your IaC workflow.

Ready to leave MongoDB, Inc. behind? Percona is the cost-effective, enterprise-grade alternative businesses trust.

MongoDB Alternative

FAQs: Generating Ansible Inventory with Terraform

Q1: Why generate an Ansible inventory with Terraform instead of using dynamic inventory plugins?
A: Generating inventory directly from Terraform ensures perfect consistency with the infrastructure Terraform manages, avoids external dependencies or API calls required by plugins, and keeps the entire inventory logic within your IaC code. It can be simpler for certain workflows.

Q2: What Terraform resources are used to generate the inventory file?
A: The primary resources are local_file (to write the file to the local machine running Terraform) and the templatefile() function (to process a template file with data from your Terraform resources). Resource labels or tags are often used to store metadata needed for grouping hosts in the inventory.

Q3: Can this method handle dynamically created resources (e.g., using count or for_each)?
A: Yes, this method excels with dynamic resources. The examples use count and Terraform expressions within the template file to iterate over dynamically created instances and assign them to the correct groups based on their attributes or labels.

Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments