While Red Hat® Ansible Automation Platform (AAP)® can certainly handle your Day 1 cloud native provisioning tasks end to end, sometimes you just want Terraform® to hand off a server it just built to AAP, maybe to do something like register the host in an inventory and then run an AAP job template, without bouncing between tools.
Two methods are available:
- The pre-AAP 2.5 method:
null_resource
+local-exec
+ AAP REST API calls (works anywhere). - The new official Red Hat provider method: the
ansible/aap
provider.
1. The pre-AAP 2.5 Method: local-exec
+ API Calls
When you’re running AAP prior to 2.5 and you can’t (or simply don’t want to) use a provider (e.g., in an environment with no extra dependencies) you can make raw API calls from Terraform using the tried-and-true null_resource
+ local-exec
pattern.
Classic example:
# main.tf
variable "aap_url" {}
variable "aap_token" {}
variable "inventory_id" {}
variable "new_host_name" {}
variable "job_template_id" {}
resource "null_resource" "aap_add_host" {
provisioner "local-exec" {
command = <<EOT
curl -s -X POST \
-H "Authorization: Bearer ${var.aap_token}" \
-H "Content-Type: application/json" \
-d '{"name": "${var.new_host_name}"}' \
"${var.aap_url}/api/v2/inventories/${var.inventory_id}/hosts/"
EOT
}
}
resource "null_resource" "aap_launch_job" {
provisioner "local-exec" {
command = <<EOT
curl -s -X POST \
-H "Authorization: Bearer ${var.aap_token}" \
-H "Content-Type: application/json" \
"${var.aap_url}/api/v2/job_templates/${var.job_template_id}/launch/"
EOT
}
depends_on = [null_resource.aap_add_host]
}
- Works with any Terraform install
- No provider install needed
- No stateful tracking of job runs
2. The New Official Provider Method: ansible/aap
Red Hat’s new official ansible/aap
provider for Terraform Enterprise brings stateful, typed resources for AAP objects and jobs, and it works with the default terraform
program as well.
Provider block
# provider block
terraform {
required_providers {
aap = {
source = "ansible/aap"
version = "1.3.0-prerelease2" # or newer
}
}
}
provider "aap" {
host = "https://<AAP_IP_OR_FQDN>"
username = "admin"
password = "<PASSWORD>"
# export AAP_INSECURE_SKIP_VERIFY=true to bypass TLS checks (dev only)
}
Full example: create inventory → add host/group → launch job
Note: this .tf file assumes you are running on a Mac Silicon-based macOS and is adapted from https://registry.terraform.io/providers/ansible/aap/latest/docs
# main.tf
# This example creates an inventory named `My new inventory`
# and adds a host `tf_host` and a group `tf_group` to it,
# and then launches a job based on the "Demo Job Template"
# in the "Default" organization using the inventory created.
#
terraform {
required_providers {
aap = {
source = "ansible/aap"
version = "1.3.0-prerelease2"
}
}
}
provider "aap" {
host = "https://<AAP_IP_OR_FQDN>"
username = "admin"
password = "<PASSWORD>"
}
resource "aap_inventory" "my_inventory" {
name = "My new inventory"
description = "A new inventory for testing"
organization = 1
variables = jsonencode(
{
"foo" : "bar"
}
)
}
resource "aap_group" "my_group" {
inventory_id = aap_inventory.my_inventory.id
name = "tf_group"
variables = jsonencode(
{
"foo" : "bar"
}
)
}
resource "aap_host" "my_host" {
inventory_id = aap_inventory.my_inventory.id
name = "tf_host"
variables = jsonencode(
{
"foo" : "bar"
}
)
groups = [aap_group.my_group.id]
}
data "aap_job_template" "demo_job_template" {
name = "Demo Job Template"
organization_name = "Default"
}
# In order for passing the inventory id to the job template execution, the Inventory on the job template needs to be set to "prompt on launch"
resource "aap_job" "my_job" {
inventory_id = aap_inventory.my_inventory.id
job_template_id = data.aap_job_template.demo_job_template.id
# This resource creation needs to wait for the host and group to be created in the inventory
depends_on = [
aap_host.my_host,
aap_group.my_group
]
}
Platform Notes
- Apple Silicon: Use
ansible/aap >= v1.3.0-prerelease2
to run locally. Older versions lacked darwin_arm64 builds. - HCP Terraform / Terraform Enterprise: Runs provider on Linux/amd64, so no local platform issues.
- TLS with self-signed certs:
- Dev-only:
export AAP_INSECURE_SKIP_VERIFY=true
before running Terraform. - Better: fix SANs or trust your internal CA.
- Dev-only:
In order to successfully test using the example above, you’ll need to modify the Demo Job Template which ships with AAP.
Edit Job Template: Inventory: click “Prompt on launch”.

Steps to test (assumes you have a running AAP controller to target, that you’ve defined a real managed host, with valid Machine credentials attached to your Demo Job Template):
# steps to run in dev-only:
export AAP_INSECURE_SKIP_VERIFY=true
terraform init -upgrade
# vi main.tf # to paste your .tf file
terraform validate
terraform plan
terraform apply
Successful results:

And upon success, you should also see a new inventory in AAP:


Wrapping Up
Terraform and AAP each shine in their own rights, but they’re often at their best when combined. When you are looking for Hashicorp’s approach to state management of your cloud native resources, Terraform can lay down cloud infrastructure for you on Day 1, while AAP handles all of your configuration and orchestration needs starting Day 2. And the hand-off between them can be as simple or as sophisticated as your infrastructure as code workflows may demand. Whether you start with a lightweight local-exec
hook, or adopt the official provider for full state tracking, the end result is a cleaner and more connected automation pipeline than ever.
If you’re curious about applying more cloud native patterns like this in your own environment, Red Hat Premier Partner Level Up is here for you: arc@levelupla.io.