Terraform Runner

What is the Terraform Runner Driver?

The Terraform Runner Driver is a virtual driver that wraps the Terraform Driver to provide an easy, standardized and re-usable way to run the Terraform Runner in a target cluster .

The Terraform Runner Driver supports only AKS, EKS, and GKE clusters as a target cluster for the execution of the Terraform Runner. It means that it can be used in combination with a cluster_type of aks, eks, or gke.

To make the Terraform Runner run on a generic cluster, please keep on using the Terraform Driver and specify a runner object with a cluster_type of k8s.

Why use the Terraform Runner Driver?

Using the Terraform Runner Driver should ensure:

  • Reusability: You may want to use a dedicated Terraform Runner cluster to provision infrastructure via Terraform. By separating out the runner configuration, it can be injected into any number Resource Definitions that should use that specific cluster to run the Terraform Runner.
  • Separation of concerns: As the configuration details are all in the config Resource Definition as shown in the example below, the Terraform Resource Definition is completely oriented to provide the Terraform specification.

How it works

The Terraform Runner Driver wraps the Terraform Driver and injects the Terraform Runner configuration referencing a config Resource Definition. It applies the config pattern :

  • The Terraform Runner Driver injects the runner_mode custom-kubernetes.
  • A config Resource Definition should provide the runner configuration. It should:
    • Match class default and resource id tf-runner (and a specific environment type)
    • Provide the cluster configuration in an output named runner that should contain the properties documented in the runner object section of the Terraform Driver. The account to create and handle the Kubernetes resources needed by the Terraform Runner in the cluster needs to be specified.
    • Have a secret template output named agent_url that should be a reference to an Agent Resource , if the cluster is accessible only via Humanitec Agent , or an empty string.
  • Any Resource Definition built on the Terraform Runner Driver would only care about the Terraform specific inputs (e.g. scripts, files, source…) and it automatically depends on the config resource.

Matching different cluster configuration

By attaching the proper Matching Criteria to the config Resource Definition, a different Terraform Runner configuration can be matched per Environment Type, so that the Terraform Runner is executed in the proper cluster.

Using Terraform Backends

By default, this Driver injects the configuration of a Kubernetes Terraform Backend that:

  • Creates Kubernetes secrets in the Runner namespace.
  • Uses the Resource’s Globally Unique Id as secret_suffix via the context.res.guresid placeholder, to prevent any overlapping among resources.

The Kubernetes service account used by the Runner in the target namespace must be created and configured to have the permissions needed by the Runner to complete its execution.

Kubernetes Service Account
apiVersion: v1
kind: ServiceAccount
metadata:
  name: humanitec-tf-runner
  namespace: humanitec-terraform
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: humanitec-terraform
  name: humanitec-tf-runner
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["create", "get", "delete", "list", "update", "deletecollection"]
# Only needed if the chosen Terraform Backend is kubernetes
- apiGroups: ["coordination.k8s.io"]
  resources: ["leases"]
  verbs: ["create", "get", "list", "update", "watch"]  
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: humanitec-tf-runner
  namespace: humanitec-terraform
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: humanitec-tf-runner
subjects:
- kind: ServiceAccount
  name: humanitec-tf-runner
  namespace: humanitec-terraform

If you want to specify a different backend:

  • Set the boolean input value use_default_backend to false
  • Configure a different backend in your Terraform code.

See our backends example for ways to handle backends.

Terraform Runner Driver reference

This Driver has the same inputs as the Terraform Driver , with the exception that:

  • No inputs for configuring the Terraform Runner are allowed or should be specified here.
  • A non-secret input value use_default_backend needs to be supplied and set to false in case of a backend that is not the default one should be used to store the Resource state.

Examples

In addition to the Terraform Driver examples page, we provide here an example that consists of:

  • A config Resource Definition. It matches a res_id of tf_runner and produces a runner objects as its output.
  • A Terraform Runner Resource Definition that performs provisioning of an S3 bucket via the execution of Terraform code stored in a private Github repository. The Terraform code will be executed in the cluster specified by the config Resource Definition. Note that no reference to the config Resource is required.

Set the following environment variables for the CLI and API commands:

Variable Example Description
HUMANITEC_TOKEN my-token The authentication token for accessing the Humanitec API
HUMANITEC_ORG my-org-id The unique identifier for the Humanitec Organization

Use the command below for the interface of your choice.

Config Resource Definition

  1. Create a file defining the config Resource Definition you want to create to define the cluster where the Terraform Runner should run:
cat << "EOF" > config-tf-runner.yaml
apiVersion: entity.humanitec.io/v1b1
kind: Definition
metadata:
  id: config-tf-runner
entity:
  name: Config For TF Runner
  type: config
  driver_type: humanitec/template
  driver_inputs:
    values:
      templates:
        outputs:
          runner:
            account: myOrg/myAccount
            cluster:
              loadbalancer: 10.10.10.10
              name: my-cluster
              project_id: my-gcp-project
              zone: cluster-zone
            cluster_type: gke
            namespace: humanitec-terraform
            service_account: humanitec-tf-runner
        secrets: |
          agent_url: {{ .driver.secrets.agent_url }}
    secrets:
      agent_url: ${resources.agent.outputs.url}
  criteria:
  - env_type: development
    res_id: tf-runner
EOF
  1. Use the humctl create command to create the Resource Definition in the Organization defined by your configured context:
humctl create -f config-tf-runner.yaml
rm config-tf-runner.yaml

curl https://api.humanitec.io/orgs/${HUMANITEC_ORG}/resources/defs \
  -X POST \
  -H "Authorization: Bearer ${HUMANITEC_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '
{
  "id": "config-tf-runner",
  "name": "Config For TF Runner",
  "type": "config",
  "criteria": [
    {
      "env_type": "development",
      "res_id": "tf-runner"
    }
  ],
  "driver_type": "humanitec/template",
  "driver_inputs": {
    "values": {
      "templates": {
        "outputs": "runner:\n  account: myOrg/myAccount\n  cluster:\n    loadbalancer: 10.10.10.10\n    name: my-cluster\n    project_id: my-gcp-project\n    zone: cluster-zone\n  cluster_type: gke\n  namespace: humanitec-terraform\n  service_account: humanitec-tf-runner\n",
        "secrets": {
          "agent_url": "{{ .driver.secrets.agent_url }}"
        }
      }
    },
    "secrets": {
      "agent_url": "${resources.agent.outputs.url}"
    }
  }
}'

Terraform Runner Resource Definition

  1. Create a file defining the terraform-runner Resource Definition you want to create to define the Terraform code to execute:
cat << "EOF" > s3-tf.yaml
apiVersion: entity.humanitec.io/v1b1
kind: Definition
metadata:
  id: my-s3-bucket
entity:
  name: S3 Bucket
  type: s3
  driver_type: humanitec/terraform-runner
  driver_inputs:
    values:
      source:
        path: s3/terraform
        rev: refs/heads/main
        url: https://my-domain.com/my-org/my-repo.git
        username: my-git-handler
      variables:
        bucket_name: my-bucket
    secret_refs:
      source:
        password:
          store: my-store
          ref: path/to/git/password
      ....
  criteria:
  - env_type: development
EOF
  1. Use the humctl create command to create the Resource Definition in the Organization defined by your configured context:
humctl create -f s3-tf.yaml
rm s3-tf.yaml

curl https://api.humanitec.io/orgs/${HUMANITEC_ORG}/resources/defs \
  -X POST \
  -H "Authorization: Bearer ${HUMANITEC_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '
{
  "id": "my-s3-bucket",
  "name": "S3 Bucket",
  "type": "s3",
  "criteria": [
    {
      "env_type": "development"
    }
  ],
  "driver_type": "humanitec/terraform-runner",
  "driver_inputs": {
    "values": {
      "source": {
        "path": "s3/terraform",
        "rev": "refs/heads/main",
        "url": "https://my-domain.com/my-org/my-repo.git",
        "username": "my-git-handler"
      "variables":
        "bucket_name": "my-bucket",       
      }
    },
    "secret_refs": {
      "source":{
        "password": {
          "store": "my-store",
          "ref": "path/to/git/password"
        },
        ...
      }
    }
  }
}'
Top