Terraform Ansible Inventory
About
A high-performance, zero-dependency Go command-line tool for building complete
Ansible inventories from Terraform state generated by the ansible/ansible
provider.
terraform-ansible-inventory
is a small Go CLI for converting Terraform state
into complete Ansible inventories. The tool was created to work with the
ansible/ansible
Terraform provider which stores hosts, groups and variables in
the state file. RedHat also provides a dynamic inventory plugin that reads
Terraform state, but it cannot handle child modules and therefore misses large
parts of real-world configurations. This CLI parses the state directly and
fully supports nested modules so you can build inventories reliably.
To generate usable state data you must manage your inventory with the
ansible/ansible
provider. Once the provider has written hosts and groups into
your state file, this tool can consume it and output Ansible formatted data.
Features
- Streaming JSON parsing for huge state files without high memory use using the
jstream
library. - Multiple output formats:
yaml
,ini
, andjson
. - Understands provider resources: host variables, group hierarchy and
inventory level variables from the
ansible/ansible
provider. - Child module aware: traverses nested modules to pick up all resources.
- Built-in IP/CIDR handling so exported addresses work directly in Ansible.
- Clean CLI interface with automatic
--help
and sensible defaults. - No external runtime dependencies other than the Go binary itself.
- CI ready: sample state file and GitHub Actions workflow included.
- Filter output by host or group using
--host
and--group
flags.
Installation
Clone and build from source or grab a prebuilt binary from the releases page:
# Build from source
git clone https://github.com/HilkopterBob/terraform-ansible-inventory.git
cd terraform-ansible-inventory
go build -o terraform-ansible-inventory ./main.go
# (Optional) install globally
go install github.com/HilkopterBob/terraform-ansible-inventory@latest
Download the latest release if you prefer not to build the binary yourself.
Docker image
Two container images are published on
GitHub Container Registry. terraform-ansible-inventory
contains only the inventory binary while the -tf
tag additionally installs the
latest Terraform release. Use the -tf
variant when accessing remote state.
# minimal image
docker run --rm ghcr.io/HilkopterBob/terraform-ansible-inventory:latest --help
# with Terraform installed
docker run --rm ghcr.io/HilkopterBob/terraform-ansible-inventory:latest-tf terraform version
In GitLab CI you must override the image entrypoint so the pipeline script can run:
image:
name: ghcr.io/HilkopterBob/terraform-ansible-inventory:latest
entrypoint: [""]
generate-inventory:
script:
- terraform-ansible-inventory --input tf.json --format yaml > inventory.yaml
Usage
Run the executable with --help
to see all options:
terraform-ansible-inventory --help
Common examples assuming your state file is state.json
:
# YAML inventory
terraform-ansible-inventory -i state.json -f yaml > inventory.yml
# INI inventory
terraform-ansible-inventory -i state.json -f ini > inventory.ini
# JSON machine readable form
terraform-ansible-inventory -i state.json -f json > inventory.json
# Native Ansible inventory
terraform-ansible-inventory -i state.json -f ansible
Example HCL and Generated Inventory
Below is a small Terraform snippet demonstrating how hosts and groups are
defined with the ansible/ansible
provider:
resource "ansible_inventory" "default" {
variables = {
env = "prod"
}
}
resource "ansible_group" "web" {
name = "web"
variables = {
tier = "frontend"
}
}
resource "ansible_host" "test1" {
name = "test1"
groups = [ansible_group.web.name]
variables = {
ip = "192.168.1.10"
os = "linux"
}
}
Running the CLI against the state generated from this configuration yields:
YAML
all:
vars:
env: prod
children:
web:
hosts:
test1:
ansible_host: 192.168.1.10
os: linux
vars:
tier: frontend
INI
[all]
[all:vars]
env=prod
[web]
test1 ansible_host=192.168.1.10 os=linux
[web:vars]
tier=frontend
JSON
{
"Hosts": {
"test1": {
"Name": "test1",
"Variables": {
"ip": "192.168.1.10",
"os": "linux"
},
"Groups": ["web"],
"Enabled": true,
"Metadata": {}
}
},
"Groups": {
"web": {
"Name": "web",
"Variables": {"tier": "frontend"},
"Children": null,
"Hosts": ["test1"],
"Parents": null
}
},
"Vars": {"env": "prod"}
}
You can restrict output to specific hosts or groups using the --host
and
--group
flags. Multiple values are allowed.
Contributing
- Fork & clone the repo
- Create a feature branch
git checkout -b feature/myfeature
- Add tests under
internal/*_test.go
- Ensure all tests pass
- Submit a PR
License
Apache-2.0 © Nick von Podewils