Run Ansible from Terraform

Prerequisites
- Terraform instalation
- Ansible instalation
- OpenStack application credentials (~/.config/openstack/clouds.yaml)
- OpenStack security group with allow ingress traffic to TCP 22 (SSH) from terraform node

main.tf

terraform {
  required_providers {
    openstack = {
      source = "terraform-provider-openstack/openstack"
    }
 
    ansible = {
      source = "ansible/ansible"
    }
  }
}
 
provider "openstack" {
  cloud = "test-application-credentials"
}
 
data "openstack_compute_keypair_v2" "keypair_1" {
  name = "test-keypair"
}
 
data "openstack_networking_network_v2" "network_1" {
  name = "test-network"
}
 
data "openstack_networking_secgroup_v2" "secgroup_1" {
  # Ensure that the security group allow ingress to TCP 22 (SSH) from terraform node
  name = "test-secgroup" 
}
 
data "openstack_networking_port_v2" "port_1" {
  device_id  = openstack_compute_instance_v2.instance_1.id
  network_id = openstack_compute_instance_v2.instance_1.network.0.uuid
}
 
# data "template_file" "user_data" {
#   template = <<EOF
# #cloud-config
# package_update: true
# packages:
#  - python3
# runcmd:
#  - cloud-init status --wait
# EOF
# }
 
resource "openstack_compute_instance_v2" "instance_1" {
  name            = "test-www1"
  image_name      = "Ubuntu 24.04"
  flavor_name     = "m1.micro"
  key_pair        = data.openstack_compute_keypair_v2.keypair_1.name
  security_groups = [data.openstack_networking_secgroup_v2.secgroup_1.id]
  # user_data       = data.template_file.user_data.rendered
 
  network {
    uuid = data.openstack_networking_network_v2.network_1.id
  }
}
 
resource "openstack_networking_floatingip_v2" "floatingip_1" {
  pool = "public"
}
 
resource "openstack_networking_floatingip_associate_v2" "instance_fip_association" {
  floating_ip = openstack_networking_floatingip_v2.floatingip_1.address
  port_id     = data.openstack_networking_port_v2.port_1.id
}
 
resource "ansible_playbook" "playbook" {
  playbook   = "test-playbook.yml"
  name       = openstack_networking_floatingip_v2.floatingip_1.address
  groups     = ["www"]
  # replayable = true
  # verbosity  = 3
 
  extra_vars = {
    ansible_user = "ubuntu"
  }
 
  depends_on = [openstack_networking_floatingip_associate_v2.instance_fip_association]
}
 
output "instance_floatingip" {
  value = openstack_networking_floatingip_v2.floatingip_1.address
}

test-playbook.yml

---
- name: Deploy webserver(s)
  hosts: www
  # remote_user: ubuntu
  gather_facts: no
  become: true
  pre_tasks:
    - name: Wait util host is reachable by SSH
      wait_for_connection:
        timeout: 300
 
    - name: Gether facts
      setup:
  tasks:
    - name: Install nginx
      apt:
        update_cache: yes
        name:
          - nginx

Deploy

terraform init
terraform apply -auto-approve

Ansible Provider
https://github.com/ansible/terraform-provider-ansible
https://registry.terraform.io/providers/ansible/ansible/latest/docs

Links
https://www.redhat.com/en/blog/providing-terraform-with-that-ansible-magic