Gruntworks open-sourced their terraform, docker, packer etc. testing framework and I simply find it amazing. To my knowledge, there is nothing comparable out there.
Let’s take a look at a simple example. You can find the code at https://github.com/datacisions/terraform-examples. What we will do:
- Write a terratest to check whether a particularly labeled EC 2 instance is there;
- Run it an see it fail;
- Write the terraform code necessary to make it pass, to deploy the instance and label it.
- Run the test again to see it pass.
- Write a second, slightly more robust test for the same “component” (the EC 2 instance).
- Fix this bug in the terraform code
- See the second test pass.
To setup terraform see https://www.terraform.io/intro/getting-started/install.html. Make sure to configure your go paths correctly, see https://github.com/golang/go/wiki/SettingGOPATH. Put this project in your go-workspace. You can check your setup with
$ terraform - -version >… $ echo $GOPATH > ...
— src —— main.tf contains the AWS components —— outputs.tf defines what outputs we want from terraform (like some id) —— variables.tf contains variables we want to be able to set (e.g. instance size) — test — — firstExample_test.go contains our “test”.
1. Write a terratest
Let’s say you want to deploy an ec2 instance, then test that it’s there. Let’s think for a second about a test for this. What I usually do is to launch my instance with some test-label, then head over to the AWS console and check for that label. Then I might grab the IP and try to connect to it.
So that sounds like a plan, let’s write a test that at least checks whether an instance with a predefined label is there:
2. Run the test and see it fail
$ go test -v > --- FAIL: TestEc2InstanceProvisioning (109.93s) … FAIL exit status 1 FAILterraform-examples/test109.950s
3. Let’s fix this
# --------------------------------------------------------------------------------------------------------------------- # OPTIONAL PARAMETERS # These parameters have reasonable defaults. # --------------------------------------------------------------------------------------------------------------------- variable "region" { description = "AWS region to deploy the instances" default = "us-east-1" } variable "instance_name" { description = "The name tag to set for the EC2 Instance." default = "testing-example-instance" } variable "test_label" { description = "Tag to identify the instance as test instance." default = "yes" } variable "ami_id" { description = "Id of the ami to deploy, depends on region." default = "ami-b70554c8" // for region us-east-1 }
output "instance_id" { value = "${aws_instance.example.id}" } output "instance_private_ip" { value = "${aws_instance.example.private_ip}" }
# --------------------------------------------------------------------------------------------------------------------- # DEPLOY AN EC2 INSTANCE RUNNING UBUNTU provider "aws" { region = "${var.region}" profile= "admin" } resource "aws_instance" "example" { ami = "${var.ami_id}" instance_type = "t2.micro" tags { Name = "${var.instance_name}" Test = "${var.test_label}" } }
4. Run the test again, to see it pass
go test -v
5. Making things more interesting
6. Run terratest again
TestEc2InstanceProvisioningWithRandomRegion 2018-07-14T21:42:16+02:00 command.go:96: Destroy complete! Resources: 1 destroyed. ... --- PASS: TestEc2InstanceProvisioningWithRandomRegion (106.61s) .... --- PASS: TestEc2InstanceProvisioning (127.41s) PASS ok terraform-examples/test 127.432s