Skip to main content

Terraform Automated Testing

All of our Terraform modules have automated tests. We have two sets of checks:

  • The first set of checks is executed through the feature-branch workflow, which can be found here This workflow generates some documentation and performs basic sanity checks, including linting and formatting. These checks are lightweight and can be executed without requiring any special permissions. Consequently, they are automatically run on every commit. Before committing and pushing your changes, you can and should run this set of checks locally by executing the following command on your host
make precommit/terraform

Running these checks locally incorporates all the required changes that otherwise would block your PR.

  • The second set of checks consists of Terraform integration tests that validate the functionality and integration of the module. These tests are performed using the terratest library, specifically designed for infrastructure testing, and do more in-depth integration tests of module functionality. Unlike the first set of checks, these integration tests are executed only on request, and only by authorized contributors. We use ChatOps to trigger this workflow.

Philosophy of Terraform Integration Testing

At a minimum, we ensure that all of our modules cleanly plan, apply and destroy. This catches 80% of the problems with only 20% of the effort. We also test than then the enabled input is set to false, no resources are created.

Ideally we would like to test that the resources are properly created, but often this is difficult to verify programmatically, in which case we settle for spot checking that the dynamic outputs match our expectations. At the same time, we do not want to waste effort retesting what has already been tested by HashiCorp and their providers. For example, we have our terraform-aws-s3-bucket module that creates an S3 bucket. We don't need to test that a bucket is created; we assume that would be caught by the upstream terraform tests. But we do want to test that the bucket name is what we expect it to be, since this is something under our control.

Using ChatOps To Trigger Integration Tests

In addition to automatic triggers, tests can be run on demand via "ChatOps". (You will need to have at least triage level of access to a repo to use ChatOps commands.) Typically, tests are run by a CloudPosse contributor or team member as part of a PR review.

Tests are initiated by posting GitHub comments on the PR. Currently supported commands are the following:

CommandDescription
/terratestRun the terratest integration tests in test/src

Terraform tests run against our testing infrastructure that we host in an isolated account on AWS, strictly for the purposes of testing infrastructure.

ChatOps is powered by GitHub Actions and the slash-dispatch-command.

The terratest workflow is defined in the cloudposse/actions repository. The benefit with this is that we have one place to control the testing workflow for all of our hundreds of terraform modules. The downside, however, with dispatched workflows is that the workflows always run from the main branch.

Manually triggering a shared workflow

Here's a list a workflows you might want to trigger manually should things go wrong on GitHub side or with our configuration.

  • feature-branch can be triggered anytime by labeling/unlabeling PR with any label.
  • release-branch is the same to creating a GH release manually. We have created a complimentary workflow release-published for this case: it will fulfill the missing parts once you create a release manually. Note that you are skipping tests before release in this case.
  • scheduled can be triggered anytime from GitHub UI, it has a workflow_dispatch trigger for this purpose.

ChatOps Configuration

If you're a contributor who wants to intialize one of our terraform modules, this is the process. Note, if a repo has already been configured for chatops, there's no need to proceed with these steps.

To initialize one of our modules with chatops, run the following commands:

  1. git clone the terraform module repository
  2. cd $repo to enter the repository directory
  3. make init to initialize the build-harness
  4. git add * to add the changes
  5. Add the build badge to the README.yaml under the badges section.
  6. make readme to rebuild the README.md (remember, never edit the README.md manually since it's generated from the README.yaml)
  7. Open up a Pull Request with the changes. Here is a good example.
  8. Request a Code Review in the #pr-reviews Slack channel (and big thanks for your contribution!)