Previously if you wanted to use a dynamic Ansible inventory from resources created by Terraform you had to use a Python script to create this inventory from Terraform’s output.
Now the Ansible provider can be used to create an inventory with Terraform configuration without writing any scripts.
Terraform Configuration
1. Install Ansible Provider
The Terraform Ansible Provider is required to start defining the inventory from Terraform resources.
1terraform {
2 required_providers {
3 ansible = {
4 source = "ansible/ansible"
5 version = "1.2.0"
6 }
7 }
8}
Then run terraform init
.
2. Define Inventory Hosts and Groups
Define ansible_host
resources that will be part of the inventory:
1# EC2 instance.
2resource "aws_instance" "web1" {/* ... */}
3
4# Inventory host resource.
5resource "ansible_host" "web1" {
6 name = "web1"
7 groups = ["aws"] # Groups this host is part of.
8
9 variables = {
10 # Connection vars.
11 ansible_user = "admin" # Default user depends on the OS.
12 ansible_host = aws_instance.web1.public_ip
13
14 # Custom vars that we might use in roles/tasks.
15 hostname = "web1"
16 fqdn = "web1.example.com"
17 }
18}
Define groups if needed using the ansible_group
resource:
1resource "ansible_group" "web" {
2 name = "web"
3 children = ["aws"]
4
5 # Group variables that will apply to the children hosts.
6 variables = {
7 ansible_ssh_private_key_file = "~/.ssh/id_rsa"
8 }
9}
This is equivalent to this definition in a yaml inventory file:
1aws:
2 hosts:
3 web1:
4 ansible_user: admin
5 ansible_host: 1.2.3.4
6 hostname: web1
7 fqdn: web1.example.com
8
9web:
10 children:
11 aws:
12 vars:
13 ansible_ssh_private_key_file: ~/.ssh/id_rsa
The variables
definition is a map of string, so jsonencode()
must be used for list or map values.
1resource "ansible_host" "web1" {
2 // ...
3 variables = {
4 // ...
5 list_var = jsonencode(["one", "two", "three"])
6
7 map_var = jsonencode({
8 country = "US"
9 region = "us-east-1"
10 })
11 }
12}
Now run terraform apply
to create the inventory resources.
Ansible Configuration
1. Install Terraform Collection
For Ansible to have access to the inventory defined in the Terraform configuration, the Terraform Collection for Ansible is required.
$ansible-galaxy collection install cloud.terraform
Or define it in a requirements.yml
file:
1---
2collections:
3 - name: cloud.terraform
4 version: 2.0.0
Then install it with:
$ansible-galaxy install -r requirements.yml
2. Create Inventory File
Create an inventory file that uses the Terraform inventory plugin:
1plugin: cloud.terraform.terraform_provider
2project_path: /path/to/terraform-project
3# Terraform binary (available in the $PATH) or full path to the binary.
4binary_path: terraform
3. Use the Inventory
To use the inventory, specify it with the -i, --inventory
option:
$ansible -i terraform.yml ...
Or define it in the ansible.cfg
file:
1[defaults]
2inventory = terraform.yml
List the Inventory
Test the setup by listing the inventory hosts with their variables:
$ansible-inventory -i terraform.yml --graph --vars
@all:
|--@ungrouped:
|--@web:
| |--@aws:
| | |--web1
| | | |--{ansible_host = 1.2.3.4}
| | | |--{ansible_ssh_private_key_file = ~/.ssh/id_rsa}
| | | |--{ansible_user = admin}
| | | |--{fqdn = web1.example.com}
| | | |--{hostname = web1}
| | | |--{list_var = ["one","two","three"]}
| | | |--{map_var = {"country":"US","region":"us-east-1"}}
| |--{ansible_ssh_private_key_file = ~/.ssh/id_rsa}
Full Demo Repository
For a full demo with a dynamic Ansible inventory from Terraform using AWS and Hetzner Cloud check out this repository: