This should be another short one. One of the advantages of IaC (infrastructure as code) is the fact you can test the things you write. There are multiple tools to test your Terraform configs with, but Gruntwork has created an awesome Go package to test your Terraform configs called Terratest. The advantage to Terratest is you just write Go like you would with anything else and it just works.

Here’s an example module to create an ec2 instance:

terraform
  • main
  • vars
  • outputs
1
2
3
4
5
6
7
8
9
10
11
12
provider "aws" {
    region  = "us-east-1"
}

resource "aws_instance" "web" {
    ami             = "ami-0f544554edba5e8ed"
    instance_type   = "t2.micro"

    tags = {
        Name = var.tag_name
    }
}

This is obviously a very simple module. It creates an ec2 instance and takes a single variable for the tag called Name. It then has an output variable called instance_id. To test this we can write a small Go test to check that the tag exists and is correct.

package test

import (
	"testing"

	"github.com/gruntwork-io/terratest/modules/aws"
	"github.com/gruntwork-io/terratest/modules/terraform"
	"github.com/stretchr/testify/assert"
)

func TestTerraform(t *testing.T) {
	tagName := "testing_tag"
	region := "us-east-1"

	terraformOptions := &terraform.Options{
		TerraformDir: "../",

		Vars: map[string]interface{}{
			"tag_name": tagName,
		},
	}

	defer terraform.Destroy(t, terraformOptions)

	terraform.InitAndApply(t, terraformOptions)

	instanceID := terraform.Output(t, terraformOptions, "instance_id")

	instanceTags := aws.GetTagsForEc2Instance(t, region, instanceID)

	testTag, containsTag := instanceTags["Name"]
	assert.True(t, containsTag)
	assert.Equal(t, tagName, testTag)
}

I have been putting my tests in a tests directory with my module. Then I can run go test -v ./tests/... to test the module.

The function TestTerraform passes the value testing_tag to the module’s tag_name variable. It then does a terraform init and a terraform apply. We defer the terraform destroy until the end of the tests.

Then we get the instance id from the output variable and pass that to the GetTagsForEc2Instance function. It grabs the tags for us and then we use the assert package to ensure the tag exists and is the correct one.

This is obviously a very simple test, but you can easily build on these concepts and have them run directly in your CI pipeline when you are working on your modules.