terraform_http plugin

This Ansible inventory plugin templates inventory from Terraform state stored in HTTP Terraform state backend.

It is used for populating Ansible inventory with VMs created with the machine Terraform module when using HTTP Terraform state backend with GitLab-managed Terraform state.

There is a sister terraform_local Ansible inventory plugin doing the same thing for local Terraform state.

Options

  • hosts - List of hosts to add to the Ansible inventory. Required.

Each hosts entry contains the following options. All values accept template strings, which are rendered with Terraform outputs as context.

  • ansible_host - IP of the host. Required.
  • ansible_port - Port to use for SSH connection. Required.
  • ansible_group - Group to add the host to. Required.
  • vars - Dictionary of additional host vars to add.

Terraform Configuration

This inventory plugin works with Terraform HTTP state backend using GitLab-managed Terraform state. Make sure to configure Terraform to use the HTTP state backend:

# Inside versions.tf
terraform {
  # ...
  backend "http" {}
}

See GitLab’s guide for instructions on configuring the Terraform HTTP state backend. It is recommended to use the .env example below for configuring your local machine to use GitLab-managed Terraform state.

GitLab Authentication

This plugin uses TF_HTTP_ADDRESS, TF_HTTP_USERNAME and TF_HTTP_PASSWORD environment variables in the same way Terraform does.

The GitLab token for TF_HTTP_PASSWORD requires full API access, just read_repository and write_repository are not enough.

If you configure your Terraform state backend through environment variables, this plugin works without any configuration.

During Development

It is recommended to use a .env file to configure both Terraform and terraform_http Ansible inventory plugin. For example, if our GitLab instance is git.example.com and the project ID is 57, we may use the following .env file:

# Inside .env
# Authentication details for GitLab managed Terraform state.
export GITLAB_USER='Lior'
export GITLAB_TOKEN='glpat-xxxxxxxxxxxxxxxxxxxx'

# Immitating CI environment variables.
export CI_PROJECT_ID='57'
export CI_API_V4_URL='https://git.example.com/api/v4'
export CI_ENVIRONMENT_NAME='dev'

# Terraform state configuration.
export TF_HTTP_ADDRESS="${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${CI_ENVIRONMENT_NAME}"
export TF_HTTP_LOCK_ADDRESS="${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${CI_ENVIRONMENT_NAME}/lock"
export TF_HTTP_LOCK_METHOD='POST'
export TF_HTTP_UNLOCK_ADDRESS="${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${CI_ENVIRONMENT_NAME}/lock"
export TF_HTTP_UNLOCK_METHOD='DELETE'
export TF_HTTP_USERNAME="${GITLAB_USER}"
export TF_HTTP_PASSWORD="${GITLAB_TOKEN}"

In GitLab CI

The TF_* environment variables can be reused when configuring GitLab CI jobs provisioning VMs for a seamless experience:

# Inside .gitlab-ci.yml
variables:
  TF_HTTP_ADDRESS: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${CI_ENVIRONMENT_NAME}
  TF_HTTP_LOCK_ADDRESS: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${CI_ENVIRONMENT_NAME}/lock
  TF_HTTP_LOCK_METHOD: POST
  TF_HTTP_UNLOCK_ADDRESS: ${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/terraform/state/${CI_ENVIRONMENT_NAME}/lock
  TF_HTTP_UNLOCK_METHOD: DELETE
  TF_HTTP_USERNAME: gitlab-ci-token
  TF_HTTP_PASSWORD: ${CI_JOB_TOKEN}

With these environment variables set, you can both provision VMs with Terraform and configure them with Ansible.

Example

Assuming you have environment variables configured as described above, and GitLab Terraform state contains the machine_ssh_ip and machine_ssh_user outputs. This inventory config reads the GitLab Terraform state and adds a host to the production group:

---
plugin: lkummer.homelab.terraform_http
hosts:
  - ansible_host: '{{ machine_ssh_ip }}'
    ansible_group: production
    ansible_port: '2222'
    vars:
      ansible_user: '{{ machine_ssh_user }}'

Note it is designed to integrate with outputs from machine Terraform modules.