This post is more of a note for me how to clone a specific tag from git repo branch and the commit/push the changes back. Also I’m adding a new tag for my changes.
Tags are nothing but checkpoints in a branch.
git clone <git repo url>
git checkout tags/v1.0.4 -b <Branch Name> //v1.0.4 is the latest tag on the branch
git describe --tags //This command will help us to confirm the tag
Now you can make all your changes to the code and once you are done,
git add <Files Updated>
git commit -m "<Summary of changes made>"
git tag -a v1.0.5 -m "<Overall Change Summary>" //Here we have added a new tag for our changes
git push --tags origin <Branch Name>
Unit testing of Terraform or an IaC tool is breaking the infrastructure code into small modules and testing them individually. But most of the infrastructure code deals with outside entities (cloud resources) so the testing steps would be,
Deploy the infrastructure
Validate it works (Via HTTP/API/SSH calls or commands)
Undeploy/Destroy the infrastructure.
Terratest is a go library that provides patterns and helper functions for testing the infrastructure, with support for Terraform, Packer, AWS and more. Here we are unit testing EC2, ELB & ASG modules using Terratest.
Benefits of Terratest:
Terratest is written in go language which has strong community and developer support. Terraform and Kubernetes are also written in go, this helps the transition easier and offers better integration.
It supports a wide range of cloud platforms, including AWS , Azure, GCP, as well as Kubernetes, Packer machine images, and Docker images.
Terratest framework is written in golang and has the following directory structure. All the files should be inside $GOPATH\src folder.
examples – All the Terraform code is saved in this folder. You can create sub folders for each project.
test – this folder contains all the Terratest files which we will use for testing our modules
Before we test our modules using Terratest we will explain the format of a simple test file. The basic structure/code to run a Terratest file is given below. Lets create a go file terraform_test.go which will contain our test cases.
First, we need to create a package and lets name it test.
package test
Now import all the necessary golang libraries that we need for our testing. This can be done by creating an import block and then adding all the libraries we need.
package test
import (
"testing"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/stretchr/testify/assert"
)
Add a new function to the code. This function can be named anything but for our continence we name it as TestEC2. The testing library is used by calling it inside the newly created function.
Now we can add our tests to the file. You can also see two other statements in the file which initialize and apply the changes also destroy the created infrastructure. Using “defer” runs the command at the end of the test, whether the test succeeds or fails.
package test
import (
"testing"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/stretchr/testify/assert"
)
func TestEC2 (t *testing.T) {
terraformOptions := &terraform.Options {
}
// At the end of the test, run `terraform destroy` to clean up any resources that were created
defer terraform.Destroy(t, terraformOptions)
// This will run `terraform init` and `terraform apply` and fail the test if there are any errors
terraform.InitAndApply(t, terraformOptions)
}
Now we will test our modules using Terratest. The test will create an EC2 instance, return the instance Id and and if the instance id is valid then mark the test as PASSED. Finally it will destroy the infrastructure it created.
Terraform code : This code will create an EC2 instance with Linux AMI using the EC2 module. We also have an output parameters which return instance id and tags.
Terratest code: In this code we mention the path of the Terraform files and then apply init and plan functions followed by apply. Once the instance is created, we check the instance id and the test is passed if it is valid.
Once the test is complete the resources are destroyed by Terratest.
package test
import (
"testing"
"github.com/gruntwork-io/terratest/modules/terraform"
"github.com/stretchr/testify/assert"
)
func TestEC2 (t *testing.T) {
t.Parallel()
terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
// The path to where our Terraform code is located
TerraformDir: "../examples/ec2",
})
defer terraform.Destroy(t, terraformOptions)
terraform.InitAndApply(t, terraformOptions)
instanceID := terraform.Output(t, terraformOptions, "instance_id")
assert.NotNil(t, instanceID)
}
Below are the results of our Terratest module. We ran the test in verbose mode so maximum information is displayed. It clearly lists the step-by-step process followed by the testing tool.
You can see the instance ids and tags values listed as per the output parameters. I had to truncate most of the output to remove sensitive information.
PS > go test -v -timeout 30m
=== RUN TestEC2
=== PAUSE TestEC2
=== CONT TestEC2
TestEC2 2021-07-12T12:32:18-04:00 retry.go:91: terraform [init -upgrade=false]
TestEC2 2021-07-12T12:32:18-04:00 logger.go:66: Running command terraform with args [init -upgrade=false]
TestEC2 2021-07-12T12:32:19-04:00 logger.go:66: ?[0m?[1mInitializing modules...?[0m
......
......
......
......
TestEC2 2021-07-12T12:34:28-04:00 logger.go:66: Destroy complete! Resources: 1 destroyed.?[0m
--- PASS: TestEC2 (130.78s)
PASS
ok test 131.936s