Examine the evolution of virtualization technologies from bare metal, virtual machines, and containers and the tradeoffs between them.
Install terraform and configure it to work with AWS
Learn the common terraform commands and how to use them
•Terraform Plan, Apply, Destroy
Use Terraform variables and outputs to improve make our configurations more flexible
Explore HCL language features in Terraform to create more expressive and modular infrastructure code.
Learn to break your code into modules to make it flexible and reuseable
Overview of two primary methods for managing multiple Terraform environments
Techniques for testing and validating Terraform code
Covers how teams generally work with Terraform, including automated deployment with CI/CD
In this lesson, we'll cover different testing techniques for Terraform code.
We'll walk through static checks, Bash script testing, and Terraform testing using the Terratest package from Gruntwork.
We'll also discuss a powerful test to execute periodic terraform plan commands within your CI/CD system.
Before we build out any tests, first lets review a reasonable layout for your code repository:
/modules - Define any modules that you are building.
/examples - Working examples of consuming the modules.
/deployed - Different environments such as production and staging.
/test - Contains various tests and checks for your Terraform code.
By structuring things this way, the purpose of each portion of the codebase is clear.
These checks are not tests, but they are useful for analyzing the codebase.
terraform fmt
: Formats your code according to Terraform's opinionated formatting structure. This can be used in continuous integration to enforce a consistent style guide.terraform validate
: Checks if your code is a valid Terraform configuration.A simple, (yet somewhat rudimentary) approach to testing is to use a Bash script to automate the process of applying, testing, and destroying resources.
The script should:
terraform init
and terraform apply with the -auto-approve
flag.sleep
command).curl
request to the IP address to check for a successful response.terraform destroy
when the test completes#!/bin/bash
set -euo pipefail
# Change directory to example
cd ../../examples/hello-world
# Create the resources
terraform init
terraform apply -auto-approve
# Wait while the instance boots up
# (Could also use a provisioner in the TF config to do this)
sleep 60
# Query the output, extract the IP and make a request
terraform output -json |\
jq -r '.instance_ip_addr.value' |\
xargs -I {} curl http://{}:8080 -m 10
# If request succeeds, destroy the resources
terraform destroy -auto-approve
The Terratest package from Gruntwork provides a more robust approach to testing Terraform code using the Go programming language. With Terratest, you can:
package test
import (
"crypto/tls"
"fmt"
"testing"
"time"
"github.com/gruntwork-io/terratest/modules/http-helper"
"github.com/gruntwork-io/terratest/modules/terraform"
)
func TestTerraformHelloWorldExample(t *testing.T) {
// retryable errors in terraform testing.
terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
TerraformDir: "../../examples/hello-world",
})
defer terraform.Destroy(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
instanceURL := terraform.Output(t, terraformOptions, "url")
tlsConfig := tls.Config{}
maxRetries := 30
timeBetweenRetries := 10 * time.Second
http_helper.HttpGetWithRetryWithCustomValidation(
t, instanceURL, &tlsConfig, maxRetries, timeBetweenRetries, validate,
)
}
func validate(status int, body string) bool {
fmt.Println(body)
return status == 200
}
One simple test that can be very useful is to periodically execute a terraform plan
command within your CI/CD system.
This will notify you of any changes made outside of Terraform, allowing you to investigate and either revert or incorporate the changes into your configuration.