Skip to content

How to implement a Terraform testing pipeline for shared modules

This guide shows you how to implement our Terraform testing pipeline for shared modules within the uis/devops/infra/terraform GitLab group. Please note that this process is specific to these modules and may not function as intended in other Terraform repositories.

Write your Terraform tests

Create your Terraform test files and store them either in the root of your project or, preferably, in a tests/ directory. All test files must use the .tftest.hcl file extension.

Note

For guidance on writing Terraform tests, refer to the official Terraform documentation, which provides the most comprehensive reference.

Providing variables

Add any variables to a ./tests/tests.auto.tfvars file if you want them to be automatically loaded by our standard pipeline.

Running tests locally

We use Docker to run Terraform tests locally. Start by creating a docker-compose.yml file in the root of your project with the following content:

name: <project name>-testing

services:
  test:
    image: registry.gitlab.developers.cam.ac.uk/uis/devops/infra/dockerimages/logan-terraform:<terraform version>
    entrypoint: ["bash", "-c"]
    environment:
      # This unsets the GOOGLE_APPLICATION_CREDENTIALS as it is not required but the logan-terraform images sets it.
      - GOOGLE_APPLICATION_CREDENTIALS=
      - GOOGLE_IMPERSONATE_SERVICE_ACCOUNT=terraform-deploy@<project ID>.iam.gserviceaccount.com
    volumes:
      - .:/workdir:rw
      - ~/.config/gcloud/application_default_credentials.json:/root/.config/gcloud/application_default_credentials.json:ro
    cap_drop:
      - "ALL"

To simplify running the container, we use a poethepoet task. Create a file named poe_tasks.yaml in your project root with the following contents:

tasks:
  test:
    cmd: docker compose run --rm test "terraform init && terraform test -var-file=tests/tests.auto.tfvars $0 $*" ${TEST_ARGS}
    args:
      - name: TEST_ARGS
        positional: true
        multiple: true

You can now run tests locally using:

poe test

Before doing so, ensure you're authenticated to Google Cloud using Application Default Credentials (ADC).

If you need to pass additional arguments to the test command you may need to separate them with an initial --, for example:

poe test -- --filter=tests/my-tests.tftest.hcl

Include the standard terraform-module.yml pipeline template

To run the tests in a CI pipeline, in your module's .gitlab-ci.yml, ensure that you include version >= v6.15.0 of the terraform-module.yml CI template:

include:
  - project: uis/devops/continuous-delivery/ci-templates
    file: /terraform-module.yml
    ref: v6.15.0

You’ll also need to define the following variables in the pipeline:

variables:
  TERRAFORM_DEPLOY_VERSION: "<terraform version>"
  GCP_PROJECT: "<project ID>"
  GOOGLE_IMPERSONATE_SERVICE_ACCOUNT: "terraform-deploy@<project ID>.iam.gserviceaccount.com"
  UCAM_DEVOPS_TERRAFORM_TEST: "<terraform module name>"

The GCP_PROJECT and GOOGLE_IMPERSONATE_SERVICE_ACCOUNT variable values can be found in the gcp-product-factory for the terraform-testing product.

TERRAFORM_DEPLOY_VERSION should be set according to the requirements of your specific project but must be at least 1.6 as this is when the terraform test command was introduced.

UCAM_DEVOPS_TERRAFORM_TEST must be set to the name of your Terraform module's project. This ensures the test cleanup script correctly targets any provisioned resources.

See also