terratest Documentation

Terratest is a Go library that makes it easier to write automated tests for your infrastructure code.

7,983 stars Go Go 113 files Β· ~85,936 tokens #aws#devops#docker#golang#packer#terraform#testing#testing-library
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy terratest on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name terratest -p 4000:4000 --restart always gruntwork-io/terratest:latest
Configured Services & Ports
βš™οΈ web
image: build locally
πŸ”Œ Ports: 4000:4000, 35729:35729
docker-compose.yml
yaml (docker-compose.yml)
version: '3'

services:
  web:
    build: .
    volumes:
      # Bind mount the working dir so the app reloads automatically every time you make a change
      # Note that we use 'delegated' to improve perf on OSX: https://docs.docker.com/docker-for-mac/osxfs-caching/
      - .:/src:delegated
      # Bind a Docker-only volume to the generated _site folder to make it clear we don't need to sync that folder
      # back to the host OS. That makes Jekyll in Docker work much faster.
      - generated_site:/src/_site
    ports:
      - "4000:4000"
      # Expose port for jekyll livereload
      - "35729:35729"
    environment:
      - JEKYLL_ENV=development

volumes:
  generated_site:

Technical Documentation: gruntwork-io/terratest

ℹ️ Provenance: Multi-Tier Ingestion Β· CodeWiki Reference

Overview (`README.md`)

Terratest


Terratest is a Go library that makes it easier to write automated tests for your infrastructure code. It provides a
variety of helper functions and patterns for common infrastructure testing tasks, including:

  • Testing Terraform code
  • Testing Packer templates
  • Testing Docker images
  • Executing commands on servers over SSH
  • Working with AWS APIs
  • Working with Azure APIs
  • Working with GCP APIs
  • Working with Kubernetes APIs
  • Testing Helm Charts
  • Making HTTP requests
  • Running shell commands
  • And much more

Install

bash
go get github.com/gruntwork-io/terratest@latest

Requires Go 1.26 or later. To lock to a specific release instead of @latest, see Pinning a Terratest version.

Stability and versioning

Starting with v1.0.0, Terratest follows semantic versioning. Breaking changes to the public API
only happen in major releases (e.g. v2.0.0).

Symbols renamed or replaced in v1 are kept with // Deprecated: annotations pointing at the new name; removals happen
in v2. Migrating from v0.x: see the v1 migration guide. Migrating from v1 to v2: see the v2 migration guide.

v1 maintenance. With v2 in development, the v1 line has entered maintenance: it receives security fixes only,
delivered on the v1 branch, until 12 months after v2.0.0 reaches general availability. v2 ships under new /v2
module paths, so pinned v1 consumers are unaffected. Upgrade on your own schedule.

More info

License

This code is released under the Apache 2.0 License. Please see LICENSE and NOTICE for more details.

Copyright © 2025 Gruntwork, Inc.


Overview (`docs/README.md`)

Terratest website

This is the code for the Terratest website.

Terratest website is built with Jekyll and published on Github Pages from docs folder on main branch.

Quick Start

Download project

Clone or fork Terratest repository.

Run

  1. Install Ruby. Version 2.4 or above is recommended.
    Consider using rbenv to manage Ruby versions.

  2. Install bundler:

    bash
    gem install bundler
  3. Go to the docs folder:

    bash
    cd docs
  4. Install gems:

    bash
    bundle install
  5. Run the docs site locally:

    bash
    bundle exec jekyll serve
  6. Open http://localhost:4000/ in your web browser.

Deployment

GitHub Pages automatically rebuilds the website from the /docs folder whenever you commit and push changes to the main
branch.

Working with the documentation

We recommend updating the documentation before updating any code (see Readme Driven
Development
). This ensures the documentation
stays up to date and allows you to think through the problem at a high level before you get lost in the weeds of
coding.

The Terratest website contains Docs collection stored in /docs/_docs.

When you work with the documentation, it's good to preview the changes. To do that, run project as it is described in Run section.

  1. Change content on the existing page
  2. Add a new page
  3. Remove or rename page
  4. Add custom redirection

Change content on the existing page

  1. Find page in _docs by file name (it's the same as page's title).
  2. Edit content and save file.

Add a new page

  1. Create a new file in _docs. The file's name and title have to be the same.
  2. At the beginning of the file, add:
text
---
layout: collection-browser-doc                  # X Cannot be changed
title: Quick start                              # <--- Change this
categories:
  - getting-started                             # <--- Change this if needed
excerpt: Learn how to work with Terratest.      # <--- Change page description
tags: ["Quick Start", "DRY", "backend", "CLI"]  # <--- Set tags
order: 100                                      # <--- It sorts the docs on the list
nav_title: Documentation                        # X Cannot be changed
nav_title_link: /docs/                          # X Cannot be changed
---
  • layout - do not change! (Layout sets components like a navigation sidebar, page header, footer, etc.)
  • title - document title
  • category - the document's category. The categories in use are: 'getting-started', 'testing-best-practices', 'migrating-to-v1', 'migrating-to-v2', and 'community'.
  • excerpt - description. Try to keep it short.
  • tags - check other posts to see common tags, but you can set a new as well.
  • order - it is used to sort the documents within collection.
  • nav_title - the title displayed above navigation. It's optional and it's recommended to use the same as other files in the collection.
  • nav_title_link - it is URL. If it is set, the nav_title becomes a link with a given URL.
  1. Add content at the end of the file.

Remove or rename page

  1. Find page in _docs by file name (it's the same as page's title).
  2. Delete page or rename.

Add custom redirection

To add link to any page, including subpages outside of any collection, you can create a new file in specific collection (e.g. _docs), and set following content in the file:

text
---
title: Support
categories: Community
excerpt: Need help?
tags: ["support"]
redirect_to:
  - /support
order: 301
---

The navigation sidebar is built in _includes/collection_browser/navigation/_collection_toc.html.

First, the script groups documents of the given collection by categories. Categories make the uppermost level in the navigation sidebar.
Then, within each category, the script adds documents titles to the navigation under specific categories. Documents are sorted by order field set in frontmatter section.
Next, headings from each document are being extracted and added to the navigation.

Development

Project structure

text
|-- _docs                     # docs *collection*
|-- _includes                 # partials
|-- _layouts                  # layouts
|-- _pages                    # static pages
| |-- 404                     # "404: Not found" page
| |-- cookie-policy           # "Cookie Policy" page
| |-- docs                    # index page for *_docs* collection
| |-- index                   # home page
|
|-- _posts                    # Posts collection - empty and not used
|-- _site                     # website generated by Jekyll
|-- assets                    # Javascript, Stylesheets, and images
|-- scripts                   # useful scripts to use in development
| |-- convert_md_to_adoc      # contains the command to convert MD files to ADOC
|
|-- Gemfile
|-- _config.yml               # Jekyll configuration file

Documentation and Examples collections

The documentation is implemented as a Jekyll collection and built with Collection Browser.

Documentation collection

The index page of the Docs collection is in: _pages/docs/index.html and is available under /docs URL. It uses Collection browser from _includes/collection_browser/browser which makes the list of docs, adds search input with tag filter and puts navigation sidebar containing collection's categories.

Collection is stored in _docs folder.

Adding new pages to collections

The Docs collection uses collection browser which requires to setup proper meta tags in the doc file.

  1. Create a new file in collection folder. Docs add to the _docs.
text
---
layout: collection-browser-doc
title: CLI options  # CHANGE THIS
categories:
  - getting-started # CHANGE THIS
excerpt: >- # CHANGE THIS
  Terratest example description
tags: ["CLI"] # CHANGE THIS
order: 102 # CHANGE THIS
nav_title: Documentation # OPTIONAL
nav_title_link: /docs/ # OPTIONAL
---
  • layout - always has to be: collection-browser-doc [DO NOT CHANGE]
  • title - the doc title.
  • categories - set one category. Use downcase with dashes, e.g. getting-started.
  • excerpt - the doc description.
  • tags - doc tags.
  • order - it is used to list documents in the right order. "Getting Started" starts from 100, "Testing Best Practices" from 200, "Migrating to v1" from 300, "Migrating to v2" from 400, and "Community" from 500.
  • nav_title - the title above navigation. It's optional. It's a link if nav_title_link is set.
  • nav_title_link - it is a URL. If it is set, nav_link is transformed to the link.

Adding new collections

To add a new collection based on Collection browser, like Docs collection:

  1. Add collection to the _config.yml:
text
collections:
  my-collection:   # --> Change to your collection's name
    output: true
    sort_by: order
    permalink: /:collection/:categories/:title/  # --> You can adjust this to your needs. You can remove ":categories" if your collection doesn't use it.
  1. Create a folder for collection in root directory, e.g: _my-collection (change name)
  2. Add documents to the _my-collection folder and set proper meta tags (see: Adding new docs to collections).
  3. Create folder for collection's index page in _pages. Use collection name, e.g: _pages/my-collection.
  4. Add index.html file to newly create folder:
text
---
layout: collection-browser # DO NOT CHANGE THIS
title: Use cases
subtitle: Learn how to work with Terratest.
excerpt: Learn how to work with Terratest.
permalink: /examples/
slug: examples
nav_title: Documentation # OPTIONAL
nav_title_link: /docs/ # OPTIONAL
---

{% include collection_browser/browser.html collection=site.examples collection_name='examples' %}
  1. Change title, subtitle, excerpt, permalink, and slug in meta tags.
  2. In include statement, set collection to your collection set in _config.yml and set collection_name.

Collection Browser

The Collection Browser is strongly inspired by implementation of guides on gruntwork.io website.

The Collection Browser's purpose is to wrap Jekyll collection into:

  • index page containing ordered list of docs with search form,
  • show pages presenting docs' contents, and containing navigation sidebar,
  • and build navigation sidebar.

Usage

  1. Add collection to _config.yml
text
collections:
  my-collection:   # --> Change to your collection's name
    output: true
    sort_by: order
    permalink: /:collection/:categories/:title/  # --> You can adjust this to your needs. You can remove ":categories" if your collection doesn't use it.
  1. Create a folder for collection in root directory: _my-collection
  2. Add documents (.md format is recommended) to the _my-collection folder.
  3. In each document add:
text
---
layout: collection-browser-doc  # <-- It has to be "collection-browser-doc"
title: CLI options              # <-- [CHANGE THIS] doc's title
categories:                     # <-- [CHANGE THIS] use single category. (Downcase and dashes instead of spaces)
  - getting-started
excerpt: >-                     # <-- [CHANGE THIS] doc's description
  Some description.
tags: ["CLI", "Another tag"]    # <-- [CHANGE THIS] doc's tags
order: 102                      # <-- [CHANGE THIS] set different number to each doc to set right order
---
  1. Create index page for collection. Create folder with collection name in _pages: my-collection
  2. Add index.html in _pages/my-collection:
text
---
layout: collection-browser         # <-- It has to be "collection-browser"
title: Use cases
subtitle: Learn how to work with Terratest.
excerpt: Learn how to work with Terratest.
permalink: /use-cases/
slug: use-cases
---

{% include collection_browser/browser.html collection=site.my-collection collection_name='my-collection' %}

Adjust meta tags and replace my-collection with your collection name in {% include ... %}

How it works

The Collection Browser needs the index page in _pages folder. It basically imports browser.html from _includes/collection_browser.
Meta tags, like title, subtitle, excerpt, are used by Collection Browser on index page. The index page is then published under URL assigned to permalink.

The index page displays the list of collection's docs. Clicking on any of them, redirects user to the collection's doc page.

config.yml

Collections are registered in the _config.yml file like other typical Jekyll collections.
Additional field used in the configuration is: sort_by: order. It ensures that collection's documents are displayed in the right order.
The order is set then in every collection document. For large collections it's recommended to split files into several folders, and then to use 3-digit numbers. So each folder would have reserved range of numbers, like: 100 - 199, 200-299, etc. It makes easy to add new documents without overwriting order fields in other docs.

Layouts

The Collection Browser uses two layouts:

  • _layouts/collection-browser.html - for the index page containing the list of documents
  • _layouts/collection-browser-doc.html - for the "show" page of collection's doc

Includes

All Collection Browser partials are stored in _includes/collection_browser.

  • browser.html - it is the collection's index page
  • _doc-page.html - is a starting point for collection's document pages (show pages)

Some includes may use partials from _includes directory. For example, _includes/collection_browser/_cta-section.html uses _includes/links-n-built-by.html.

Assets

Names of assets used by collection-browser in assets folder start with collection-browser.

Collection Browser's classes in stylesheets starts mostly with cb, collection-browser and collection-browser-doc.

Javascript files used by Collection Browser:

  • collection-browser_scroll.js - responsible for the scroll spying in navigation sidebar and sticking this bar at the top of the screen when page is being scrolled.
  • collection-browser_search.js - responsible for handling text search and tag filters.
  • collection-browser_toc.js - responsible for opening and closing navigation sidebar on the document page.

The navigation sidebar is built in _includes/collection_browser/navigation/_collection_toc.html. Read more: Navigation

Markdown (md) > AsciiDoc (adoc) converter

Recommended format of documents is Github Markdown (.md). If you use the Markdown format (.md), and you want to convert to AsciiDoc format, you can do this with Pandoc:

  1. Create input.md file and paste there Markdown content
  2. Run:
text
$ pandoc --from=gfm --to=asciidoc --wrap=none --atx-headers  input.md > output.adoc
  1. The converted content in .adoc format is printed in output.adoc

You can use also scripts/convert_md_to_adoc.sh.

AsciiDoc (adoc) > Markdown (md) converter

To convert from .adoc (AsciiDoc) format to Markdown, you need AsciiDoctor and Pandoc.

First, install Asciidoctor:

text
$ sudo apt-get install asciidoctor

Next, install Pandoc:
https://pandoc.org/installing.html

Then you can use script: scripts/convert_adoc_to_md.sh or use the command:

text
$ asciidoctor -b docbook input.adoc && pandoc -f docbook -t gfm input.xml -o output.md --wrap=none --atx-headers

In both cases:

  1. create a file: input.adoc,
  2. add content to the file,
  3. run script or command,
  4. The output can be found in output.md.

Overview (`test-docker-images/README.md`)

Gruntwork Terratest Docker Images

As part of writing Unit Tests with Terratest, we recommend using Packer to
build a Docker image using the same script provisioners that
Packer uses to configure the Amazon Machine Image you would normally build for production usage. Docker images build 10x
faster than AMIs and launch 100x faster, reducing our cycle time while developing.

But Packer's Docker image builds can still be slower than desired because, unlike a native docker build command against
a Dockerfile, Packer does not use any image caching.
As a result, each packer build creates the Docker image from scratch. Unfortunately, much of the Docker image build
time is spent downloading libraries like curl and sudo which we assume are present on the AWS AMI associated with
Ubuntu, Amazon Linux, CentOS, or any other Linux distro we're supporting.

We solve this problem by creating canonical Gruntwork Terratest Docker Images which have most of the desired libraries
pre-installed. We upload these images to a public Docker Hub repo such as https://hub.docker.com/r/gruntwork/ubuntu-test/ so
that Packer templates that build Docker images can reference them directly as in the following example.

Sample Packer Builder

json
{
  "builders": [{
    "name": "ubuntu-ami",
    "type": "amazon-ebs"
    // ... (other params omitted) ...
  },{
    "name": "ubuntu-docker",
    "type": "docker",
    "image": "gruntwork/ubuntu-test:18.04",
    "commit": "true"
  }],
  "provisioners": [
    // ...
  ],
  "post-processors": [{
    "type": "docker-tag",
    "repository": "gruntwork/example",
    "tag": "latest",
    "only": ["ubuntu-docker"]
  }]
}

Overview (`examples/azure/README.md`)

Terratest Configuration and Setup

Terratest uses Go to make calls to Azure through the azure-sdk-for-go library and independently confirm the actual Azure resource property matches the expected state provided by Terraform output variables.

  • Instructions for running each Azure Terratest module are included in each Terraform example sub-folder:
    • examples/azure/terraform-azure-*-example/README.md
  • Tests which assert against expected Terraform output values are located in the the respective go files of the folder:
  • Test APIs which provide the actual Azure resource property values via the azure-sdk-for-go are located in the folder:

Go Dependencies

Install Golang and make sure this code is checked out into your GOPATH

These modules are currently using the latest version of Go and was tested with go1.14.4.

Azure-sdk-for-go version

Let's make sure go.mod includes the appropriate azure-sdk-for-go version:

go
require (
    ...
    github.com/Azure/azure-sdk-for-go v46.1.0+incompatible
    ...
)

If we make changes to either the go.mod or the go test file, we should make sure that the go build command works still.

powershell
go build terraform_azure_*_test.go

Review Environment Variables

As part of configuring terraform for Azure, we'll want to check that we have set the appropriate credentials and also that we set the environment variables on the testing host.

For non-commercial cloud deployments, set the "AZURE_ENVIRONMENT" environment variable to the appropriate cloud environment (this is used by the client_factory to set the correct azure endpoints):

bash
export ARM_CLIENT_ID=your_app_id
export ARM_CLIENT_SECRET=your_password
export ARM_SUBSCRIPTION_ID=your_subscription_id
export ARM_TENANT_ID=your_tenant_id

# AZURE_ENVIRONMENT is the name of the Azure environment to use. Set to one of the following:
export AZURE_ENVIRONMENT=AzureUSGovernmentCloud
export AZURE_ENVIRONMENT=AzureChinaCloud
export AZURE_ENVIRONMENT=AzureGermanCloud
export AZURE_ENVIRONMENT=AzurePublicCloud
export AZURE_ENVIRONMENT=AzureStackCloud

Note, in a Windows environment, these should be set as system environment variables. We can use a PowerShell console with administrative rights to update these environment variables:

powershell
[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_ID",$your_app_id,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_SECRET",$your_password,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable("ARM_SUBSCRIPTION_ID",$your_subscription_id,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable("ARM_TENANT_ID",$your_tenant_id,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable("AZURE_ENVIRONMENT",$your_azure_env,[System.EnvironmentVariableTarget]::Machine)

Overview (`examples/docker-hello-world-example/README.md`)

Docker "Hello, World" Example

This folder contains a Dockerfile to build a very simple Docker imageβ€”one which contains a text file with the
text "Hello, World"!β€”to demonstrate how you can use Terratest to write automated tests for your Docker images.

Check out test/docker_hello_world_example_test.go to see how you can write
automated tests for this simple Docker image.

Building the Docker container

  1. Install Docker and make sure it's on your PATH.
  2. Run docker build -t gruntwork/docker-hello-world-example ..
  3. Run docker run -it --rm gruntwork/docker-hello-world-example cat /test.txt.
  4. You should see the text "Hello, World!"

Running automated tests against the Docker container

  1. Install Docker and make sure it's on your PATH.
  2. Install Golang and make sure this code is checked out into your GOPATH.
  3. cd test
  4. go test -v -run TestDockerHelloWorldExample

Overview (`examples/helm-basic-example/README.md`)

Helm Basic Example

This folder contains a minimal helm chart to demonstrate how you can use Terratest to test your helm charts.

There are two kinds of tests you can perform on a helm chart:

  • Helm Template tests are tests designed to test the logic of the templates. These tests should run helm template with
    various input values and parse the yaml to validate any logic embedded in the templates (e.g by reading them in using
    client-go). Since templates are not statically typed, the goal of these tests is to promote fast cycle time
  • Helm Integration tests are tests that are designed to deploy the infrastructure and validate that it actually
    works as expected. If you consider the templates to be syntactic tests, these are semantic tests that validate the
    behavior of the deployed resources.

The helm chart deploys a single replica Deployment resource given the container image spec and a Service that
exposes it. This chart requires the containerImageRepo and containerImageTag input values.

See the corresponding terratest code for an example of how to test this chart:

Running automated tests against this Helm Chart

  1. Install and setup helm
  2. Install Golang and make sure this code is checked out into your GOPATH.
  3. cd test
  4. dep ensure
  5. go test -v -tags helm -run TestHelmBasicExampleTemplate for the template test
  6. go test -v -tags helm -run TestHelmBasicExampleDeployment for the integration test

NOTE: we have build tags to differentiate kubernetes tests from non-kubernetes tests, and further differentiate helm
tests. This is done because minikube is heavy and can interfere with docker related tests in terratest. Similarly, helm
can overload the minikube system and thus interfere with the other kubernetes tests. Specifically, many of the tests
start to fail with connection refused errors from minikube. To avoid overloading the system, we run the kubernetes
tests and helm tests separately from the others. This may not be necessary if you have a sufficiently powerful machine.
We recommend at least 4 cores and 16GB of RAM if you want to run all the tests together.


Overview (`examples/helm-dependency-example/README.md`)

Helm Dependency Example

This folder contains a minimal helm chart to demonstrate how you can use Terratest to test your helm charts with dependencies.

There are two kinds of tests you can perform on a helm chart:

  • Helm Template tests are tests designed to test the logic of the templates. These tests should run helm template with
    various input values and parse the yaml to validate any logic embedded in the templates (e.g by reading them in using
    client-go). Since templates are not statically typed, the goal of these tests is to promote fast cycle time

The helm chart deploys a single replica Deployment resource given the container image spec and a Service that
exposes it. This chart requires the containerImageRepo and containerImageTag input values.

See the corresponding terratest code for an example of how to test this chart:

Running automated tests against this Helm Chart

  1. Install and setup helm
  2. Install Golang and make sure this code is checked out into your GOPATH.
  3. cd test
  4. dep ensure
  5. go test -v -tags helm -run TestHelmDependencyExampleTemplate for the template test

NOTE: we have build tags to differentiate kubernetes tests from non-kubernetes tests, and further differentiate helm
tests. This is done because minikube is heavy and can interfere with docker related tests in terratest. Similarly, helm
can overload the minikube system and thus interfere with the other kubernetes tests. Specifically, many of the tests
start to fail with connection refused errors from minikube. To avoid overloading the system, we run the kubernetes
tests and helm tests separately from the others. This may not be necessary if you have a sufficiently powerful machine.
We recommend at least 4 cores and 16GB of RAM if you want to run all the tests together.


Overview (`examples/kubernetes-basic-example/README.md`)

Kubernetes Basic Example

This folder contains a minimal Kubernetes resource config file to demonstrate how you can use Terratest to write
automated tests for Kubernetes.

This resource file deploys an nginx container as a single pod deployment with a node port service attached to it.

See the corresponding terratest code for an example of how to test this resource config:

Deploying the Kubernetes resource

  1. Setup a Kubernetes cluster. We recommend using a local version:

  2. Install and setup kubectl to talk to the deployed
    Kubernetes cluster.

  3. Run kubectl apply -f nginx-deployment.yml

Running automated tests against this Kubernetes deployment

  1. Setup a Kubernetes cluster. We recommend using a local version:

  2. Install and setup kubectl to talk to the deployed
    Kubernetes cluster.

  3. Install and setup kubectl.

  4. Install Golang and make sure this code is checked out into your GOPATH.

  5. cd test

  6. dep ensure

  7. go test -v -tags kubernetes -run TestKubernetesBasicExample

  8. You can also run TestKubernetesBasicExampleServiceCheck


Overview (`examples/kubernetes-hello-world-example/README.md`)

Kubernetes "Hello, World" Example

This folder contains the most minimal Kubernetes resource configβ€”which deploys a simple webapp that responds with
"Hello, World!"β€”to demonstrate how you can use Terratest to write automated tests for Kubernetes.

Check out test/kubernetes_hello_world_example_test.go to see how you can
write automated tests for this simple resource config.

Deploying the Kubernetes resource

  1. Setup a Kubernetes cluster. We recommend using a local version:
  2. Install and setup kubectl to talk to the deployed
    Kubernetes cluster.
  3. Run kubectl apply -f hello-world-deployment.yml

Running automated tests against this Kubernetes deployment

  1. Setup a Kubernetes cluster. We recommend using a local version:
  2. Install and setup kubectl to talk to the deployed
    Kubernetes cluster.
  3. Install Golang and make sure this code is checked out into your GOPATH.
  4. cd test
  5. go test -v -tags kubernetes -run TestKubernetesHelloWorldExample

Overview (`examples/kubernetes-kustomize-example/README.md`)

Kubernetes Kustomize Example

This folder contains a minimal Kubernetes resource config file to demonstrate how you can use Terratest to write
automated tests for Kubernetes.

This resource file deploys an nginx container as a single pod deployment with a node port service attached to it.

See the corresponding terratest code for an example of how to test this resource config:

Deploying the Kubernetes resource

  1. Setup a Kubernetes cluster. We recommend using a local version:

  2. Install and setup kubectl to talk to the deployed
    Kubernetes cluster.

  3. Run kubectl apply -k .

Running automated tests against this Kubernetes deployment

  1. Setup a Kubernetes cluster. We recommend using a local version:

  2. Install and setup kubectl to talk to the deployed
    Kubernetes cluster.

  3. Install Golang and make sure this code is checked out into your GOPATH.

  4. cd test

  5. dep ensure

  6. go test -v -tags kubernetes -run TestKubernetesKustomizeExample


Overview (`examples/kubernetes-rbac-example/README.md`)

Kubernetes RBAC Example

This folder contains a Kubernetes resource config file that creates a new Namespace and a ServiceAccount that has admin
level permissions in the Namespace, but nowhere else. This example is used to demonstrate how you can test RBAC
permissions using terratest.

See the corresponding terratest code (kubernetes_rbac_example_test.go) for
an example of how to test this resource config:

Deploying the Kubernetes resource

  1. Setup a Kubernetes cluster. We recommend using a local version:

  2. Install and setup kubectl to talk to the deployed
    Kubernetes cluster.

  3. Run kubectl apply -f namespace-service-account.yml

Running automated tests against this Kubernetes deployment

  1. Setup a Kubernetes cluster. We recommend using a local version:

  2. Install and setup kubectl to talk to the deployed
    Kubernetes cluster.

  3. Install and setup kubectl.

  4. Install Golang and make sure this code is checked out into your GOPATH.

  5. cd test

  6. dep ensure

  7. go test -v -tags kubernetes -run TestKubernetesRBACExample


Overview (`examples/packer-basic-example/README.md`)

Packer Basic Example

This folder contains a very simple Packer template to demonstrate how you can use Terratest to write automated tests
for your Packer templates. The template just creates an up-to-date Ubuntu AMI by running apt-get update and
apt-get upgrade.

Check out test/packer_basic_example_test.go to see how you can write
automated tests for this simple template.

Note that this template doesn't do anything useful; it's just here to demonstrate the simplest usage pattern for
Terratest. For slightly more complicated, real-world examples of Packer templates and the corresponding tests, see
packer-docker-example and
terraform-packer-example.

Installation steps

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables.
  3. Install Packer and make sure it's on your PATH.

Building the Packer template manually (Packer >= 1.7.0)

  1. Run packer init build.pkr.hcl. # Use build-gcp.pkr.hcl if using GCP
  2. Run packer build build.pkr.hcl. # Use build-gcp.pkr.hcl if using GCP

Building the Packer template manually (Packer < 1.7.0)

  1. Run packer build build.json.

Running automated tests against this Packer template

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables.
  3. Install Packer and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. cd test
  6. dep ensure
  7. go test -v -run TestPackerBasicExample

Running automated tests against this Packer template for the GCP builder

  1. Sign up for GCP.
  2. Configure your GCP credentials using one of the
    Authentication methods.
  3. Install Packer and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. cd test
  6. dep ensure
  7. go test -v -run TestPackerGCPBasicExample

Running automated tests against this Packer template for the OCI builder

  1. Sign up for OCI.
  2. Configure your OCI credentials via CLI Configuration
    Information
    .
  3. Create VCN and subnet
    resources in your tenancy (a.k.a. a root compartment).
  4. (Optional) Create TF_VAR_pass_phrase environment property with the pass phrase for decrypting of the OCI API signing
    key
    (can be omitted
    if the key is not protected).
  5. Install Packer and make sure it's on your PATH.
  6. Install Golang and make sure this code is checked out into your GOPATH.
  7. cd test
  8. dep ensure
  9. go test -v -run TestPackerOciExample

Overview (`examples/packer-docker-example/README.md`)

Packer Docker Example

This folder contains a Packer template to demonstrate how you can use Terratest to write automated tests for your
Packer templates. The template creates an Ubuntu AMI with a simple web app (built on top of Ruby / Sinatra) installed.
This template also creates a Docker image with the same web app installed, and contains a docker-compose.yml file
for running that Docker image. These allow you to test your Packer template completely locally, without having to
deploy to AWS.

Check out test/packer_docker_example_test.go to see how you can write
automated tests for this simple template.

The Docker-based tests in this folder are in some sense "unit tests" for the Packer template. To see an example of
"integration tests" that deploy the AMI to AWS, check out the
terraform-packer-example.

Installation steps

  1. Install Packer and make sure it's on your PATH.
  2. Install Docker and make sure it's on your PATH.

Building a Docker image for local testing (Packer >= 1.7.0)

  1. Run packer init build.pkr.hcl.
  2. Run packer build build.pkr.hcl.

Building a Docker image for local testing (Packer < 1.7.0)

  1. Run packer build build.json.

Run the container

  1. Run docker compose up.
  2. You should now be able to access the sample web app at http://localhost:8080

Building an AMI for testing in AWS

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables.
  3. Install Packer and make sure it's on your PATH.
  4. Run packer build -only=ubuntu-ami build.json.

Running automated tests locally against this Packer template

  1. Install Packer and make sure it's on your PATH.
  2. Install Docker and make sure it's on your PATH.
  3. Install Golang and make sure this code is checked out into your GOPATH.
  4. cd test
  5. dep ensure
  6. go test -v -run TestPackerDockerExampleLocal

Running automated tests in AWS against this Packer template

See terraform-packer-example.


Overview (`examples/packer-hello-world-example/README.md`)

Packer "Hello, World" Example

This folder contains the simplest possible Packer templateβ€”one that builds a Docker image with a text file that says
"Hello, World"!β€”to demonstrate how you can use Terratest to write automated tests for your Packer templates.

Check out test/packer_hello_world_example_test.go to see how you can write
automated tests for this simple template.

Installation steps

  1. Install Packer and make sure it's on your PATH.
  2. Install Docker and make sure it's on your PATH.

Building the Packer template (Packer >= 1.7.0)

  1. Run packer init build.pkr.hcl.
  2. Run packer build build.pkr.hcl.

Building the Packer template (Packer < 1.7.0)

  1. Run packer build build.json.

Run Docker

  1. Run docker run -it --rm gruntwork/packer-hello-world-example cat /test.txt.
  2. You should see the text "Hello, World!"

Running automated tests against the Packer template

  1. Install Packer and make sure it's on your PATH.
  2. Install Docker and make sure it's on your PATH.
  3. Install Golang and make sure this code is checked out into your GOPATH.
  4. cd test
  5. go test -v -run TestPackerHelloWorldExample

Overview (`examples/terraform-asg-scp-example/README.md`)

Terraform ASG SCP Example

This folder contains a simple Terraform module that deploys resources in AWS to demonstrate
how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys an ASG with one instance.
The EC2 Instance allows SSH requests on the port specified by the ssh_port variable.

Check out test/terraform_scp_example_test.go to see how you can write
automated tests for this module.

Note that the example in this module is still fairly simplified, as the EC2 Instance doesn't do a whole lot! For a more
complicated, real-world, end-to-end example of a Terraform module and web server, see
terraform-packer-example.

WARNING: This module and the automated tests for it deploy real resources into your AWS account which can cost you
money. The resources are all part of the AWS Free Tier, so if you haven't used that up,
it should be free, but you are completely responsible for all AWS charges.

Overview

When a test fails, it is often important to be able to quickly get to logs and config files from your deployed apps and services. Currently, getting at this information is a bit of a pain. Often times, it would be necessary to "catch it in the act". Usually this would require running tests and then "pausing"/not tearing down the infrastructure, ssh-ing to individual instances and then viewing the logs/config files that way. This in not very convenient and gets even more tricky when trying to get the same results for tests being executed by your CI server.

You can use terratest to help with this task by specifying RemoteFileSpecification structs that describe which files you want to copy from your instances:

go
ctx := t.Context()

logstashSpec := aws.RemoteFileSpecification{
	SshUser:sshUserName,
	UseSudo:true,
	KeyPair:keyPair,
	LocalDestinationDir:filepath.Join("/tmp", "logs", t.Name(), "logstash"),
	AsgNames: strings.Split(strings.Replace(terraform.OutputRequiredContext(t, ctx, terraformOptions, "logstash_server_asg_names"), "\n", "", -1), ","),
	RemotePathToFileFilter: map[string][]string {
		"/var/log/logstash":{"*"},
		"/etc/logstash/conf.d" : {"*"},
	},
}

Once you've described what files you want, grabbing them from ASGs is simple with:

go
aws.FetchFilesFromAsgsPContextE(t, ctx, awsRegion, &logstashSpec)

or directly from EC2 instances with:

go
aws.FetchFilesFromInstanceContext(t, ctx, awsRegion, sshUserName, keyPair, appServerInstanceId, true, appServerConfig, filepath.Join("/tmp", "logs", t.Name(), "app_server"), []string{"*.yml", "caFile", "*.key", "*.pem"})

Finally, to put all of this together, in your go test you could do something like:

go
defer teststructure.RunTestStage(t, "grab_logs", func() {
	if t.Failed() {
		takeElkMultiClusterLogSnapshot(t, examplesDir, awsRegion, "ubuntu")
	}
})

The code above will run at the very end of your test and grab a snapshot of all of the log descriptors you've defined specifically when your tests fail. We usually like to defer the logging snapshot right before we defer the terraform teardown. This way, if our tests fail, we are able to grab a snapshot of all the relevant logs and config files across our whole deployment!

You can even take this a step further and pair this with your CI's artifact storage mechanism to have all of your logs and config files attached to your broken CI build when tests failed. For example, with CircleCI, you could do something like:

yml
- store_artifacts:
          path: /tmp/logs

Now, to get at your logs when your tests fail, you will just be able to click the links right in your CI.

Running this module manually

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Run terraform init.
  5. Run terraform apply.
  6. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. cd test
  6. dep ensure
  7. go test -v -run TestTerraformScpExample

Overview (`examples/terraform-aws-dynamodb-example/README.md`)

Terraform AWS DynamoDB Example

This folder contains a simple Terraform module that deploys a DynamoDB table
with server-side encryption, point in time recovery and a TTL (time to live) attribute
to demonstrate how you can use Terratest to write automated tests for your AWS Terraform code.

Check out test/terraform_aws_dynamodb_example_test.go to see how you can
test this module and validate the configuration of the parameters and options.

WARNING: This module and the automated tests for it deploy real resources into your AWS account which can cost you
money.

Running this module manually

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Set the AWS region you want to use as the environment variable AWS_DEFAULT_REGION.
  4. Install Terraform and make sure it's on your PATH.
  5. Run terraform init.
  6. Run terraform apply.
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. cd test
  6. dep ensure
  7. go test -v -run TestTerraformAwsDynamoDBExample

Overview (`examples/terraform-aws-ec2-windows-example/README.md`)

Windows Instance Example

This folder provides a Packer template that can be used to build an Amazon Machine Image (AMI) of a Windows 2016 Server that comes pre-installed with:

In addition, this folder provides an example of how to launch a Windows instance based off this AMI that can be connected to via a Remote Desktop Protocol (RDP) client for the purposes of testing software or experimentation.

This setup is ideal for "hot-reloading" code that you're actively developing and testing it against the Windows server. You can develop your code in your usual environment, perhaps a Mac or Linux laptop, yet see your changes reflected on the Windows server in seconds, by sharing a folder from your development machine with the Windows server via the RDP client.

Quick start

Pre-requistes:

First, we'll build the AMI for the Windows Instance. Change into the packer directory:

cd packer

In order to build an Amazon Machine Image with Packer, you'll need to export your AWS account credentials. You can export your AWS credentials as the environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.

For more information on authenticating to your AWS account from the command line, see our blog post Authenticating to AWS with Environment Variables.

With your credentials properly exported, you can now run the packer build:

packer build build.pkr.hcl

This may take upwards of 25 minutes to complete, but generally completes in about 5 minutes. Keep an eye on your EC2 dashboard and ensure that you have selected the correct region and that you are on the AMI view. Once your AMI status has changed from "Pending" to "Available", you can copy your AMI ID.

Create a new file named terraform.tfvars in this same directory and enter the following variables:

hcl
ami              = "<the AMI ID you copied in the previous step>"
region           = "us-east-1"
root_volume_size = 100

Save the file.

You're now ready to run terraform plan and check the output before proceeding:

terraform plan

Take a look at the plan output and ensure everything looks correct. You should see a single EC2 instance being created along with supporting resources such as a security group and security group rules.

Once you're satisfied that the plan looks good, run terraform apply to create the infrastructure:

terraform apply --auto-approve

Once your resources apply successfully you'll see a similar output message containing the public IPv4 address of your Windows instance:

instance_ip = "35.84.139.82"


Overview (`examples/terraform-aws-ecs-example/README.md`)

Terraform AWS ECS Example

This folder contains a simple Terraform module that deploys a simple ECS service in AWS
to demonstrate how you can use Terratest to write automated tests for your AWS Terraform code.

This module registers a task definition with AWS Fargate launch type and associates it with a service
to run and maintain a specified number of instances.

Check out test/terraform_aws_ecs_example_test.go to see how you can write
automated tests for this module and validate the configuration of the parameters and options.

WARNING: This module and the automated tests for it deploy real resources into your AWS account which can cost you
money.

Running this module manually

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Set the AWS region you want to use as the environment variable AWS_DEFAULT_REGION.
  4. Install Terraform and make sure it's on your PATH.
  5. Run terraform init.
  6. Run terraform apply.
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. cd test
  6. dep ensure
  7. go test -v -run TestTerraformAwsEcsExample

Overview (`examples/terraform-aws-example/README.md`)

Terraform AWS Example

This folder contains a simple Terraform module that deploys resources in AWS to demonstrate
how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys an EC2
Instance
and gives that Instance a Name tag with the value specified in the
instance_name variable.

Check out test/terraform_aws_example_test.go to see how you can write
automated tests for this module.

Note that the EC2 Instance in this module doesn't actually do anything; it just runs a Vanilla Ubuntu 16.04 AMI for
demonstration purposes. For slightly more complicated, real-world examples of Terraform modules, see
terraform-http-example and terraform-ssh-example.

WARNING: This module and the automated tests for it deploy real resources into your AWS account which can cost you
money. The resources are all part of the AWS Free Tier, so if you haven't used that up,
it should be free, but you are completely responsible for all AWS charges.

Running this module manually

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Set the AWS region you want to use as the environment variable AWS_DEFAULT_REGION.
  4. Install Terraform and make sure it's on your PATH.
  5. Run terraform init.
  6. Run terraform apply.
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. cd test
  6. dep ensure
  7. go test -v -run TestTerraformAwsExample

Overview (`examples/terraform-aws-hello-world-example/README.md`)

Terraform AWS "Hello, World" Example

This folder contains a simple Terraform module that deploys resources in AWS to demonstrate
how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys an EC2
Instance
which runs a web server that responds with "Hello, World!" on port 8080.

Check out test/terraform_aws_hello_world_example_test.go to see how
you can write automated tests for this module.

WARNING: This module and the automated tests for it deploy real resources into your AWS account which can cost you
money. The resources are all part of the AWS Free Tier, so if you haven't used that up,
it should be free, but you are completely responsible for all AWS charges.

Running this module manually

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Run terraform init.
  5. Run terraform apply.
  6. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. cd test
  6. go test -v -run TestTerraformAwsHelloWorldExample

Overview (`examples/terraform-aws-lambda-example/README.md`)

Terraform Lambda Example

This folder contains a Terraform module to demonstrate how you can use Terratest to deploy a lambda function
for your Terraform code. This module takes in an input variable called function_name, and uses the function name as
an identifier for the lambda and associated resources (e.g. IAM role).

Check out test/terraform_aws_lambda_example_test.go to see how you can write
automated tests for this simple module.

The function that this module creates is a simple one whose input can cause it to error or echo messages it receives.

Running this module manually

  1. Install Terraform and make sure it's on your PATH.
  2. Run terraform init.
  3. Run terraform apply.
  4. When you're done, run terraform destroy.

Running automated tests against this module

  1. Install Terraform and make sure it's on your PATH.
  2. Install Golang and make sure this code is checked out into your GOPATH.
  3. cd test
  4. dep ensure
  5. go test -v -run TestTerraformAwsLambdaExample

Overview (`examples/terraform-aws-network-example/README.md`)

Terraform AWS Network Example

This folder contains a Terraform module that deploys a simple network setup to demonstrate how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys two subnets within one availability zone. One subnet is public - it has a route to an internet gateway. The other subnet is private. There is a NAT gateway deployed and configured for it.
Check out test/terraform_aws_network_example_test.go to see how you can write automated tests for this module and verify the basic parameters of the VPC and subnets.

WARNING: This module and the automated tests for it deploy real resources into your AWS account which can cost you
money. The resources are all part of the AWS Free Tier, so if you haven't used that up,
it should be free, but you are completely responsible for all AWS charges.

Running this module manually

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Set the AWS region you want to use as the environment variable AWS_DEFAULT_REGION.
  4. Install Terraform and make sure it's on your PATH.
  5. Run terraform init.
  6. Run terraform apply.
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. cd test
  6. dep ensure
  7. go test -v -run TestTerraformAwsNetworkExample

Overview (`examples/terraform-aws-rds-example/README.md`)

Terraform AWS RDS Example

This folder contains a simple Terraform module that deploys a database instance (MySQL by default) in AWS
to demonstrate how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys an RDS
Instance
and associates it with an option group and parameter group to customize it.

Check out test/terraform_aws_rds_example_test.go to see how you can write
automated tests for this module and validate the configuration of the parameters and options.

This module does not use the database instance created in any way. It can be used though to validate any combination of inputs
passed while creating database instances in AWS RDS. Hence the plain text simple password used here should not have any security
implications.

WARNING: This module and the automated tests for it deploy real resources into your AWS account which can cost you
money. The resources are all part of the AWS Free Tier, so if you haven't used that up,
it should be free, but you are completely responsible for all AWS charges.

Running this module manually

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Set the AWS region you want to use as the environment variable AWS_DEFAULT_REGION.
  4. Install Terraform and make sure it's on your PATH.
  5. Run terraform init.
  6. Run terraform apply.
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. cd test
  6. dep ensure
  7. go test -v -run TestTerraformAwsRdsExample

Overview (`examples/terraform-aws-s3-example/README.md`)

Terraform AWS S3 Example

This folder contains a simple Terraform module that deploys resources in AWS to demonstrate
how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys 2 S3
Buckets
- one S3 Bucket with logging and versioning enabled, and another "targetBucket" one to serve as a
logging location for the first S3 Bucket. This module gives both Buckets a Name & Environment tag with the value
specified in the tag_bucket_name and tag_bucket_environment variables, respectively. This module also contains a terraform variable
that will create a basic bucket policy that will restrict the "origin" bucket to only accept SSL connections.

Check out test/terraform_aws_s3_example_test.go to see how you can write
automated tests for this module.

Note that the S3 Buckets in this module will not contain any actual objects/files after creation; they will only contain a
versioning and logging configuration, as well as tags. For slightly more complicated, real-world examples of Terraform modules (with
other AWS services), see terraform-http-example and
terraform-ssh-example.

WARNING: This module and the automated tests for it deploy real resources into your AWS account which can cost you
money. The resources are all part of the AWS Free Tier, so if you haven't used that up,
it should be free, but you are completely responsible for all AWS charges.

Running this module manually

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Set the AWS region you want to use as the environment variable AWS_DEFAULT_REGION.
  4. Install Terraform and make sure it's on your PATH.
  5. Run terraform init.
  6. Run terraform apply.
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. cd test
  6. dep ensure
  7. go test -v -run TestTerraformAwsS3Example

Overview (`examples/terraform-aws-ssm-example/README.md`)

Terraform AWS SSM Example

This folder contains a simple Terraform module that deploys an instance in AWS
and registers it in the AWS SSM Catalog to demonstrate how you can use Terratest to write automated tests for your AWS Terraform code.

Check out test/terraform_aws_ssm_example_test.go to see how
you can write automated tests for this module.

WARNING: This module and the automated tests for it deploy real resources into your AWS account which can cost you
money. The resources are all part of the AWS Free Tier, so if you haven't used that up,
it should be free, but you are completely responsible for all AWS charges.

Running this module manually

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Run terraform init.
  5. Run terraform apply.
  6. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. cd test
  6. go test -v -run TestTerraformAwsSsmExample

Overview (`examples/terraform-backend-example/README.md`)

Terraform Backend Example

This folder contains a simple Terraform module that demonstrates how you can use Terratest to configure a Terraform
Backend
at test time. This module doesn't really do anything other than set
up S3 as a backend, and allow Terratest to fill in that backend's configuration.

Check out test/terraform_backend_example_test.go to see how you can write
automated tests for this module.

WARNING: This module and the automated tests for it deploy real resources into your AWS account which can cost you
money. The resources are all part of the AWS Free Tier, so if you haven't used that up,
it should be free, but you are completely responsible for all AWS charges.

Running this module manually

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Set the AWS region you want to use as the environment variable AWS_DEFAULT_REGION.
  4. Install Terraform and make sure it's on your PATH.
  5. Run terraform init.
  6. Run terraform apply.
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. cd test
  6. dep ensure
  7. go test -v -run TestTerraformBackendExample

Overview (`examples/terraform-basic-example/README.md`)

Terraform Basic Example

This folder contains a very simple Terraform module to demonstrate how you can use Terratest to write automated tests
for your Terraform code. This module takes in an input variable called example, renders it using a template_file
data source, and outputs the result in an output variable called example.

Check out test/terraform_basic_example_test.go to see how you can write
automated tests for this simple module.

Note that this module doesn't do anything useful; it's just here to demonstrate the simplest usage pattern for
Terratest. For a slightly more complicated, real-world example of a Terraform module and the corresponding tests, see
terraform-aws-example.

Running this module manually

  1. Install Terraform and make sure it's on your PATH.
  2. Run terraform init.
  3. Run terraform apply.
  4. When you're done, run terraform destroy.

Running automated tests against this module

  1. Install Terraform and make sure it's on your PATH.
  2. Install Golang and make sure this code is checked out into your GOPATH.
  3. cd test
  4. dep ensure
  5. go test -v -run TestTerraformBasicExample

Overview (`examples/terraform-gcp-example/README.md`)

Terraform GCP Example

This folder contains a simple Terraform module that deploys resources in GCP to demonstrate
how you can use Terratest to write automated tests for your GCP Terraform code. This module deploys a Compute
Instance
and gives that Instance a Name with the value specified in the
instance_name variable. It also creates a Cloud Storage Bucket using the bucket_name and bucket_location variables.

Check out test/terraform_gcp_example_test.go to see how you can write
automated tests for this module.

Note that the Compute Instance in this module doesn't actually do anything; it just runs a Vanilla Ubuntu 16.04 Image for
demonstration purposes. For slightly more complicated, real-world examples of Terraform modules, see
terraform-http-example and terraform-ssh-example.

WARNING: This module and the automated tests for it deploy real resources into your GCP account which can cost you
money. The resources are all part of the GCP Free Tier, so if you haven't used that up,
it should be free, but you are completely responsible for all GCP charges.

Running this module manually

  1. Sign up for GCP.
  2. Configure your GCP credentials using one of the supported methods for GCP CLI
    tools
    .
  3. Install Terraform and make sure it's in your PATH.
  4. Ensure the desired Project ID is set: export GOOGLE_CLOUD_PROJECT=terratest-ABCXYZ.
  5. Run terraform init.
  6. Run terraform apply.
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for GCP.
  2. Configure your GCP credentials using the GCP CLI
    tools
    .
  3. Install Terraform and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. Set GOOGLE_CLOUD_PROJECT environment variable to your project name.
  6. cd test
  7. dep ensure
  8. go test -v -run TestTerraformGcpExample

Overview (`examples/terraform-gcp-hello-world-example/README.md`)

Terraform GCP "Hello, World" Example

This folder contains a simple Terraform module that deploys resources in GCP to demonstrate
how you can use Terratest to write automated tests for your GCP Terraform code. This module deploys a Compute
Instance
and gives that Instance a Name with the value specified in the
instance_name variable.

Check out test/terraform_gcp_hello_world_example_test.go to see how
you can write automated tests for this module.

Note that the Compute Instance in this module doesn't actually do anything; it just runs a Vanilla Ubuntu 18.04 Image for
demonstration purposes. For slightly more complicated, real-world examples of Terraform modules, see
terraform-http-example and terraform-ssh-example.

WARNING: This module and the automated tests for it deploy real resources into your GCP account which can cost you
money. The resources are all part of the GCP Free Tier, so if you haven't used that up,
it should be free, but you are completely responsible for all GCP charges.

Running this module manually

  1. Sign up for GCP.
  2. Configure your GCP credentials using one of the supported methods for GCP CLI
    tools
    .
  3. Install Terraform and make sure it's in your PATH.
  4. Ensure the desired Project ID is set: export GOOGLE_CLOUD_PROJECT=terratest-ABCXYZ.
  5. Run terraform init.
  6. Run terraform apply.
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for GCP.
  2. Configure your GCP credentials using the GCP CLI
    tools
    .
  3. Install Terraform and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. Set GOOGLE_CLOUD_PROJECT environment variable to your project name.
  6. cd test
  7. go test -v -run TestTerraformGcpHelloWorldExample

Overview (`examples/terraform-gcp-ig-example/README.md`)

Terraform GCP Managed Instance Group Example

This folder contains a simple Terraform configuration that deploys resources in GCP to demonstrate
how you can use Terratest to write automated tests for your GCP Terraform code. This module deploys an Instance Group.

Check out test/terraform_gcp_ig_example_test.go to see how you can write
automated tests for this module.

Note that the Instance Group in this module doesn't actually do anything; it just runs a cluster of vanilla Ubuntu 16.04
Images for demonstration purposes. For slightly more complicated, real-world examples of Terraform modules, see
terraform-http-example and terraform-ssh-example.

WARNING: This module and the automated tests for it deploy real resources into your GCP account which can cost you
money. By launching multiple Instances as part of an Instance Group, these resources may go beyond the GCP Free Tier. Naturally, you are completely responsible for all GCP charges.

Running this module manually

  1. Sign up for GCP.
  2. Configure your GCP credentials using one of the supported methods for GCP CLI
    tools
    .
  3. Install Terraform and make sure it's in your PATH.
  4. Ensure the desired Project ID is set: export GOOGLE_CLOUD_PROJECT=terratest-ABCXYZ.
  5. Run terraform init.
  6. Run terraform apply.
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for GCP.
  2. Configure your GCP credentials using the GCP CLI
    tools
    .
  3. Install Terraform and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. Set GOOGLE_CLOUD_PROJECT environment variable to your project name.
  6. cd test
  7. dep ensure
  8. go test -v -run TestTerraformGcpInstanceGroupExample

Overview (`examples/terraform-gcp-pubsub-example/README.md`)

Terraform GCP Pub/Sub Example

This folder contains a simple Terraform module that deploys resources in GCP to demonstrate
how you can use Terratest to write automated tests for your GCP Terraform code. This module deploys a Pub/Sub Topic and a Pub/Sub Subscription attached to that topic.

Check out test/gcp/terraform_gcp_pubsub_example_test.go to see how
you can write automated tests for this module.

WARNING: This module and the automated tests for it deploy real resources into your GCP account which can cost you
money. The resources are typically part of the GCP Free Tier, so if you haven't used that up,
it should be free, but you are completely responsible for all GCP charges.

Running this module manually

  1. Sign up for GCP.
  2. Configure your GCP credentials using one of the supported methods for GCP CLI
    tools
    .
  3. Install Terraform and make sure it's in your PATH.
  4. Ensure the desired Project ID is set: export GOOGLE_CLOUD_PROJECT=your-project-id.
  5. Run terraform init.
  6. Run terraform apply.
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for GCP.
  2. Configure your GCP credentials using the GCP CLI
    tools
    .
  3. Install Terraform and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. Set GOOGLE_CLOUD_PROJECT environment variable to your project name.
  6. cd test/gcp
  7. go test -v -tags=gcp -run TestTerraformGcpPubSubExample

Overview (`examples/terraform-hello-world-example/README.md`)

Terraform "Hello, World" Example

This folder contains the simplest possible Terraform moduleβ€”one that just outputs "Hello, World"β€”to demonstrate how you
can use Terratest to write automated tests for your Terraform code.

Check out test/terraform_hello_world_example_test.go to see how you can
write automated tests for this simple module.

Note that this module doesn't do anything useful; it's just here to demonstrate the simplest usage pattern for
Terratest. For a slightly more complicated example of a Terraform module and the corresponding tests, see
terraform-basic-example.

Running this module manually

  1. Install Terraform and make sure it's on your PATH.
  2. Run terraform init.
  3. Run terraform apply.
  4. When you're done, run terraform destroy.

Running automated tests against this module

  1. Install Terraform and make sure it's on your PATH.
  2. Install Golang and make sure this code is checked out into your GOPATH.
  3. cd test
  4. go test -v -run TestTerraformHelloWorldExample

Overview (`examples/terraform-http-example/README.md`)

Terraform HTTP Example

This folder contains a simple Terraform module that deploys resources in AWS to demonstrate
how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys an EC2
Instance
in the AWS region specified in the aws_region variable. The EC2 Instance runs
a simple web server that listens for HTTP requests on the port specified by the instance_port variable and returns
the text specified by the instance_text variable.

Check out test/terraform_http_example_test.go to see how you can write
automated tests for this module.

Note that the example in this module is still fairly simplified, as the "web server" we run just servers up a static
index.html, and not in a particularly production-ready manner! For a more complicated, real-world, end-to-end
example of a Terraform module and web server, see terraform-packer-example.

WARNING: This module and the automated tests for it deploy real resources into your AWS account which can cost you
money. The resources are all part of the AWS Free Tier, so if you haven't used that up,
it should be free, but you are completely responsible for all AWS charges.

Running this module manually

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Run terraform init.
  5. Run terraform apply.
  6. The instance_url output variable shows you the URL of the web server. Try opening it in your browser!
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. cd test
  6. dep ensure
  7. go test -v -run TestTerraformHttpExample

Overview (`examples/terraform-opa-example/README.md`)

Terraform OPA Example

This folder contains an OPA policy that validates that all module blocks use a
source that comes from the gruntwork-io GitHub org (the enforce_source.rego file).
To test this policy, we provided two Terraform modules, pass and fail, which will demonstrate how
OPA looks when run against a module that passes the checks, and one that fails the checks.

Check out test/terraform_opa_example_test.go to see how you can write automated
tests for this module.

Running this module manually

  1. Install OPA and make sure it's on your PATH.

  2. Install hcl2json and make sure it's on your PATH. We need this to convert
    the terraform source code to json as OPA currently doesn't support parsing HCL.

  3. Convert each terraform source code in the pass or fail folder to json by feeding it to hcl2json:

    text
    hcl2json pass/main.tf > pass/main.json
  4. Run each converted terraform json file against the OPA policy:

    text
    opa eval --fail \
      -i pass/main.json \
      -d policy/enforce_source.rego \
      'data.enforce_source.allow'

Running automated tests against this module

  1. Install OPA and make sure it's on your PATH.
  2. Install Golang.
  3. cd test
  4. go test -v -run TestOPAEvalTerraformModule

Using extra command line arguments

If you need to pass additional command line arguments to OPA eval, you can use the ExtraArgs field. These arguments are placed after the eval subcommand and before the standard arguments:

go
// For OPA eval flags (e.g., --v0-compatible for OPA v0.x compatibility)
opaOpts := &opa.EvalOptions{
    RulePath: "../examples/terraform-opa-example/policy/enforce_source.rego",
    FailMode: opa.FailUndefined,
    ExtraArgs: []string{"--v0-compatible"},
}

// For multiple eval subcommand flags
opaOpts := &opa.EvalOptions{
    RulePath: "../examples/terraform-opa-example/policy/enforce_source.rego",
    FailMode: opa.FailUndefined,
    ExtraArgs: []string{"--v0-compatible", "--format", "json"},
}

Overview (`examples/terraform-packer-example/README.md`)

Terraform Packer Example

This folder contains a Terraform module that deploys resources in AWS to demonstrate
how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys an EC2
Instance
in the AWS region specified in the aws_region variable. The EC2 Instance runs
the AMI specified via the ami_id variable. It is assumed that this is an AMI built using the Packer template in
packer-docker-example, which contains a simple Ruby web app. This module will
configure a User Data script to start the web app, configuring it to listen for HTTP requests on the port specified by
the instance_port variable and return the text specified by the instance_text variable.

Check out test/terraform_packer_example_test.go to see how you can write
automated tests for this module. Note that this is an end-to-end integration test that will build the AMI, deploy it
using Terraform, validate the web app is working, and then clean everything up. The test is broken down into "stages"
so that, when iterating locally, you can choose to skip any of the stages by setting an environment variable. For
example, if you've already built the AMI and don't want to rebuild it each time you re-run the test, you can set the
environment variable SKIP_build_ami=true.

WARNING: This module and the automated tests for it deploy real resources into your AWS account which can cost you
money. The resources are all part of the AWS Free Tier, so if you haven't used that up,
it should be free, but you are completely responsible for all AWS charges.

Running this module manually

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Install Packer and make sure it's on your PATH.
  5. Follow the instructions in packer-docker-example to build an AMI. Note down the
    AMI ID.
  6. Open variables.tf and set the ami_id variable to the ID of the AMI you just built.
  7. Run terraform init.
  8. Run terraform apply.
  9. The instance_url output variable shows you the URL of the web server. Try opening it in your browser!
  10. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Install Packer and make sure it's on your PATH.
  5. Install Golang and make sure this code is checked out into your GOPATH.
  6. cd test
  7. dep ensure
  8. go test -v -run TestTerraformPackerExample

Overview (`examples/terraform-redeploy-example/README.md`)

Terraform Redeploy Example

This folder contains a simple Terraform module that deploys resources in AWS to demonstrate
how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys an Auto Scaling
Group (ASG)
in the AWS region specified
in the aws_region variable and a Load Balancer to route traffic
across the ASG. Each EC2 Instance in the ASG runs a simple web server that listens for HTTP requests on the port
specified by the instance_port variable and returns the text specified by the instance_text variable. The ASG is
configured to support zero-downtime deployments, which is something we verify in the automated test.

Check out test/terraform_redeploy_example_test.go to see how you can write
automated tests for this module.

Note that the example in this module is still fairly simplified, as the "web server" we run just servers up a static
index.html, and not in a particularly production-ready manner! For a more complicated, real-world, end-to-end
example of a Terraform module and web server, see terraform-packer-example.

WARNING: This module and the automated tests for it deploy real resources into your AWS account which can cost you
money. The resources are all part of the AWS Free Tier, so if you haven't used that up,
it should be free, but you are completely responsible for all AWS charges.

Running this module manually

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Run terraform init.
  5. Run terraform apply.
  6. The url output variable shows you the URL of the load balancer. Try opening it in your browser!
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. cd test
  6. dep ensure
  7. go test -v -run TestTerraformRedeployExample

Overview (`examples/terraform-remote-exec-example/README.md`)

Terraform remote-exec example

This folder contains a simple Terraform module that deploys resources in AWS to demonstrate
how you can use Terratest to test modules which use remote-exec, files, and other ssh-based
provisioners.

Check out test/terraform_remote_exec_example_test.go to see how you can write
automated tests for this module.

WARNING: This module and the automated tests for it deploy real resources into your AWS account which can cost you
money. The resources are all part of the AWS Free Tier, so if you haven't used that up,
it should be free, but you are completely responsible for all AWS charges.

Running this module manually

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Run terraform init.
  5. Run terraform apply.
  6. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. cd test
  6. dep ensure
  7. go test -v -run TestTerraformRemoteExecExample

Overview (`examples/terraform-ssh-certificate-example/README.md`)

Terraform SSH Password Example

This folder contains a simple Terraform module that deploys resources in AWS to demonstrate
how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys an EC2
Instance
with a public IP in the AWS region specified in the aws_region variable. The
EC2 Instance allows SSH requests on the port specified by the ssh_port variable, and is configured with a user data
script so that it will authentication with ssh certificate.

Please note that the Terraform deployment outlined in
the example directory for this test will expect a default VPC to exist in
the target region for deployments to go into.

If this default VPC has been deleted from your AWS account, it can be recreated with the following command:

shell
$ aws ec2 create-default-vpc --region eu-west-2
{
    "Vpc": {
        "CidrBlock": "172.31.0.0/16",
        "InstanceTenancy": "default",
        "IsDefault": true,
        "State": "pending",
        ...

Check out test/terraform_ssh_password_example_test.go to see how you
can write automated tests for this module.

Note that the example in this module is still fairly simplified, as the EC2 Instance doesn't do a whole lot! For a more
complicated, real-world, end-to-end example of a Terraform module and web server, see
terraform-packer-example.

WARNING: This module and the automated tests for it deploy real resources into your AWS account which can cost you
money. The resources are all part of the AWS Free Tier, so if you haven't used that up,
it should be free, but you are completely responsible for all AWS charges.

Running this module manually

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Run terraform init.
  5. Run terraform apply.
  6. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. cd test
  6. dep ensure
  7. go test -v -run TestTerraformSshCertificateExample

Overview (`examples/terraform-ssh-example/README.md`)

Terraform SSH Example

This folder contains a simple Terraform module that deploys resources in AWS to demonstrate
how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys two EC2
Instances
, one with a public IP, one with a private IP, in the AWS region specified in
the aws_region variable. The EC2 Instances allow SSH requests on the port specified by the ssh_port variable.

Check out test/terraform_ssh_example_test.go to see how you can write
automated tests for this module.

Note that the example in this module is still fairly simplified, as the EC2 Instance doesn't do a whole lot! For a more
complicated, real-world, end-to-end example of a Terraform module and web server, see
terraform-packer-example.

WARNING: This module and the automated tests for it deploy real resources into your AWS account which can cost you
money. The resources are all part of the AWS Free Tier, so if you haven't used that up,
it should be free, but you are completely responsible for all AWS charges.

Running this module manually

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Run terraform init.
  5. Run terraform apply.
  6. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. cd test
  6. dep ensure
  7. go test -v -run TestTerraformSshExample

Overview (`examples/terraform-ssh-password-example/README.md`)

Terraform SSH Password Example

This folder contains a simple Terraform module that deploys resources in AWS to demonstrate
how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys an EC2
Instance
with a public IP in the AWS region specified in the aws_region variable. The
EC2 Instance allows SSH requests on the port specified by the ssh_port variable, and is configured with a user data
script so that it will accept passwords for authentication.

Please note that the Terraform deployment outlined in
the example directory for this test will expect a default VPC to exist in
the target region for deployments to go into.

If this default VPC has been deleted from your AWS account, it can be recreated with the following command:

shell
$ aws ec2 create-default-vpc --region eu-west-2
{
    "Vpc": {
        "CidrBlock": "172.31.0.0/16",
        "InstanceTenancy": "default",
        "IsDefault": true,
        "State": "pending",
        ...

Check out test/terraform_ssh_password_example_test.go to see how you
can write automated tests for this module.

Note that the example in this module is still fairly simplified, as the EC2 Instance doesn't do a whole lot! For a more
complicated, real-world, end-to-end example of a Terraform module and web server, see
terraform-packer-example.

WARNING: This module and the automated tests for it deploy real resources into your AWS account which can cost you
money. The resources are all part of the AWS Free Tier, so if you haven't used that up,
it should be free, but you are completely responsible for all AWS charges.

Running this module manually

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Run terraform init.
  5. Run terraform apply.
  6. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for AWS.
  2. Configure your AWS credentials using one of the supported methods for AWS CLI
    tools
    , such as setting the
    AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables. If you're using the ~/.aws/config file for profiles then export AWS_SDK_LOAD_CONFIG as "True".
  3. Install Terraform and make sure it's on your PATH.
  4. Install Golang and make sure this code is checked out into your GOPATH.
  5. cd test
  6. dep ensure
  7. go test -v -run TestTerraformSshPasswordExample

Overview (`examples/terragrunt-example/README.md`)

Terragrunt Example

This folder contains a single Terragrunt unit demonstrating how to test it using Terratest's terraform package
with TerraformBinary: "terragrunt".

Check out modules/terragrunt/terragrunt_example_test.go to see how you can write automated tests
for this module.

For testing a stack of Terragrunt units with dependencies (using --all commands), see
terragrunt-multi-module-example.

Running this module manually

  1. Install Terraform and make sure it's on your PATH.
  2. Install Terragrunt and make sure it's on your PATH.
  3. Run terragrunt apply.
  4. When you're done, run terragrunt destroy.

Running automated tests against this module

  1. Install Terraform and make sure it's on your PATH.
  2. Install Terragrunt and make sure it's on your PATH.
  3. Install Golang and make sure this code is checked out into your GOPATH.
  4. cd test
  5. go test -v -run TestTerragruntExample

Overview (`examples/terragrunt-multi-module-example/README.md`)

Terragrunt Multi-Module Example

This folder contains a Terragrunt configuration with multiple modules that have dependencies (VPC β†’ Database β†’ App),
demonstrating how to use Terratest's terragrunt package to test stack configurations.

Check out modules/terragrunt/terragrunt_example_test.go to see how you can write automated tests
for this configuration using ApplyAll and DestroyAll.

Structure

text
.
β”œβ”€β”€ modules/           # Terraform modules
β”‚   β”œβ”€β”€ vpc/
β”‚   β”œβ”€β”€ database/     # Depends on VPC
β”‚   └── app/          # Depends on VPC and Database
└── live/             # Terragrunt configurations
    β”œβ”€β”€ vpc/
    β”œβ”€β”€ database/
    └── app/

Running this module manually

  1. Install Terraform and Terragrunt.
  2. cd live
  3. Run terragrunt apply --all.
  4. When you're done, run terragrunt destroy --all.

Running automated tests against this module

  1. Install Terraform and Terragrunt.
  2. Install Golang and make sure this code is checked out into your GOPATH.
  3. cd test
  4. go test -v -run TestTerragruntMultiModuleExample

Overview (`modules/terragrunt/README.md`)

Terragrunt Module

Testing library for Terragrunt configurations in Go. Provides helpers for running Terragrunt commands for single units, across multiple modules (run-all), and stack-based workflows.

Requirements

  • Terragrunt binary in PATH
  • OpenTofu or Terraform binary in PATH (Terragrunt is a wrapper and requires one of these)

To specify which binary to use (terraform vs opentofu):

go
// Option 1: Via environment variable
options := &terragrunt.Options{
    TerragruntDir: "/path/to/config",
    EnvVars: map[string]string{
        "TERRAGRUNT_TFPATH": "/usr/local/bin/tofu",  // or "TG_TF_PATH"
    },
}

// Option 2: Via command-line flag
options := &terragrunt.Options{
    TerragruntDir:  "/path/to/config",
    TerragruntArgs: []string{"--tf-path", "/usr/local/bin/tofu"},
}

Quick Start

Single Unit

go
import (
    "testing"
    "github.com/gruntwork-io/terratest/modules/terragrunt/v2"
    "github.com/stretchr/testify/assert"
)

func TestSingleUnit(t *testing.T) {
    t.Parallel()

    ctx := t.Context()

    options := &terragrunt.Options{
        TerragruntDir: "../path/to/terragrunt/unit",
    }

    defer terragrunt.DestroyContext(t, ctx, options)
    terragrunt.InitAndApplyContext(t, ctx, options)

    // Get a specific output as JSON
    vpcOutput := terragrunt.OutputJSONContext(t, ctx, options, "vpc_id")
    assert.Contains(t, vpcOutput, "vpc-")
}

Multiple Modules (--all)

go
func TestTerragruntApply(t *testing.T) {
    t.Parallel()

    ctx := t.Context()

    options := &terragrunt.Options{
        TerragruntDir: "../path/to/terragrunt/config",
    }

    defer terragrunt.DestroyAllContext(t, ctx, options)
    terragrunt.ApplyAllContext(t, ctx, options)
}

Key Concepts

Options Struct

The Options struct has two distinct parts:

  1. Test Framework Configuration (NOT passed to terragrunt CLI):

    • TerragruntDir - where to run terragrunt (required)
    • TerragruntBinary - binary name (default: "terragrunt")
    • EnvVars - environment variables
    • Logger - custom logger for output
    • MaxRetries, TimeBetweenRetries - retry settings
    • RetryableTerraformErrors - map of error patterns to retry messages
    • WarningsAsErrors - map of warning patterns to treat as errors
    • BackendConfig - backend configuration passed to init
    • PluginDir - plugin directory passed to init
    • Stdin - stdin reader for commands
  2. Command-Line Arguments (passed to terragrunt):

    • TerragruntArgs - global terragrunt flags (e.g., --log-level, --no-color)
    • TerraformArgs - command-specific OpenTofu/Terraform flags (e.g., -upgrade)

Error-Returning Variants (E-suffix)

Every function has an E-suffix variant that returns an error instead of calling t.Fatal on failure. For example:

  • ApplyContext(t, ctx, options) calls t.Fatal on error
  • ApplyContextE(t, ctx, options) returns (string, error) for custom error handling

Use E variants when you need to test error cases or handle failures gracefully:

go
_, err := terragrunt.ApplyContextE(t, t.Context(), options)
require.Error(t, err)

TerragruntArgs vs TerraformArgs

Arguments are passed in this order:

text
terragrunt [TerragruntArgs] --non-interactive run -- <command> [TerraformArgs]

Example:

go
options := &terragrunt.Options{
    TerragruntDir:  "/path/to/config",
    TerragruntArgs: []string{"--log-level", "error"},  // Global TG flags
    TerraformArgs:  []string{"-upgrade"},              // OpenTofu/Terraform flags
}
// Executes: terragrunt --log-level error --non-interactive run -- init -upgrade

Functions

Single-Unit Commands

Run terragrunt commands against a single unit (one terragrunt.hcl directory):

  • InitContext(t, ctx, options) - Initialize configuration
  • ApplyContext(t, ctx, options) - Apply changes
  • DestroyContext(t, ctx, options) - Destroy resources
  • PlanContext(t, ctx, options) - Generate and show execution plan
  • PlanExitCodeContext(t, ctx, options) - Plan and return exit code (0=no changes, 2=changes, other=error)
  • ValidateContext(t, ctx, options) - Validate configuration
  • OutputJSONContext(t, ctx, options, key) - Get output as JSON (specific key or all outputs)

Convenience Wrappers

Run init + command in a single call:

  • InitAndApplyContext(t, ctx, options) - Init then apply
  • InitAndPlanContext(t, ctx, options) - Init then plan
  • InitAndValidateContext(t, ctx, options) - Init then validate

Run Command

  • RunContext(t, ctx, options, tgArgs, tfArgs) - Run any OpenTofu/Terraform command via terragrunt run [tgArgs...] -- [tfArgs...]

The -- separator disambiguates Terragrunt flags (like --all) from OpenTofu/Terraform flags. The OpenTofu/Terraform command (e.g. "apply") should be the first element of tfArgs.

Run --all Commands

Work with implicit stacks (multiple units in a directory):

  • ApplyAllContext(t, ctx, options) - Apply all modules with dependencies
  • DestroyAllContext(t, ctx, options) - Destroy all modules with dependencies
  • PlanAllExitCodeContext(t, ctx, options) - Plan all and return exit code (0=no changes, 2=changes, other=error)
  • ValidateAllContext(t, ctx, options) - Validate all modules
  • RunAllContext(t, ctx, options, command) - Deprecated: use RunContext with --all in tgArgs instead. Run any OpenTofu/Terraform command with --all flag
  • OutputAllJSONContext(t, ctx, options) - Get all outputs as raw JSON string (note: returns separate JSON objects per module)

HCL Commands

Terragrunt HCL tooling commands:

  • FormatAllContext(t, ctx, options) - Format all terragrunt.hcl files (terragrunt hcl format)
  • HclValidateContext(t, ctx, options) - Validate terragrunt.hcl syntax and configuration (terragrunt hcl validate)

Configuration Commands

  • RenderContext(t, ctx, options) - Render resolved terragrunt configuration as HCL
  • RenderJSONContext(t, ctx, options) - Render resolved terragrunt configuration as JSON
  • GraphContext(t, ctx, options) - Output dependency graph in DOT format

Stack Commands

Work with explicit stacks (a directory with a terragrunt.stack.hcl file):

  • StackGenerateContext(t, ctx, options) - Generate stack from stack.hcl
  • StackRunContext(t, ctx, options) - Run command on generated stack
  • StackCleanContext(t, ctx, options) - Remove .terragrunt-stack directory
  • StackOutputContext(t, ctx, options, key) - Get stack output value
  • StackOutputJSONContext(t, ctx, options, key) - Get stack output as JSON
  • StackOutputAllContext(t, ctx, options) - Get all stack outputs as map
  • StackOutputListAllContext(t, ctx, options) - Get list of all output variable names

Examples

See the examples directory for complete working examples:

Testing with Dependencies

go
func TestStack(t *testing.T) {
    t.Parallel()

    ctx := t.Context()

    options := &terragrunt.Options{
        TerragruntDir: "../live/prod",
    }

    // Apply respects dependency order
    terragrunt.ApplyAllContext(t, ctx, options)
    defer terragrunt.DestroyAllContext(t, ctx, options)

    // Verify infrastructure
    // ... your assertions here
}

Using Custom Arguments

go
func TestWithCustomArgs(t *testing.T) {
    t.Parallel()

    options := &terragrunt.Options{
        TerragruntDir:  "../config",
        TerragruntArgs: []string{"--log-level", "error", "--no-color"},
        TerraformArgs:  []string{"-upgrade"},
    }

    terragrunt.InitContext(t, t.Context(), options)
}

Testing Stack Outputs

go
func TestStackOutput(t *testing.T) {
    t.Parallel()

    ctx := t.Context()

    options := &terragrunt.Options{
        TerragruntDir: "../stack",
    }

    applyOpts := &terragrunt.Options{
        TerragruntDir: "../stack",
        TerraformArgs: []string{"apply"},
    }
    destroyOpts := &terragrunt.Options{
        TerragruntDir: "../stack",
        TerraformArgs: []string{"destroy"},
    }

    terragrunt.StackRunContext(t, ctx, applyOpts)
    defer terragrunt.StackRunContext(t, ctx, destroyOpts)

    // Get specific output
    vpcID := terragrunt.StackOutputContext(t, ctx, options, "vpc_id")
    assert.NotEmpty(t, vpcID)

    // Get all outputs
    outputs := terragrunt.StackOutputAllContext(t, ctx, options)
    assert.Contains(t, outputs, "vpc_id")
}

Checking Plan Exit Code

go
func TestInfrastructureUpToDate(t *testing.T) {
    t.Parallel()

    ctx := t.Context()

    options := &terragrunt.Options{
        TerragruntDir: "../prod",
    }

    // First apply
    terragrunt.ApplyAllContext(t, ctx, options)
    defer terragrunt.DestroyAllContext(t, ctx, options)

    // Plan should show no changes (exit code 0)
    exitCode := terragrunt.PlanAllExitCodeContext(t, ctx, options)
    assert.Equal(t, 0, exitCode, "No changes expected")
}

Using Run for Flexibility

go
func TestCustomCommand(t *testing.T) {
    t.Parallel()

    ctx := t.Context()

    options := &terragrunt.Options{
        TerragruntDir: "../modules",
    }

    // Run any OpenTofu/Terraform command with --all
    terragrunt.RunContext(t, ctx, options, []string{"--all"}, []string{"refresh"})

    // Verify state is current
    output := terragrunt.RunContext(t, ctx, options, []string{"--all"}, []string{"show"})
    assert.Contains(t, output, "expected-resource")
}

Validating Stack Output Keys

go
func TestStackOutputKeys(t *testing.T) {
    t.Parallel()

    ctx := t.Context()

    options := &terragrunt.Options{
        TerragruntDir: "../stack",
    }

    applyOpts := &terragrunt.Options{
        TerragruntDir: "../stack",
        TerraformArgs: []string{"apply"},
    }
    destroyOpts := &terragrunt.Options{
        TerragruntDir: "../stack",
        TerraformArgs: []string{"destroy"},
    }

    terragrunt.StackRunContext(t, ctx, applyOpts)
    defer terragrunt.StackRunContext(t, ctx, destroyOpts)

    // Get list of all output keys
    keys := terragrunt.StackOutputListAllContext(t, ctx, options)

    // Verify required outputs exist
    assert.Contains(t, keys, "vpc_id")
    assert.Contains(t, keys, "subnet_ids")
}

Using Filters (Terragrunt v0.97.0+)

go
options := &terragrunt.Options{
    TerragruntDir:  "../live/prod",
    TerragruntArgs: []string{"--filter", "{./vpc}"},  // Only apply vpc
}
terragrunt.ApplyAllContext(t, t.Context(), options)

Not Supported

This module does NOT have dedicated helpers for:

  • import, refresh, show, state, test commands
  • backend, exec, catalog, scaffold commands
  • Discovery commands (find, list)
  • Configuration commands (info)

For these commands, use RunContext / RunContextE or run terragrunt directly via the shell module.

Compatibility

Tested with Terragrunt v1.0.x. Earlier v0.x versions may work but are not guaranteed.

Migration from terraform Module

The following functions were previously in the terraform module and have been moved here. The deprecated versions have been removed from the terraform module.

Removed (terraform module) Replacement (terragrunt module)
TgApplyAll / TgApplyAllE ApplyAll / ApplyAllE
TgDestroyAll / TgDestroyAllE DestroyAll / DestroyAllE
TgPlanAllExitCode / TgPlanAllExitCodeE PlanAllExitCode / PlanAllExitCodeE
ValidateInputs / ValidateInputsE HclValidate / HclValidateE

Note: ValidateInputs specifically checked input alignment. For equivalent behavior, pass TerraformArgs: []string{"--inputs"} to HclValidate.

More Info


Overview (`test-docker-images/gruntwork-amazon-linux-test/README.md`)

Gruntwork Amazon-Linux-Test Docker Image

The purpose of this Docker image is to provide a pre-built Amazon Linux Docker image that has most of the libraries
we would expect to be installed on the Amazon Linux AMI that would run in AWS. For example, we'd expect sudo in AWS,
but it doesn't exist by default in Docker amazonlinux:latest.

Building and Pushing a New Docker Image to Docker Hub

This Docker image should publicly accessible via Docker Hub at https://hub.docker.com/r/gruntwork/amazonlinux-test/. To build and
upload it:

  1. docker build -t gruntwork/amazon-linux-test:2017.12 .
  2. docker push gruntwork/amazon-linux-test:2017.12

Overview (`test-docker-images/gruntwork-centos-test/README.md`)

Gruntwork CentOS-Test Docker Image

The purpose of this Docker image is to provide a pre-built CentOS 7 Docker image that has most of the libraries
we would expect to be installed on the CentOS 7 AMI that would run in AWS. For example, we'd expect sudo in AWS, but it
doesn't exist by default in Docker centos:7. It also aims to allow systemd
to run, which, in turn, allows you to run one or more services as systemd units.

Building and Pushing a New Docker Image to Docker Hub

This Docker image should publicly accessible via Docker Hub at https://hub.docker.com/r/gruntwork/centos-test/. To build and
upload it:

  1. docker build -t gruntwork/centos-test:7 .
  2. docker push gruntwork/centos-test:7

Running this Docker Image

Running systemd require elevated privileges for the Docker container, so you should run this Docker image with at least
the following options:

text
docker run -d --privileged -v /sys/fs/cgroup:/sys/fs/cgroup:ro gruntwork/zookeeper-centos-test:latest

Note that:

  • We do not specify a run command like /bin/bash because we need to retain the Docker Image's default run command of
    /usr/sbin/init. This makes systemd Process ID 1, which allows it to spawn an arbitrary number of other services
  • You can then connect to the Docker container with docker exec -it <container-id> /bin/bash.
  • The container must be --privileged because it needs to break out of the typical cgroups to run an init system like systemd.
  • You must "hook in" to a Linux host's cgroups to allow each service to run in its own cgroup. This works even on Docker
    for Mac and Docker for Windows because those systems still use a Linux VM to run the Docker engine and do not expose
    the entire host system (e.g. your Mac laptop) for docker volume mounting.

Overview (`test-docker-images/gruntwork-ubuntu-test/README.md`)

Gruntwork Ubuntu-Test Docker Image

The purpose of this Docker image is to provide a pre-built Ubuntu 18.04 Docker image that has most of the libraries
we would expect to be installed on the Ubuntu 18.04 AMI that would run in AWS. For example, we'd expect curl in AWS,
but it doesn't exist by default in Docker ubuntu:18.04.

Building and Pushing a New Docker Image to Docker Hub

This Docker image should publicly accessible via Docker Hub at https://hub.docker.com/r/gruntwork/ubuntu-test/. To build and
upload it:

  1. docker build -t gruntwork/ubuntu-test:18.04 .
  2. docker push gruntwork/ubuntu-test:18.04

Overview (`test-docker-images/moto/README.md`)

Moto

This docker image runs moto as a service. We will use Moto as a local service that
accepts AWS API calls and returns valid API responses. Moto can be used with any AWS SDK, including the awscli[].

This Docker image is expected to run alongside a cluster of docker containers to represent a "local AWS".

About Moto

Moto was originally written as a way to mock out the Python boto library, the official
AWS SDK for Python. It was motivated by the need to write automated tests for boto. But since the AWS API cannot run
"locally", Moto was written to mock the responses of the AWS API.

Moto works by receiving AWS API requests across a wide variety of AWS services, including most of EC2. It will then store
the requested AWS resource in memory and allow you to query that AWS resource using standard AWS API calls. There is
no actual VM created, or other actual resource created.

Motivation

As part of writing Unit Tests with Terratest, we need a way to run our services in a Docker
container. But this presents a new challenge: Almost all our cluster-based setups query the AWS APIs to obtain metadata
about the EC2 Instance on which they're running. How can we simulate these API calls in a local environment? Moto seems
to meet this use case perfectly.

Usage

Building and Pushing a New Docker Image to Docker Hub

This Docker image should publicly accessible via Docker Hub at https://hub.docker.com/r/gruntwork/moto/. To build and
upload it:

  1. docker build -t gruntwork/moto:v1 .
  2. docker push gruntwork/moto:v1

Run a Docker container

text
docker run -p 5000:5000 gruntwork/moto moto_server ec2 --host 0.0.0.0

This runs the moto service as a RESTful API, specially for the AWS EC2 API with support for accepting connections from
any IP address (versus just from localhost). For additional information:

Make AWS API calls against Moto

Because Moto exposes an API that is intended to be identical to the official AWS API, you can use any any AWS SDK against
it, including the AWS CLI, AWS SDK for Go, curl calls, or any other AWS API library. The only difference is that you
must explicitly set the "endpoint uRL" to point to the Moto server instead of the official AWS API. Changing this setting
will be different for each AWS SDK, but for the AWSCLI, you can simplify specify the --endpoint-url argument as follows:

text
aws --region "us-west-2" --endpoint-url="http://localhost:5000" ec2 run-instances --image-id ami-abc12345 --tag-specifications 'ResourceType=instance,Tags=[{Key=ServerGroupName,Value=josh}]'

Note that Moto supports all AWS regions, and will automatically create a VPC with default subnets for you!

Other Solutions Considered

LocalStack

LocalStack is a (coming soon) commercial service intending to offer "local AWS as a service".
It is based on the open source localstack project.

Local stack seems to offer a small set of advantages over
Moto, including throwing periodic errors to simulate a real-world cloud environment. But Localstack doesn't implement
100% of the APIs implemented by Moto (including EC2, the most important one for us!), its docker image is ~500 MB, it
doesn't appear to be an active commercial entity, and Moto supports a RESTful API already.

For these reasons, Moto is the better fit for our needs.


Overview (`examples/azure/terraform-azure-aci-example/README.md`)

Terraform Azure Example

This folder contains a Terraform module that deploys resources in Azure to demonstrate
how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys an Azure Container Instance.

Check out test/azure/terraform_azure_aci_example_test.go to see how you can write
automated tests for this module.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you
money. The resources are all part of the Azure Free Account, so if you haven't used that up,
it should be free, but you are completely responsible for all Azure charges.

Running this module manually

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your Terratest Go test environment
  5. cd test/azure
  6. go build terraform_azure_aci_example_test.go
  7. go test -v -timeout 60m -tags azure -run TestTerraformAzureACIExample

Overview (`examples/azure/terraform-azure-acr-example/README.md`)

Terraform Azure Container Registry Example

This folder contains a Terraform module that deploys resources in Azure to demonstrate
how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys an Azure Container Registry.

Check out test/azure/terraform_azure_acr_example_test.go to see how you can write
automated tests for this module.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you
money. The resources are all part of the Azure Free Account, so if you haven't used that up,
it should be free, but you are completely responsible for all Azure charges.

Running this module manually

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your Terratest Go test environment
  5. cd test/azure
  6. go build terraform_azure_acr_example_test.go
  7. go test -v -timeout 60m -tags azure -run TestTerraformAzureACRExample

Overview (`examples/azure/terraform-azure-actiongroup-example/README.md`)

Terraform Azure Action Group Example

This folder contains a Terraform module that deploys an Azure Action Group in Azure to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code.

Check out test/azure/terraform_azure_actiongroup_example_test.go to see how you can write automated tests for this module and validate the configuration of the parameters and options.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you money.

Prerequisite: Setup Azure CLI access

  1. Sign up for Azure.
  2. Install Azure CLI
  3. Install Terraform and make sure it's on your PATH.
  4. Login to Azure on the CLI with az login or az login --use-device, and then configure the CLI.

Running this module manually

  1. Create Service Principal then set the value to the environment variables.
  2. Run terraform init.
  3. Run terraform apply.
  4. Log into Azure to validate resource was created.
  5. When you're done, run terraform destroy.

Example

bash
$ az login 
$ export ARM_SUBSCRIPTION_ID={YOUR_SUBSCRIPTION_ID} 
$ az ad sp create-for-rbac
$ export TF_VAR_client_id={YOUR_SERVICE_PRINCIPAL_APP_ID}
$ export TF_VAR_client_secret={YOUR_SERVICE_PRINCIPAL_PASSWORD}
$ terraform init
$ terraform apply
$ terraform destroy

Running automated tests against this module

  1. Create Service Principal then set the value to the environment variables.
  2. Install Golang version 1.13+ required.
  3. cd test/azure
  4. go test -v -timeout 60m -tags azure -run TestTerraformAzureActionGroupExample

Example

bash
$ az login 
$ export ARM_SUBSCRIPTION_ID={YOUR_SUBSCRIPTION_ID} 
$ export TF_VAR_client_id={YOUR_SERVICE_PRINCIPAL_APP_ID}
$ export TF_VAR_client_secret={YOUR_SERVICE_PRINCIPAL_PASSWORD}
$ cd test/azure
$ go test -v -timeout 60m -tags azure -run TestTerraformAzureActionGroupExample

Overview (`examples/azure/terraform-azure-aks-example/README.md`)

Terraform Azure AKS Example

This folder contains a Terraform module that deploys a basic AKS cluster in Azure to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code.

This module deploys Azure Kubernetes Service, then deploys nginx by a kubernetes yaml file with a Public IP Address using the Service resource.

Check out test/azure/terraform_azure_aks_example_test.go to see how you can write automated tests for this module and validate the configuration of the parameters and options.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you money.

Prerequisite: Setup Azure CLI access

  1. Sign up for Azure.
  2. Install Azure CLI
  3. Install Terraform and make sure it's on your PATH.
  4. Install kubectl and make sure it's on your PATH.
  5. Login to Azure on the CLI with az login or az login --use-device, and then configure the CLI.

Running this module manually

  1. Create Service Principal then set the value to the environment variables.
  2. Run terraform init
  3. Run terraform apply
  4. Apply nginx-deployment.yml
  5. Watch the service until Public IPAddress is assigned.
  6. Send http request to the Public IPAddress, make sure it returns 200.
  7. When you're done, run terraform destroy.

Example

bash
$ az login 
$ export ARM_SUBSCRIPTION_ID={YOUR_SUBSCRIPTION_ID} 
$ az ad sp create-for-rbac
$ export TF_VAR_client_id={YOUR_SERVICE_PRINCIPAL_APP_ID}
$ export TF_VAR_client_secret={YOUR_SERVICE_PRINCIPAL_PASSWORD}
$ terraform init
$ terraform apply
$ kubectl --kubeconfig ./kubeconfig -f ./nginx-deployment.yml
$ kubectl --kubeconfig ./kubeconfig get svc -w
// Open browser and access the Nginx Service IPAddress
$ terraform destroy

Running automated tests against this module

  1. Create Service Principal then set the value to the environment variables.
  2. Install Golang version 1.13+ required.
  3. cd test
  4. go test -v -timeout 60m -tags azure -run TestTerraformAzureAKS

Example

bash
$ az login 
$ export ARM_SUBSCRIPTION_ID={YOUR_SUBSCRIPTION_ID} 
$ export TF_VAR_client_id={YOUR_SERVICE_PRINCIPAL_APP_ID}
$ export TF_VAR_client_secret={YOUR_SERVICE_PRINCIPAL_PASSWORD}
$ cd test
$ go test -v -timeout 60m -tags azure -run TestTerraformAzureAKS

Overview (`examples/azure/terraform-azure-availabilityset-example/README.md`)

Terraform Azure Availability Set Example

This folder contains a simple Terraform module that deploys resources in Azure to demonstrate
how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys an Availability Set with one attached Virtual Machine.

  • An Availability Set that gives the module the following:
    • Availability Set with the name specified in the availability_set_name output variable.
    • Fault Domain Count with the value specified in the availability_set_fdc output variable.
  • A Virtual Machine that gives the Availability Set the following:

Check out test/azure/terraform_azure_availabilityset_example_test.go to see how you can write
automated tests for this module.

Note that the Availability Set and VM in this module don't actually do anything; it just runs the resources for
demonstration purposes.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you
money. The resources are all part of the Azure Free Account, so if you haven't used that up,
it should be free, but you are completely responsible for all Azure charges.

Running this module manually

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your Terratest Go test environment
  5. cd test/azure
  6. go build terraform_azure_availabilityset_example_test.go
  7. go test -v -run TestTerraformAzureAvailabilitySetExample

Overview (`examples/azure/terraform-azure-container-apps-example/README.md`)

Terraform Azure Container Apps Example

This folder contains a simple Terraform module that deploys resources in Azure to demonstrate
how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys two Azure Container Apps (one app and a job).

Check out test/azure/terraform_azure_container_apps_example_test.go to see how you can write automated tests for this module and validate the configuration of the parameters and options.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you money.

Running this module manually

  1. Sign up for Azure.
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH.
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your Terratest Go test environment
  5. cd test/azure
  6. go build terraform_azure_container_apps_example_test.go
  7. go test -v -timeout 60m -tags azure -run TestTerraformAzureContainerAppExample

Overview (`examples/azure/terraform-azure-cosmosdb-example/README.md`)

Terraform Azure CosmosDB Example

This folder contains a complete Terraform Cosmos DB module that deploys resources in Azure to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys the following resources:

Check out test/azure/terraform_azure_cosmosdb_example_test.go to see how you can write automated tests for this module and validate the configuration of the parameters and options.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you money.

Running this module manually

  1. Sign up for Azure.
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH.
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your Terratest Go test environment
  5. cd test/azure
  6. go build terraform_azure_cosmosdb_example_test.go
  7. go test -v -timeout 60m -tags azure -run TestTerraformAzureCosmosDBExample

Overview (`examples/azure/terraform-azure-datafactory-example/README.md`)

Terraform Azure Data Factory Example

This folder contains a Terraform module that deploys resources in Azure to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code.
This module deploys a Data Factory.

Check out test/azure/terraform_azure_datafactory_example_test.go to see how you can write automated tests for this module and validate the configuration of the parameters and options.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you money.

Running this module manually

  1. Sign up for Azure.
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH.
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your Terratest Go test environment
  5. cd test/azure
  6. go build terraform_azure_datafactory_example_test.go
  7. go test -v -timeout 60m -tags azure -run TestTerraformAzureDataFactoryExample

Overview (`examples/azure/terraform-azure-disk-example/README.md`)

Terraform Azure Disk Example

This folder contains a simple Terraform module that deploys resources in Azure to demonstrate
how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys an Azure managed disk.

Check out test/azure/terraform_azure_disk_example_test.go to see how you can write automated tests for this module.

Note that the resources deployed in this module don't actually do anything; it just runs the resources for demonstration purposes.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you money. The resources are all part of the Azure Free Account, so if you haven't used that up, it should be free, but you are completely responsible for all Azure charges.

Running this module manually

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy

Running automated tests against this module

  1. Sign up for Azure.

  2. Configure your Azure credentials using one of the supported methods for Azure CLI tools.

  3. Install Terraform and make sure it's on your PATH.

  4. Review environment variables.

  5. Install Golang and make sure this code is checked out into your GOPATH.

  6. cd test

  7. Make sure the azure-sdk-for-go versions match in /test/go.mod and in test/azure/terraform_azure_disk_example_test.go.

  8. go test -v -run TestTerraformAzureDiskExample


Overview (`examples/azure/terraform-azure-example/README.md`)

Terraform Azure Example

This folder contains a simple Terraform module that deploys resources in Azure to demonstrate
how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys a Virtual
Machine
and gives that VM a Name tag with the value specified in the
vm_name variable.

Check out test/azure/terraform_azure_example_test.go to see how you can write
automated tests for this module.

Note that the Virtual Machine in this module doesn't actually do anything; it just runs a Vanilla Ubuntu 16.04 image for
demonstration purposes. For slightly more complicated, real-world examples of Terraform modules, see
terraform-http-example and terraform-ssh-example.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you
money. The resources are all part of the Azure Free Account, so if you haven't used that up,
it should be free, but you are completely responsible for all Azure charges.

Running this module manually

  1. Sign up for Azure.
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
    .
  3. Install Terraform and make sure it's on your PATH.
  4. Run terraform init.
  5. Run terraform apply.
  6. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for Azure.
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
    .
  3. Install Terraform and make sure it's on your PATH.
  4. Review environment variables.
  5. Install Golang and make sure this code is checked out into your GOPATH.
  6. cd test
  7. Make sure the azure-sdk-for-go versions match in /test/go.mod and in test/azure/terraform_azure_example_test.go.
  8. go build terraform_azure_example_test.go
  9. go test -v -run TestTerraformAzureExample

Check Go Dependencies

Check that the github.com/Azure/azure-sdk-for-go version in your generated go.mod for this test matches the version in the terratest go.mod file.

This was tested with go1.14.1.

Check Azure-sdk-for-go version

Let's make sure go.mod includes the appropriate azure-sdk-for-go version:

go
require (
    ...
    github.com/Azure/azure-sdk-for-go v38.1.0+incompatible
    ...
)

We should check that test/azure/terraform_azure_example_test.go includes the corresponding azure-sdk-for-go package:

go
import (
    "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
    ...
)

If we make changes to either the go.mod or the go test file, we should make sure that the go build command works still.

powershell
go build terraform_azure_example_test.go

Review Environment Variables

As part of configuring terraform for Azure, we'll want to check that we have set the appropriate credentials and also that we set the environment variables on the testing host.

For non-commercial cloud deployments, set the "AZURE_ENVIRONMENT" environment variable to the appropriate cloud environment (this is used by the client_factory to set the correct azure endpoints):

bash
export ARM_CLIENT_ID=your_app_id
export ARM_CLIENT_SECRET=your_password
export ARM_SUBSCRIPTION_ID=your_subscription_id
export ARM_TENANT_ID=your_tenant_id

# AZURE_ENVIRONMENT is the name of the Azure environment to use. Set to one of the following:
export AZURE_ENVIRONMENT=AzureUSGovernmentCloud
export AZURE_ENVIRONMENT=AzureChinaCloud
export AZURE_ENVIRONMENT=AzureGermanCloud
export AZURE_ENVIRONMENT=AzurePublicCloud
export AZURE_ENVIRONMENT=AzureStackCloud

Note, in a Windows environment, these should be set as system environment variables. We can use a PowerShell console with administrative rights to update these environment variables:

powershell
[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_ID",$your_app_id,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable("ARM_CLIENT_SECRET",$your_password,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable("ARM_SUBSCRIPTION_ID",$your_subscription_id,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable("ARM_TENANT_ID",$your_tenant_id,[System.EnvironmentVariableTarget]::Machine)
[System.Environment]::SetEnvironmentVariable("AZURE_ENVIRONMENT",$your_azure_env,[System.EnvironmentVariableTarget]::Machine)

Overview (`examples/azure/terraform-azure-frontdoor-example/README.md`)

Terraform Azure Front Door Example

This folder contains a simple Terraform module that deploys resources in Azure to demonstrate
how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys an Azure Front Door.

Check out test/azure/terraform_azure_frontdoor_example_test.go to see how you can write automated tests for this module and validate the configuration of the parameters and options.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you money.

Running this module manually

  1. Sign up for Azure.
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH.
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your Terratest Go test environment
  5. cd test/azure
  6. go build terraform_azure_frontdoor_example_test.go
  7. go test -v -timeout 60m -tags azure -run TestTerraformAzureFrontDoorExample

Overview (`examples/azure/terraform-azure-functionapp-example/README.md`)

Terraform Azure Function App Example

This folder contains a Terraform module that deploys a Function App in Azure to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code.

This module deploys Azure Storage, Azure Function App, Azure Function App.

Check out test/azure/terraform_azure_functionapp_example_test.go to see how you can write automated tests for this module and validate the configuration of the parameters and options.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you
money. The resources are all part of the Azure Free Account, so if you haven't used that up,
it should be free, but you are completely responsible for all Azure charges.

Running this module manually

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your Terratest Go test environment
  5. cd test/azure
  6. go build terraform_azure_functionapp_example_test.go
  7. go test -v -run TestTerraformAzureFunctionAppExample

Overview (`examples/azure/terraform-azure-keyvault-example/README.md`)

Terraform Azure Keyvault Example

This folder contains a simple Terraform module that deploys resources in Azure to demonstrate
how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys a Key Vault with one secret, key, and certificate each.

  • A Key Vault that gives the module the following:
    • Secret with the value specified in the secret_name output variable.
    • Key with the value specified in the key_name output variable.
    • Certificate with the value specified in the certificate_name output variable.

Check out test/azure/terraform_azure_keyvault_example_test.go to see how you can write
automated tests for this module.

Note that the Key Vault in this module don't actually do anything; it just runs the resources for
demonstration purposes.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you
money. The resources are all part of the Azure Free Account, so if you haven't used that up,
it should be free, but you are completely responsible for all Azure charges.

Running this module manually

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your Terratest Go test environment
  5. cd test/azure
  6. go build terraform_azure_keyvault_example_test.go
  7. go test -v -run TestTerraformAzureKeyVaultExample

Overview (`examples/azure/terraform-azure-loadbalancer-example/README.md`)

Terraform Load Balancer Example

This folder contains a simple Terraform module that deploys resources in Azure to demonstrate
how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys two Load Balancers for Public and Private IP scenarios.

  • A Public Load Balancer that gives the module the following:

    • Load Balancer with the name specified in the lb_public_name and configuration in the lb_public_fe_config_name output variables.
  • A Private Load Balancer that gives the module the following:

    • Load Balancer with the name specified in the lb_private_name and static Frontend IP Configuration in the lb_private_fe_config_static_name output variables.
  • A Default Load Balancer that gives the module the following:

    • Load Balancer with the name specified in the lb_default_name and no Frontend configuration.
  • Networking that provides the following for the Load Balancer module with the following:

    • Virtual Network with the name specified in the vnet_name output variable.
    • Subnet with the name specified in the subnet_name output variable.
    • Public IP Address with the name specified in the public_address_name output variable.

Check out test/azure/terraform_azure_loadbalancer_example_test.go to see how you can write
automated tests for this module.

Note that the Load Balancers and their associated resources in this module don't actually do anything; they are created before running the tests, for demonstration purposes.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you money. The resources are all part of the Azure Free Account, so if you haven't used that up, it should be free, but you are completely responsible for all Azure charges.

Running this module manually

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your Terratest Go test environment
  5. cd test/azure
  6. go build terraform_azure_loadbalancer_example_test.go
  7. go test -v -run TestTerraformAzureLoadBalancerExample

Overview (`examples/azure/terraform-azure-loganalytics-example/README.md`)

Terraform Azure Log Analytics Example

This folder contains a Terraform module that deploys resources in Azure to demonstrate
how you can use TerraTest to write automated tests for your Azure Terraform code. This module deploys a Log Analytics Workspace.

  • A Log Analytics Workspace that gives the module the following:
    • Name with the value specified in the loganalytics_workspace_name output variable.
    • Sku with the value specified in the loganalytics_workspace_sku output variable.
    • RetentionPeriodInDays with the value specified in the loganalytics_workspace_retention output variable.

Check out test/azure/terraform_azure_loganalytics_example_test.go to see how you can write
automated tests for this module.

Note that the Log Analytics Workspace in this module don't actually do anything; it just runs the resources for
demonstration purposes.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you
money. The resources are all part of the Azure Free Account, so if you haven't used that up,
it should be free, but you are completely responsible for all Azure charges.

Running this module manually

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your TerraTest Go test environment
  5. cd test/azure
  6. go build terraform_azure_loganalytics_example_test.go
  7. go test -v -run TestTerraformAzureLogAnalyticsExample

Overview (`examples/azure/terraform-azure-monitor-example/README.md`)

Terraform Azure Monitor Example

This folder contains a simple Terraform module that deploys resources in Azure to demonstrate
how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys an Azure Storage Account and Azure Azure Key Vault with an Azure Monitor Diagnostic Setting.

Check out test/azure/terraform_azure_monitor_example_test.go to see how you can write
automated tests for this module.

Note that the resources deployed in this module don't actually do anything; it just runs the resources for
demonstration purposes.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you
money. The resources are all part of the Azure Free Account, so if you haven't used that up,
it should be free, but you are completely responsible for all Azure charges.

Running this module manually

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy

Running automated tests against this module

  1. Sign up for Azure.
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
    .
  3. Install Terraform and make sure it's on your PATH.
  4. Review environment variables.
  5. Install Golang and make sure this code is checked out into your GOPATH.
  6. cd test
  7. Make sure the azure-sdk-for-go versions match in /go.mod and in test/azure/terraform_azure_monitor_example_test.go.
  8. go build test/azure/terraform_azure_monitor_example_test.go
  9. go test -v -run TestTerraformAzureMonitorExample

Overview (`examples/azure/terraform-azure-mysqldb-example/README.md`)

Terraform Azure MySQL DB Example

This folder contains a Terraform module that deploys resources in Azure to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code.
This module deploys a database for MySQL.

Check out test/azure/terraform_azure_mysqldb_example_test.go to see how you can write automated tests for this module and validate the configuration of the parameters and options.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you money.

Running this module manually

  1. Sign up for Azure.
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH.
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your Terratest Go test environment
  5. cd test/azure
  6. go build terraform_azure_mysqldb_example_test.go
  7. go test -v -timeout 60m -tags azure -run TestTerraformAzureMySQLDBExample

Overview (`examples/azure/terraform-azure-network-example/README.md`)

Terraform Azure Network Example

This folder contains a simple Terraform module that deploys resources in Azure to demonstrate
how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys to a Virtual Network two Network Interface Cards, one with an internal only IP and another with an internal and external Public IP.

Check out test/azure/terraform_azure_network_example_test.go to see how you can write
automated tests for this module.

Note that the Azure Virtual Network, Subnet, Network Interface and Public IP resources in this module don't actually do anything; it just runs the resources for
demonstration purposes.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you
money. The resources are all part of the Azure Free Account, so if you haven't used that up,
it should be free, but you are completely responsible for all Azure charges.

Running this module manually

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your Terratest Go test environment
  5. cd test/azure
  6. go build terraform_azure_network_example_test.go
  7. go test -v -run TestTerraformAzureNetworkExample

Overview (`examples/azure/terraform-azure-nsg-example/README.md`)

Terraform Azure NSG Example

This folder contains a simple Terraform module that deploys resources in Azure to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys the following:

  • A Virtual Machine that gives the module the following:
    • Virtual Machine with the value specified in the vm_name variable along with a random value for the postfix variable (set from test code).
    • A Network Security Group created with a single custom rule to allow SSH (port 22) with the nsg name specified in the nsg_name variable along with a random value for the postfix variable (set from test code).

Check out test/azure/terraform_azure_nsg_example_test.go to see how you can write
automated tests for this module.

Note that the resources deployed in this module don't actually do anything; it just runs the resources for
demonstration purposes.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you
money. The resources are all part of the Azure Free Account, so if you haven't used that up,
it should be free, but you are completely responsible for all Azure charges.

Running this module manually

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your Terratest Go test environment
  5. cd test/azure
  6. go build terraform_azure_nsg_example_test.go
  7. go test -v -run TestTerraformAzureNsgExample

Overview (`examples/azure/terraform-azure-postgresql-example/README.md`)

Terraform Azure PostgreSQL DB Example

This folder contains a Terraform module that deploys resources in Azure to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code.
This module deploys a database for PostgreSQL.

Check out test/azure/terraform_azure_postgresqldb_example_test.go to see how you can write automated tests for this module and validate the configuration of the parameters and options.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you money.

Running this module manually

  1. Sign up for Azure.
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH.
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your Terratest Go test environment
  5. cd test/azure
  6. go build terraform_azure_postgresql_example_test.go
  7. go test -v -timeout 60m -tags azure -run TestPostgreSQLDatabase

Overview (`examples/azure/terraform-azure-recoveryservices-example/README.md`)

Terraform Azure Recovery Services Example

This folder contains a simple Terraform module that deploys resources in Azure to demonstrate
how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys a Recovery Services Vault with one backup virtual machine policy.

  • A Recovery Services that gives the module the following:
    • Backup Vault with the value specified in the recovery_service_vault_name output variable.
    • Backup VM Policy with the value specified in the backup_policy_vm_name output variable.

Check out test/azure/terraform_azure_recoveryservices_example_test.go to see how you can write
automated tests for this module.

Note that the Recovery Services Vault and backup virtual machine policy in this module don't actually do anything; it just runs the resources for
demonstration purposes.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you
money. The resources are all part of the Azure Free Account, so if you haven't used that up,
it should be free, but you are completely responsible for all Azure charges.

Running this module manually

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your Terratest Go test environment
  5. cd test/azure
  6. go build terraform_azure_recoveryservices_example_test.go
  7. go test -v -run TestTerraformAzureRecoveryServicesExample

Overview (`examples/azure/terraform-azure-resourcegroup-example/README.md`)

Terraform Azure Resource Group Example

This folder contains a simple Terraform module that deploys resources in Azure to demonstrate
how you can use TerraTest to write automated tests for your Azure Terraform code. This module deploys a Resource Group.

Check out test/azure/terraform_azure_resourcegroup_example_test.go to see how you can write
automated tests for this module.

Note that the Resource Group this module creates does not actually do anything; it just runs the resources for
demonstration purposes.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you
money. The resources are all part of the Azure Free Account, so if you haven't used that up,
it should be free, but you are completely responsible for all Azure charges.

Running this module manually

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your TerraTest Go test environment
  5. cd test/azure
  6. go build terraform_azure_resourcegroup_example_test.go
  7. go test -v -run TestTerraformAzureResourceGroupExample

Overview (`examples/azure/terraform-azure-servicebus-example/README.md`)

Terraform Azure Service Bus Example

This folder contains a Terraform module that deploys resources in Azure to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys a Service Bus.

  • A Service Bus with the namespace specified in the namespace_name variable.

Check out test/azure/terraform_azure_servicebus_example_test.go to see how you can write automated tests for this module and validate the configuration of the parameters and options.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you money. The resources are all part of the Azure Free Account, so if you haven't used that up,
it should be free, but you are completely responsible for all Azure charges.

Running this module manually

  1. Sign up for Azure.
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH.
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your Terratest Go test environment
  5. cd test/azure
  6. go build terraform_azure_servicebus_example_test.go
  7. go test -v -run TestTerraformAzureServiceBusExample

Overview (`examples/azure/terraform-azure-sqldb-example/README.md`)

Terraform Azure SQL DB Example

This folder contains a Terraform module that deploys resources in Azure to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys a SQL server, and a SQL database.

  • A SQL server with the name specified in the sql_server_name variable.
  • A SQL Database with the name specified in the sql_database_name variable.

Check out test/azure/terraform_azure_sqldb_example_test.go to see how you can write automated tests for this module and validate the configuration of the parameters and options.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you money. The resources are all part of the Azure Free Account, so if you haven't used that up,
it should be free, but you are completely responsible for all Azure charges.

Running this module manually

  1. Sign up for Azure.
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH.
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your Terratest Go test environment
  5. cd test/azure
  6. go build terraform_azure_sqldb_example_test.go
  7. go test -v -run TestTerraformAzureSQLDBExample

Overview (`examples/azure/terraform-azure-sqlmanagedinstance-example/README.md`)

Terraform Azure SQL DB Example

This folder contains a Terraform module that deploys resources in Azure to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys a SQL Managed Instance, and a SQL Managed Instance database.

Check out test/azure/terraform_azure_sqlmanagedinstance_example_test.go to see how you can write automated tests for this module and validate the configuration of the parameters and options.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you money. The resources are all part of the Azure Free Account, so if you haven't used that up,
it should be free, but you are completely responsible for all Azure charges.

Running this module manually

  1. Sign up for Azure.
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH.
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy.

Running automated tests against this module

WARNING: The deploymnet for this module usually takes more than 4-6 hours as stated in the microsoft docs, so please make sure to set the timeout accordingly in the below go test command.

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your Terratest Go test environment
  5. cd test/azure
  6. go build terraform_azure_sqlmanagedinstance_example_test.go
  7. go test -v -run TestTerraformAzureSQLManagedInstanceExample -timeout

Overview (`examples/azure/terraform-azure-storage-example/README.md`)

Terraform Azure Storage Example

This folder contains a simple Terraform module that deploys resources in Azure to demonstrate
how you can use TerraTest to write automated tests for your Azure Terraform code. This module deploys a
Storage Account.

Check out test/azure/terraform_azure_storage_example_test.go to see how you can write
automated tests for this module.

Note that the Storage Account in this module don't actually do anything; it just runs the resources for
demonstration purposes.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you
money. The resources are all part of the Azure Free Account, so if you haven't used that up,
it should be free, but you are completely responsible for all Azure charges.

Running this module manually

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your TerraTest Go test environment
  5. cd test/azure
  6. go build terraform_azure_storage_example_test.go
  7. go test -v -run TestTerraformAzureStorageExample

Overview (`examples/azure/terraform-azure-synapse-example/README.md`)

Terraform Azure Synapse Example

This folder contains a Terraform module that deploys resources in Azure to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code.
This module deploys below resource:

Check out test/azure/terraform_azure_synapse_example_test.go to see how you can write automated tests for this module and validate the configuration of the parameters and options.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you money.

Running this module manually

  1. Sign up for Azure.
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH.
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy.

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your Terratest Go test environment
  5. cd test/azure
  6. go build terraform_azure_synapse_example_test.go
  7. go test -v -timeout 60m -tags azure -run TestTerraformAzureSynapseExample

Overview (`examples/azure/terraform-azure-vm-example/README.md`)

Terraform Azure Virtual Machine Example

This folder contains a complete Terraform VM module that deploys resources in Azure to demonstrate
how you can use Terratest to write automated tests for your Azure Virtual Machine Terraform code. This module deploys these resources:

  • A Virtual Machine and gives that VM the following resources:
    • Virtual Machine with the name specified in the vm_name variable.
    • Managed Disk with the name specified in the managed_disk_name variable.
    • Availability Set with the name specified in the availability_set_name variable.
  • A Virtual Network module that contains the following resources:
    • Virtual Network with the name specified in the virtual_network_name variable.
    • Subnet with the name specified in the subnet_name variable.
    • Public Address with the name specified in the public_ip_name variable.
    • Network Interface with the name specified in the network_interface_name variable.

Check out test/azure/terraform_azure_vm_test.go to see how you can write
automated tests for this module.

Note that the Virtual Machine module creates a Microsoft Windows Server Image with a managed disk, availability set and network configuration for demonstration purposes.

WARNING: This module and the automated tests for it deploy real resources into your Azure account which can cost you
money. The resources are all part of the Azure Free Account, so if you haven't used that up,
it should be free, but you are completely responsible for all Azure charges.

Running this module manually

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CL
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Ensure environment variables are available
  5. Run terraform init
  6. Run terraform apply
  7. When you're done, run terraform destroy

Running automated tests against this module

  1. Sign up for Azure
  2. Configure your Azure credentials using one of the supported methods for Azure CLI
    tools
  3. Install Terraform and make sure it's on your PATH
  4. Configure your Terratest Go test environment
  5. cd test/azure
  6. go build terraform_azure_vm_test.go
  7. go test -run -v -timeout 20m TestTerraformAzureVmExample

Overview (`examples/terraform-aws-lambda-example/src/README.md`)

AWS Lambda Function Handler Source

The lambda executable handler was built using

shell
go get github.com/aws/aws-lambda-go/lambda
GOOS=linux GOARCH=amd64 go build -tags lambda.norpc -o bootstrap .

Docs 01 Getting Started Packages Overview (`docs/_docs/01_getting-started/packages-overview.md`)


Now that you've had a chance to browse the examples and their tests, here's an overview of the packages you'll find in
Terratest's modules folder and how they can help you test different types infrastructure:

{:.doc-styled-table}

Package Description
aws Functions that make it easier to work with the AWS APIs. Examples: find an EC2 Instance by tag, get the IPs of EC2 Instances in an ASG, create an EC2 KeyPair, look up a VPC ID.
azure Functions that make it easier to work with the Azure APIs. Examples: get the size of a virtual machine, get the tags of a virtual machine.
docker Functions that make it easier to work with Docker and Docker Compose. Examples: run docker compose commands.
files Functions for manipulating files and folders. Examples: check if a file exists, copy a folder and all of its contents.
gcp Functions that make it easier to work with the GCP APIs. Examples: Add labels to a Compute Instance, get the Public IPs of an Instance, Get a list of Instances in a Managed Instance Group, Work with Storage Buckets and Objects.
helm Functions for working with Helm. Examples: Install a Helm chart.
httphelper Functions for making HTTP requests. Examples: make an HTTP request to a URL and check the status code and body contain the expected values, run a simple HTTP server locally.
k8s Functions that make it easier to work with Kubernetes. Examples: Getting the list of nodes in a cluster, waiting until all nodes in a cluster is ready.
logger A replacement for Go's t.Log and t.Logf that writes the logs to stdout immediately, rather than buffering them until the very end of the test. This makes debugging and iterating easier.
logger/parser Includes functions for parsing out interleaved go test output and piecing out the individual test logs.
packer Functions for working with Packer. Examples: run a Packer build and return the ID of the artifact that was created.
random Functions for generating random data. Examples: generate a unique ID that can be used to namespace resources so multiple tests running in parallel don't clash.
retry Functions for retrying actions. Examples: retry a function up to a maximum number of retries, retry a function until a stop function is called, wait up to a certain timeout for a function to complete. These are especially useful when working with distributed systems and eventual consistency.
shell Functions to run shell commands. Examples: run a shell command and return its stdout and stderr.
ssh Functions to SSH to servers. Examples: SSH to a server, execute a command, and return stdout and stderr.
terraform Functions for working with Terraform. Examples: run terraform init, terraform apply, terraform destroy.
terragrunt Functions for working with Terragrunt. Examples: run terragrunt apply --all, terragrunt destroy --all, test stack configurations with dependencies, and work with Terragrunt stacks.
teststructure Functions for structuring your tests to speed up local iteration. Examples: break up your tests into stages so that any stage can be skipped by setting an environment variable.

Docs 03 Migrating To V1 Overview (`docs/_docs/03_migrating-to-v1/overview.md`)


Terratest v1.0.0 is the first stable release. Once you are on v1, breaking
changes to the public API only happen in major releases (e.g. v2.0.0), per
semver. Renamed or replaced symbols stay around as
deprecated aliases inside v1; full removal is deferred to v2.

Already on v1 and looking for v2? See
migrating to v2.

This page is the orientation map for v0.x to v1.0.0. It tells you what
shape the changes take and where to look; the per-service guides hold the
mechanical details.

Prerequisites

  • Go 1.26 or newer. v1.0.0 raised the minimum.
  • After upgrading, run go mod tidy from the directory that holds your
    test module's go.mod. The AWS, Azure, and GCP SDK pins all moved.

Function naming conventions

Most public Terratest helpers come in up to four variants. Knowing which
to call is the most common source of confusion when reading v1 godoc:

Suffix Takes context.Context On error
Foo no calls t.Fatal (fails the test)
FooE no returns error to the caller
FooContext yes calls t.Fatal
FooContextE yes returns error

Two independent suffixes:

  • E suffix. Long-standing Terratest convention. Use the bare name
    (Apply) when you want any failure to fail the test, and the E
    variant (ApplyE) when you want the error back to assert on it or
    retry.
  • Context suffix. Added in v1. Takes an explicit context.Context
    as the second argument so callers can plumb timeouts, cancellation,
    and tracing through. The non-Context variants are now deprecated
    in favor of their *Context* counterparts.

The preferred v1 call is FooContext (or FooContextE). For example,
prefer terraform.ApplyContext(t, ctx, opts) over
terraform.Apply(t, opts).

A small number of helpers do not yet expose all four variants (some
packages added Context and dropped the bare Foo form, others have
not grown a Context variant at all). Trust godoc and the deprecation
warnings over the table when they disagree.

Migrating to the `Context` variants

The Context migration is the single largest source of deprecation
warnings you will see when upgrading. It touches nearly every helper
package: terraform, helm, dnshelper, httphelper, packer,
docker, ssh, oci, k8s, aws, azure, gcp. The non-Context
variants compile and behave the same as before; they just emit a
// Deprecated: godoc warning.

Mechanical migration:

go
// Before
out := terraform.Apply(t, options)
out, err := terraform.ApplyE(t, options)

// After
ctx := context.Background() // or context.WithTimeout(...) for cancellation
out := terraform.ApplyContext(t, ctx, options)
out, err := terraform.ApplyContextE(t, ctx, options)

The *Context* variants always take (t, ctx, ...originalArgs). If
you do not need cancellation or timeouts, context.Background() gives
you the same behavior as the deprecated wrapper. When t is
*testing.T (Go 1.24+), t.Context() is an even better default
because it ties the context lifetime to the test.

You can do this incrementally. The deprecated wrappers will keep
working for the entire v1 line; they only disappear in v2.

What changed by service

Azure

The largest set of breaking changes by far. The whole modules/azure
package was moved from the archived services/... SDK to the actively
maintained sdk/resourcemanager/... SDK, plus a handful of naming
cleanups. Updating imports and the resulting compile errors is the bulk
of the work; per-service tables and a search-and-replace cheatsheet are
in Azure modules.

AWS

modules/aws/s3.go migrated off the deprecated
s3/manager package onto s3/transfermanager. Four exported functions
that returned *manager.Uploader now return *transfermanager.Client:
NewS3Uploader, NewS3UploaderE, NewS3UploaderContext, and
NewS3UploaderContextE. The call shape moves from
uploader.Upload(ctx, &s3.PutObjectInput{...}) to
client.UploadObject(ctx, &transfermanager.UploadObjectInput{...}),
with the input/output types under
github.com/aws/aws-sdk-go-v2/feature/s3/transfermanager.

Every direct github.com/aws/aws-* dependency was bumped to the
versions current at the v1.0.0 cut. If your tests import the AWS SDKs
directly, expect to run go mod tidy and resolve a small number of
type renames at the SDK level.

GCP

modules/gcp/pubsub.go moved from cloud.google.com/go/pubsub (v1) to
cloud.google.com/go/pubsub/v2. The wrapper functions in modules/gcp
are unchanged in shape, but callers that drove the underlying client
directly need to switch from client.Topic("name") /
client.Subscription("name") handles to TopicAdminClient /
SubscriptionAdminClient calls that take fully qualified resource
names (projects//topics/<name>).

A new family of *WithClient helpers was added across modules/gcp
(compute, oslogin, region, pubsub, storage, cloudbuild, gcr) so tests
can inject a pre-built SDK client. This parallels the Azure
*WithClient change and is purely additive.

Kubernetes

GetKubernetesClientFromOptionsContextE now logs the kubeconfig load
error before falling back to rest.InClusterConfig(); previously the
fallback was silent.

This was a silent-failure footgun: a typo in
KubectlOptions.ConfigPath would send tests against the test runner's
in-cluster identity (potentially a different cluster) with no signal
that anything had happened. v1 surfaces the error in the test log, and
adds an explicit KubectlOptions.InClusterAuth = true opt-in that
skips kubeconfig loading entirely for callers who want fully explicit
auth.

Other deprecations you can defer

A large set of legacy spellings picked up Go-idiomatic replacements in
v1, all preserved as deprecated aliases. Most follow common acronym
casing (Id β†’ ID, Ip β†’ IP, Json β†’ JSON, Url β†’ URL,
Ssh β†’ SSH, Gcp β†’ GCP); a few drop redundant prefixes (Azure's
CreateNew*Client* becomes Create*Client*); and a few rename for
clarity (e.g. SaveAmiId / LoadAmiId became
SaveArtifactID / LoadArtifactID to reflect that the helpers are
not AMI-specific).

You do not need to track these one by one. Run go vet or
staticcheck against your test module after upgrading; the deprecated
aliases all carry // Deprecated: annotations and the linter will
list them with the replacement to use. Aliases stay for the v1 line
and are removed in v2.

Need help

Open an issue on the Terratest
repo
with a snippet
of the failing code and the relevant module label. If you spot a gap
in this guide, send a PR against docs/_docs/03_migrating-to-v1/.


Docs 04 Migrating To V2 Overview (`docs/_docs/04_migrating-to-v2/overview.md`)


Terratest v2 splits the single github.com/gruntwork-io/terratest module
into 16 independent modules, so you depend only on the parts you use. A
test that imports terraform no longer pulls in the AWS SDK, client-go,
and every other provider's dependencies.

The cost is that every import path changes. This page tells you what the
changes are and the order to apply them; the per-topic pages hold the
details.

Should you migrate yet

v2 is in beta. v1 is in maintenance and receives security fixes only, until
12 months after v2.0.0 reaches general availability. Migrate now if you want
the smaller dependency graph or are starting fresh; wait for v2.0.0 if you
would rather not track beta releases.

You can migrate incrementally. v1 and v2 import paths differ, so both can
coexist in one module while you convert package by package. The change
touches only .go files, go.mod and go.sum, so git checkout undoes
it.

The minimum Go version is unchanged.

The five changes

1. Everything v1 deprecated is gone. v1 kept deprecated aliases
alongside their replacements; v2 deletes them. This is the largest edit in
the migration, and it is not only the Context variants:

  • non-Context wrappers: terraform.Apply is now only ApplyContext
  • initialism renames: random.UniqueId is now UniqueID,
    aws.GetAccountIdE is now GetAccountIDContextE
  • reshaped helpers: packer.BuildAmi is now BuildArtifactContextE

The reliable way to find all of it is to run staticcheck against your
existing v1 code and clear every SA1019 (deprecated symbol) warning before
you touch imports. Once v1 is warning-free, the rest of this guide applies.

go
// v1
out := terraform.Apply(t, options)
// v2
out := terraform.ApplyContext(t, t.Context(), options)

The Context variants always take (t, ctx, ...originalArgs).
t.Context() is the best default; context.Background() also works. The
v1 guide covers this
migration in detail, and doing it on v1 first, where both forms still
compile, is easier than doing it at the same time as the import rewrite.

2. Import paths gain a /v2 suffix. The /v2 goes after the module
root, not at the end of the path:

go
// v1
"github.com/gruntwork-io/terratest/modules/terraform"
// v2
"github.com/gruntwork-io/terratest/modules/terraform/v2"

3. Six utility packages collapse into core. random, files,
logger, shell, retry and testing are no longer separate packages:

go
// v1
"github.com/gruntwork-io/terratest/modules/random"
// v2
"github.com/gruntwork-io/terratest/modules/core/v2/random"

4. Three packages are renamed to drop the hyphen. This changes the
package identifier at call sites, not just the import path:

http-helper becomes httphelper, dns-helper becomes dnshelper, and
test-structure becomes teststructure. The full table is in the import
map
.

5. Each module needs its own require. Where v1 was one line in
go.mod, v2 needs one per module you import. Add them with go get
rather than by hand:

bash
go get github.com/gruntwork-io/terratest/modules/terraform/[email protected]
go get github.com/gruntwork-io/terratest/modules/aws/[email protected]

Each module is tagged modules/<name>/vX.Y.Z, so the tag for the command
above is modules/terraform/v2.0.0-beta.2. The current version is on the
releases page. All 16
modules are released together and their cross-module requires are pinned to
the release version, so keep them on the same version.

The full path mapping is in the import
map
.

Order to do it in

  1. Move to the Context variants, ideally while still on v1 so both forms
    compile.
  2. Rewrite import paths and package identifiers. This is mechanical and the
    compiler finds everything.
  3. Fix the symbol relocations. Also compile errors, also mechanical. They
    are listed under rewriting
    imports
    .
  4. Add a require per module, then go mod tidy.
  5. Review the behavior
    changes
    , which
    the compiler will not find for you. There are two, both in k8s.

Steps 1 to 4 are compiler-detectable, so the build tells you when they are
complete. Step 5 is not: the code compiles either way, so it needs reading
before you call the migration done.

Removed packages

Six packages and two binaries are not carried forward. Three have a
standard library replacement:

v1 Replacement
modules/collections stdlib slices
modules/environment stdlib os.Getenv
modules/git stdlib os/exec
modules/slack none; vendor from v1
modules/version-checker none; shell out
modules/oci none; Oracle Cloud is not carried forward, stay on v1

cmd/pick-instance-type and cmd/terratest_log_parser are gone as
binaries. The log parser's library survives at
modules/core/v2/logger/parser.

What did not change

The Foo / FooE convention is unchanged: FooContext fails the test,
FooContextE returns an error. Beyond dropping the non-Context wrappers
and the relocations above, function arguments and return types are the
same. Test data written by v1 loads in v2, since filenames and JSON layout
are unchanged.

Need help

Open an issue on the Terratest
repo
with the version
you are coming from and the error you hit. If you spot a gap in this
guide, send a PR against docs/_docs/04_migrating-to-v2/.



layout: subpage
permalink: /cookie-policy/
slug: cookie-policy
redirect_to:



Config.Yml (`docs/_config.yml`)

Welcome to Jekyll!

This config file is meant for settings that affect your whole blog, values

which you are expected to set up once and rarely edit after that. If you find

yourself editing this file very often, consider using Jekyll's data files

feature for the data you need to update frequently.

For technical reasons, this file is *NOT* reloaded automatically when you use

'bundle exec jekyll serve'. If you change this file, please restart the server process.

If you need help with YAML syntax, here are some quick references for you:

https://learn-the-web.algonquindesign.ca/topics/markdown-yaml-cheat-sheet/#yaml

https://learnxinyminutes.com/docs/yaml/

Site settings

These are used to personalize your new site. If you look in the HTML files,

you will see them accessed via {{ site.title }}, {{ site.email }}, and so on.

You can create any custom variable you would like, and they will be accessible

in the templates via {{ site.myvariable }}.

title: Terratest
url: "https://terratest.gruntwork.io"
email: [email protected]
name: "Terratest | Automated tests for your infrastructure code."
Terratest is a Go library that provides patterns and helper functions for
testing infrastructure, with 1st-class support for Terraform, Packer, Docker,
Kubernetes, AWS, GCP, and more.
baseurl: "" # the subpath of your site, e.g. /blog
full_company_name: "Gruntwork, Inc"
thumbnail_path: "/assets/img/terratest-thumbnail.png"

Keep this on the latest GA release so users copy stable, released code rather than

whatever is currently on `main`. Update this and github_api_url below on each GA release.

stable_ref: v1.0.1
twitter_username: https://twitter.com/gruntwork_io
github_username: https://github.com/gruntwork-io

github_api_url: https://raw.githubusercontent.com/gruntwork-io/terratest/v1.0.1

Build settings

theme: minima

assets_base_url: '/assets/'

gtm_tracker: GTM-5TTJJGTL

theme: null

plugins:

  • jekyll-toc
  • jekyll-redirect-from
  • jekyll-sitemap

sass:
sass_dir: assets/css
style: compressed

whitelist:

  • jekyll-redirect-from

include: ['_pages']

collections:
docs:
output: true
sort_by: order
permalink: /:collection/:categories/:title/

Exclude from processing.

The following items will not be processed, by default.

Any item listed under the `exclude:` key here will be automatically added to

the internal "default list".

Excluded items can be processed by explicitly listing the directories or

their entries' file path in the `include:` list.

exclude:

  • .sass-cache/
  • .jekyll-cache/
  • gemfiles/
  • Gemfile
  • Gemfile.lock
  • node_modules/
  • vendor/bundle/
  • vendor/cache/
  • vendor/gems/
  • vendor/ruby/
  • scripts/

Docker Compose.Yml (`docs/docker-compose.yml`)

version: '3'

services:
web:
build: .
volumes:
# Bind mount the working dir so the app reloads automatically every time you make a change
# Note that we use 'delegated' to improve perf on OSX: https://docs.docker.com/docker-for-mac/osxfs-caching/
- .:/src:delegated
# Bind a Docker-only volume to the generated _site folder to make it clear we don't need to sync that folder
# back to the host OS. That makes Jekyll in Docker work much faster.
- generated_site:/src/_site
ports:
- "4000:4000"
# Expose port for jekyll livereload
- "35729:35729"
environment:
- JEKYLL_ENV=development

volumes:
generated_site:


V2 Import Map (`docs/v2-import-map.md`)

Terratest v2 Import Map

Status: FROZEN for import paths. The one open decision (renames) is resolved: the three hyphenated packages are renamed to idiomatic Go names at the /v2 boundary.

Some symbols also moved between modules during the beta. See Symbols relocated during the v2 beta.

Built from the actual v1 layout at tag v1.0.1-test (27 modules/ packages, 2 cmd/ binaries, 1 internal/lib tree).

Module base path: github.com/gruntwork-io/terratest

Transformation rule

For any surviving import path, the rewrite is a prefix replacement that also applies to every subpackage:

  • modules/<name>/... -> modules/<name>/v2/... (the /v2 SIV goes after the module root; directory layout unchanged except for the three renames below)
  • The six tier-0 utilities collapse under one module: modules//... -> modules/core/v2//...
  • Three packages are also renamed to drop the hyphen: http-helper -> httphelper, dns-helper -> dnshelper, test-structure -> teststructure. The package identifier loses its underscore too (http_helper -> httphelper), so call sites change, not just the import path. The codemod handles both.

So e.g. modules/logger/parser -> modules/core/v2/logger/parser, modules/aws/foo -> modules/aws/v2/foo, and modules/http-helper -> modules/httphelper/v2.

core collapse (6 v1 packages -> one `modules/core/v2`)

v1 import path v2 import path
modules/logger modules/core/v2/logger
modules/testing modules/core/v2/testing
modules/retry modules/core/v2/retry
modules/random modules/core/v2/random
modules/files modules/core/v2/files
modules/shell modules/core/v2/shell

Standalone `/v2` submodules

v1 import path v2 import path
modules/aws modules/aws/v2
modules/azure modules/azure/v2
modules/gcp modules/gcp/v2
modules/k8s modules/k8s/v2
modules/helm modules/helm/v2
modules/ssh modules/ssh/v2
modules/docker modules/docker/v2
modules/packer modules/packer/v2
modules/database modules/database/v2
modules/opa modules/opa/v2
modules/terraform modules/terraform/v2
modules/terragrunt modules/terragrunt/v2
modules/http-helper modules/httphelper/v2
modules/dns-helper modules/dnshelper/v2
modules/test-structure modules/teststructure/v2

Removed in v2.0.0 (deprecated in v1 first, deleted at cutover)

v1 import path replacement
modules/collections stdlib slices
modules/environment stdlib os.Getenv
modules/git stdlib os/exec
modules/slack none, vendor from frozen v1 if needed
modules/version-checker none, shell out
modules/oci none, Oracle Cloud support not carried forward; remains in frozen v1, vendor if needed
cmd/pick-instance-type none, standalone binary, out of scope
cmd/terratest_log_parser none, standalone binary (its logger/parser lib survives under modules/core/v2/logger/parser)

Internal flatten (non-importable, not consumer-facing)

v1 v2
internal/lib/formatting internal/formatting

Symbols relocated during the v2 beta

Moved to the module owning the type, so teststructure no longer requires aws, k8s, packer and ssh (#1877).
Signatures and on-disk filenames are unchanged, and every call site is a compile error.

beta.1 beta.2 onwards
teststructure.{Save,Load}Ec2KeyPair aws.{Save,Load}Ec2KeyPair
teststructure.{Save,Load}KubectlOptions k8s.{Save,Load}KubectlOptions
teststructure.{Save,Load}PackerOptions packer.{Save,Load}PackerOptions
teststructure.{Save,Load}SSHKeyPair ssh.{Save,Load}SSHKeyPair

Nothing else moved. Watch for files that alias Terratest's aws because plain aws is the AWS SDK.

Behavior changes during the v2 beta

Node addresses prefer ExternalIP (#1878). k8s.FindNodeHostnameContextE and GetServiceEndpoint (NodePort)
now return the Node's ExternalIP when present, falling back to the internal hostname as before. On EKS that is the
public IP, so no EC2 call and no ec2:DescribeInstances permission is needed. Signatures are unchanged; the new
FindNodeHostnameWithOptionsContext[E] consults NodePublicIPLookup for clusters with no ExternalIP.

KubectlOptions carrying a RestConfig no longer serializes (#1879). MarshalJSON returns
k8s.ErrRestConfigNotSerializable instead of dropping the config. This already failed, with an opaque
json: unsupported type: transport.WrapperFunc. Use NewKubectlOptions or NewKubectlOptionsWithInClusterAuth.

Accounting

27 modules/ packages = 6 collapsed into core + 15 standalone submodules + 6 removed. Plus 2 removed cmd/ binaries and 1 internal flatten. Submodule count: 16.

Open decisions

None. The map is frozen.

Resolved

  • oci (Oracle Cloud Infrastructure): not carried forward to v2. Niche provider; removed alongside the other dropped packages. Oracle Cloud users stay on frozen v1.
  • Renames. Decided to rename the three hyphenated packages at the v2 boundary: http-helper -> httphelper, dns-helper -> dnshelper, test-structure -> teststructure. Consumers already rewrite every import for the /v2 bump, so folding the rename into that same edit adds no separate migration, and it drops the non-idiomatic underscore package names (http_helper, currently suppressed with //nolint:staticcheck). The rename rides along with the modularization import rewrite, and the codemod covers both the path and the package identifier.

V2 Release Runbook (`docs/v2-release-runbook.md`)

Terratest v2 Release Runbook

How to cut a coordinated release of the v2 submodules. Read this before tagging.

The whole release is one manual workflow: Create v2 Release
(.github/workflows/create-release.yml, run via workflow_dispatch). Give it a
version (e.g. v2.0.0-beta.1) and a ref (default main); it runs the
pre-flight checks, pins the cross-module requires, commits that in CI, pushes the
16 tags in dependency order, and verifies the proxy. Run it once with
dry_run=true to preview the exact tags, then again with dry_run=false to push.

The rest of this runbook explains what that workflow does under the hood and how
to do each step by hand if you ever need to.

Layout

v2 is split into per-domain modules under modules/<name>/, each declaring
module github.com/gruntwork-io/terratest/modules/<name>/v2. Local development
uses the root go.work, which resolves every submodule to its local tree, so the
submodule go.mod files do not need internal require lines or replace
directives during normal development.

Why pinning is a release-time step (do not commit it early)

On main, a submodule's cross-module require sits at the local zero
placeholder (e.g. core/v2 v2.0.0-00010101000000-000000000000) that go.work
resolves; it is never pinned to a real, to-be-published version. Pinning a sibling require to the to-be-published
version (e.g. core/v2 v2.0.0-beta.1) BREAKS the workspace build until that tag
actually exists: go.work does not shadow an unpublished required version, so
go build and go work sync try to fetch the missing revision and fail. The pin
must therefore happen immediately before the tags are pushed, never on main or
a modularization PR. The Create v2 Release workflow does this pin in CI (via
scripts/release-prep-pin.sh) on an ephemeral commit that only the tags point
at, so the broken-build state never lands on a branch.

CI validates the release-mode build continuously without committing the pin: the
GOWORK=off check generates the pinned state with throwaway replace directives,
builds a consumer, and discards it (see scripts/).

Pre-flight (what the workflow does before tagging)

  1. Choose the version, e.g. v2.0.0-beta.1.
  2. Pin each module, in dependency order (core first, then helpers, tooling,
    platforms, k8s/helm, IaC). For each module:
    • Add a temporary replace for EVERY sibling it transitively needs, not just
      its direct imports. Tidy follows transitive edges, so a partial replace set
      fails with unknown revision on a deeper sibling.
    • Seed the module with the root go.mod's exact dependency versions before
      tidying (copy its require lines in). Otherwise tidy floats deps to the
      latest compatible release and you get silent version drift, e.g. the Azure
      SDK advancing to a release that drops a symbol the code uses
      (undefined: armmonitor.DiagnosticSettingsClient). The code is tested
      against the root's pinned versions; the submodules must inherit them.
    • GOWORK=off go mod tidy to populate external requires and go.sum.

scripts/check-release-mode.sh performs this exact pin (transitive replaces +
root-version seeding + an all-module external consumer build under GOWORK=off)
in a throwaway and reverts it, and runs in CI on every PR so the release-mode
build is validated continuously without committing the pin or needing tags.
3. Set every internal require to the exact version being tagged, then DROP all
internal replace directives. Do not run go work sync against the unpinned
tree.
4. Before tagging, confirm no internal replace directives remain in any
modules/*/go.mod. A committed replace would publish a module pointing at a
local path and break consumers.
5. Move test/ to its own module here too if not already done, and pin it the
same way (it is test-only, so committed replaces are acceptable for it).

Tag push order

All tags point at the same release commit. The tag name is the module's
on-disk subdirectory (which does NOT include the /v2, since /v2 is only the
SIV in the module path, not a directory) followed by the version:
modules/<name>/<version>, e.g. modules/aws/v2.0.0-beta.1. Do NOT put the
/v2 in the tag (modules/<name>/v2/<version>), Go looks for the tag at
<subdir>/<version> and will not find it. Push in dependency order:

  1. modules/core/v2.0.0-beta.1
  2. helpers: ssh, httphelper, dnshelper
  3. tooling: docker, packer, database, opa
  4. platforms: aws, azure, gcp, then k8s, helm
  5. IaC: terraform, terragrunt, teststructure

After each tier, probe the proxy before continuing:
curl -o /dev/null -w '%{http_code}' https://proxy.golang.org/github.com/gruntwork-io/terratest/modules/<name>/v2/@v/<version>.info
should return 200.

Verify

Build a throwaway external consumer that imports every published module with
GOWORK=off. This is what scripts/check-release-mode.sh generates in a temp
directory, except now it resolves against the real published tags rather than
local replaces. A clean consumer should resolve, build, and test green with
zero local references.

If a tag is wrong

Proxy tags are immutable. Recover by cutting the next patch (v2.0.0-beta.2),
never by editing in place. The pre-flight checks exist to keep this rare.

Beta to GA

After the beta soaks (suggested two weeks minimum), repeat the same procedure at
v2.0.0 with no suffix: same release commit shape, same tag sequence, same proxy
verification, then announce.


Data Examples.Yml (`docs/_data/examples.yml`)


Docs 01 Getting Started Examples (`docs/_docs/01_getting-started/examples.md`)


title: Examples
category: getting-started
excerpt: Examples are the best way to start testing Terraform, Docker, Packer, Kubernetes, AWS, GCP, and more with Terratest.
tags: ["example"]
redirect_to:

  • /examples/
    order: 102
    nav_title: Documentation
    nav_title_link: /docs/


Docs 01 Getting Started Godoc (`docs/_docs/01_getting-started/godoc.md`)


layout: collection-browser-doc
title: GoDoc
category: getting-started
excerpt: >-
Browse Terratest methods and types in GoDoc.
tags: ["packages"]
redirect_to:



Docs 01 Getting Started Introduction (`docs/_docs/01_getting-started/introduction.md`)


Introduction

Terratest is a Go library that makes it easier to write automated tests for your infrastructure code. It provides a
variety of helper functions and patterns for common infrastructure testing tasks, including:

  • Testing Terraform code
  • Testing Packer templates
  • Testing Docker images
  • Executing commands on servers over SSH
  • Working with AWS APIs
  • Working with Azure APIs
  • Working with GCP APIs
  • Working with Kubernetes APIs
  • Enforcing policies with OPA
  • Testing Helm Charts
  • Making HTTP requests
  • Running shell commands
  • And much more

Watch: β€œHow to test infrastructure code”

Yevgeniy Brikman talks about how to write automated tests for infrastructure code, including the code written for use with tools such as Terraform, Docker, Packer, and Kubernetes. Topics covered include: unit tests, integration tests, end-to-end tests, dependency injection, test parallelism, retries and error handling, static analysis, property testing and CI / CD for infrastructure code.

This presentation was recorded at QCon San Francisco 2019: https://qconsf.com/.

Slides

Slides to the video can be found here: Slides: How to test infrastructure code{:target="_blank"}.

Gruntwork

Terratest was developed at Gruntwork to help maintain the Infrastructure as Code
Library
, which contains over 300,000 lines of code written
in Terraform, Go, Python, and Bash, and is used in production by hundreds of companies.

See how to get started with Terratest
Quick Start


Docs 01 Getting Started Quick Start (`docs/_docs/01_getting-started/quick-start.md`)


layout: collection-browser-doc
title: Quick start
category: getting-started
excerpt: Learn how to start with Terratest.
tags: ["quick-start"]
order: 101
nav_title: Documentation
nav_title_link: /docs/
custom_js:

  • examples
  • prism

Requirements

Terratest uses the Go testing framework, and the examples below drive OpenTofu. To follow
along, you need:

Terratest's terraform module runs whichever binary you point it at. By default it uses terraform when that binary
is on your PATH and otherwise falls back to tofu, so installing only OpenTofu is enough to get going. To pin a test
to OpenTofu regardless of what else is installed, set TerraformBinary: "tofu" in the terraform.Options you pass to
the helpers (more on this below).

The rest of this guide uses mise to manage tool versions. It isn't required (install Go and
OpenTofu however you like), but it keeps everyone on the same versions.

Starting a new project

If you're adding tests to an existing module, skip to Setting up your tests. Otherwise, here
is how to stand up a fresh Go project from scratch.

  1. Create the project and initialize Git:

    bash
    mkdir my-infra && cd my-infra
    git init
  2. Pin your tools with mise. This writes a mise.toml that anyone cloning the repo can use to install the exact same
    versions:

    bash
    mise use [email protected]
    mise use [email protected]

    Run mise install to fetch the tools, and prefix commands with mise x -- <command> (or run mise activate in
    your shell) so they resolve to the pinned versions.

  3. Lay out the standard Terratest folders. Infrastructure code lives in examples, and the Go tests that exercise it
    live in test:

    bash
    mkdir examples test
  4. Initialize the Go module. Terratest tests live in their own module under test:

    bash
    cd test
    go mod init "<MODULE_NAME>"

    Where <MODULE_NAME> is the name of your module, typically in the format
    github.com/<YOUR_USERNAME>/<YOUR_REPO_NAME>.

  5. Add a .gitignore so you don't commit local state, provider plugins, or build artifacts:

    bash
    cat > ../.gitignore <<'EOF'
    .terraform/
    *.tfstate
    *.tfstate.backup
    .terraform.lock.hcl
    EOF

Now add some infrastructure and a test, as described next.

Setting up your tests

The easiest way to get started with Terratest is to copy one of the examples and its corresponding tests from this
repo. This quick start section uses an OpenTofu/Terraform example, but check out the
Examples section for other types of infrastructure code you can test (e.g., Packer,
Kubernetes, etc).

  1. Copy the folder including all the files from the [basic example](https://github.com/gruntwork-io/terratest/tree/{{ site.stable_ref }}/examples/terraform-basic-example/) into the examples folder.

  2. Copy the [basic example test](https://github.com/gruntwork-io/terratest/blob/{{ site.stable_ref }}/test/terraform_basic_example_test.go) into the test folder.

  3. To configure dependencies, run:

    bash
    cd test
    go mod tidy

    (If you skipped the previous section, run go mod init "<MODULE_NAME>" first.)

    To lock your tests to a specific Terratest release, see [Pinning a Terratest version]({{ site.baseurl }}/docs/getting-started/version-pinning/).

  4. To run the tests:

    bash
    cd test
    go test -v -timeout 30m

    (See [Timeouts and logging]({{ site.baseurl }}/docs/testing-best-practices/timeouts-and-logging/) for why the -timeout parameter is used.)

Preferring OpenTofu

By default the terraform helpers use the terraform binary if it's installed and fall back to tofu otherwise. To
run OpenTofu explicitly, even on a machine that also has Terraform, set TerraformBinary on the options you pass in:

go
terraformOptions := &terraform.Options{
    TerraformDir:    "../examples/terraform-basic-example",
    TerraformBinary: "tofu",
}

The helper function names (terraform.InitAndApply, terraform.Output, and so on) don't change; only the underlying
executable does.

Terratest intro

The basic usage pattern for writing automated tests with Terratest is to:

  1. Write tests using Go’s built-in package testing: you create a file ending in _test.go and run tests with the go test command. E.g., go test my_test.go.
  2. Use Terratest to execute your real IaC tools (e.g., OpenTofu, Packer, etc.) to deploy real infrastructure (e.g., servers) in a real environment (e.g., AWS).
  3. Use the tools built into Terratest to validate that the infrastructure works correctly in that environment by making HTTP requests, API calls, SSH connections, etc.
  4. Undeploy everything at the end of the test.

To make this sort of testing easier, Terratest provides a variety of helper functions and patterns for common infrastructure testing tasks, such as testing OpenTofu and Terraform code, testing Packer templates, testing Docker images, executing commands on servers over SSH, making HTTP requests, working with AWS APIs, and so on.

Example #1: OpenTofu "Hello, World"

Let's start with the simplest possible OpenTofu code, which just outputs the text,
"Hello, World" (if you’re new to OpenTofu or Terraform, check out our Comprehensive Guide to
Terraform
, which applies equally to
OpenTofu):

{% include examples/explorer.html example_id='terraform-hello-world' file_id='terraform_code' class='wide quick-start-examples' skip_learn_more=true skip_view_on_github=true skip_tags=true %}

How can you test this code to be confident it works correctly? Well, let’s think about how you would test it manually:

  1. Run tofu init and tofu apply to execute the code.
  2. When apply finishes, check that the output variable says, "Hello, World".
  3. When you're done testing, run tofu destroy to clean everything up.

Using Terratest, you can write an automated test that performs the exact same steps! Here’s what the code looks like:

{% include examples/explorer.html example_id='terraform-hello-world' file_id='test_code' class='wide quick-start-examples' skip_learn_more=true skip_view_on_github=true skip_tags=true %}

This code does all the steps we mentioned above, including running tofu init, tofu apply, reading the
output variable using tofu output, checking its value is what we expect, and running tofu destroy
(using defer to run it at the end of the test, whether the test
succeeds or fails). If you put this code in a file called terraform_hello_world_example_test.go, you can run it by
executing go test, and you’ll see output that looks like this (truncated for readability):

console
$ go test -v
=== RUN   TestTerraformHelloWorldExample
Running command tofu with args [init]
Initializing provider plugins...
[...]
OpenTofu has been successfully initialized!
[...]
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
hello_world = "Hello, World!"
[...]
Running command tofu with args [destroy -auto-approve -input=false]
[...]
Destroy complete! Resources: 2 destroyed.
--- PASS: TestTerraformHelloWorldExample (149.36s)

Success!

Example #2: OpenTofu and AWS

Let's now try out a more realistic example. Here is some OpenTofu code that deploys a simple web server in
AWS:

{% include examples/explorer.html example_id='aws-hello-world' file_id='terraform_code' class='wide quick-start-examples' skip_learn_more=true skip_view_on_github=true skip_tags=true %}

The code above deploys an EC2 Instance that is running an Ubuntu
Amazon Machine Image (AMI). To keep this example
simple, we specify a User Data
script that, while the server is booting, fires up a dirt-simple web server that returns β€œHello, World” on port 8080.

How can you test this code to be confident it works correctly? Well, let’s again think about how you would test it
manually:

  1. Run tofu init and tofu apply to deploy the web server into your AWS account.
  2. When apply finishes, get the IP of the web server by reading the public_ip output variable.
  3. Open the IP in your web browser with port 8080 and make sure it says β€œHello, World”. Note that it can take 1–2
    minutes for the server to boot up, so you may have to retry a few times.
  4. When you’re done testing, run tofu destroy to clean everything up.

Here's how we can automate the steps above using Terratest:

{% include examples/explorer.html example_id='aws-hello-world' file_id='test_code' class='wide quick-start-examples' skip_learn_more=true skip_view_on_github=true skip_tags=true %}

This test code runs tofu init and tofu apply, reads the server IP using tofu output, makes HTTP
requests to the web server (including plenty of retries to account for the server taking time to boot), checks the HTTP
response is what we expect, and then runs tofu destroy at the end. If you put this code in a file called
terraform_aws_hello_world_example_test.go, you can run just this test by passing the -run argument to go test as
follows:

console
$ go test -v -run TestTerraformAwsHelloWorldExample -timeout 30m
=== RUN   TestTerraformAwsHelloWorldExample
Running command tofu with args [init]
Initializing provider plugins...
[...]
OpenTofu has been successfully initialized!
[...]
Running command tofu with args [apply -auto-approve]
aws_instance.example: Creating...
  associate_public_ip_address:       "" => "<computed>"
  availability_zone:                 "" => "<computed>"
  ephemeral_block_device.#:          "" => "<computed>"
  instance_type:                     "" => "t2.micro"
  key_name:                          "" => "<computed>"
[...]
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Outputs:
public_ip = 52.67.41.31
[...]
Making an HTTP GET call to URL http://52.67.41.31:8080
dial tcp 52.67.41.31:8080: getsockopt: connection refused.
Sleeping for 5s and will try again.
Making an HTTP GET call to URL http://52.67.41.31:8080
dial tcp 52.67.41.31:8080: getsockopt: connection refused.
Sleeping for 5s and will try again.
Making an HTTP GET call to URL http://52.67.41.31:8080
Success!
[...]
Running command tofu with args [destroy -auto-approve -input=false]
[...]
Destroy complete! Resources: 2 destroyed.
--- PASS: TestTerraformAwsHelloWorldExample (149.36s)

Success! Now, every time you make a change to this OpenTofu code, the test code can run and make sure your web server
works as expected.

Note that in the go test command above, we set -timeout 30m. This is because Go sets a default test time out of 10
minutes, and if your test take longer than that to run, Go will panic, and kill the test code part way through. This is
not only annoying, but also prevents the clean up code from running (the tofu destroy), leaving you with lots of
resources hanging in your AWS account. To prevent this, we always recommend setting a high test timeout; the test above
doesn't actually take anywhere near 30 minutes (typical runtime is ~3 minutes), but we give lots of extra buffer to be
extra sure that the test always has a chance to finish cleanly.

Example #3: Docker

You can use Terratest for testing a variety of infrastructure code, not just OpenTofu. For example, you can use it to
test your Docker images:

{% include examples/explorer.html example_id='docker-hello-world' file_id='docker_code' class='wide quick-start-examples' skip_learn_more=true skip_view_on_github=true skip_tags=true %}

The Dockerfile above creates a simple Docker image that uses Ubuntu 18.04 as a base and writes the text "Hello, World!"
to a text file. At this point, you should already know the drill. First, let's think through how you'd test this
Dockerfile manually:

  1. Run docker build to build the Docker image.
  2. Run the image via docker run.
  3. Check that the running Docker container has a text file with the text "Hello, World!" in it.

Here's how you can use Terratest to automate this process:

{% include examples/explorer.html example_id='docker-hello-world' file_id='test_code' class='wide quick-start-examples' skip_learn_more=true skip_view_on_github=true skip_tags=true %}

Instead of using the OpenTofu/Terraform helpers, this test code uses Terratest's Docker helpers to run docker build, docker run,
and check the contents of the text file. As before, you can run this test using go test!

Example #4: Kubernetes

Terratest also provides helpers for testing your Kubernetes code. For example, here's a
Kubernetes manifest you might want to test:

{% include examples/explorer.html example_id='kubernetes-hello-world' file_id='k8s_code' class='wide quick-start-examples' skip_learn_more=true skip_view_on_github=true skip_tags=true %}

This manifest deploys the Docker training webapp, a simple app that
responds with the text "Hello, World!", as a Kubernetes Deployment and exposes it to the outside world on port 5000
using a LoadBalancer.

To test this code manually, you would:

  1. Run kubectl apply to deploy the Docker training webapp.
  2. Use the Kubernetes APIs to figure out the endpoint to hit for the load balancer.
  3. Open the endpoint in your web browser on port 5000 and make sure it says β€œHello, World”. Note that, depending on
    your Kubernetes cluster, it could take a minute or two for the Docker container to come up, so you may have to retry
    a few times.
  4. When you're done testing, run kubectl delete to clean everything up.

Here's how you automate this process with Terratest:

{% include examples/explorer.html example_id='kubernetes-hello-world' file_id='test_code' class='wide quick-start-examples' skip_learn_more=true skip_view_on_github=true skip_tags=true %}

The test code above uses Kubernetes helpers built into Terratest to run kubectl apply, wait for the service to come
up, get the service endpoint, make HTTP requests to the service (with plenty of retries), check the response is what
we expect, and runs kubectl delete at the end. You run this test with go test as well!

Give it a shot!

The above is just a small taste of what you can do with Terratest. To
learn more:

  1. Check out the examples and the corresponding automated tests for those examples for fully working (and tested!) sample code.
  2. Browse through the list of Terratest packages to get a sense of all the tools available in Terratest.
  3. Read our Testing Best Practices Guide.
  4. Check out real-world examples of Terratest usage in our open source infrastructure modules: Consul, Vault, Nomad.

Happy testing!


Docs 01 Getting Started Testing Terragrunt (`docs/_docs/01_getting-started/testing-terragrunt.md`)


Overview

Terratest provides two approaches for testing Terragrunt configurations:

Approach Use Case Package
Unit Testing individual units modules/terraform with TerraformBinary: "terragrunt"
Stack Testing a stack of units with --all commands modules/terragrunt

Unit Testing

For testing a single Terragrunt unit, use the terraform package with TerraformBinary set to "terragrunt":

go
func TestTerragruntModule(t *testing.T) {
    t.Parallel()

    ctx := t.Context()

    terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
        TerraformDir:    "../examples/my-module",
        TerraformBinary: "terragrunt",
    })

    defer terraform.DestroyContext(t, ctx, terraformOptions)
    terraform.ApplyContext(t, ctx, terraformOptions)

    output := terraform.OutputContext(t, ctx, terraformOptions, "my_output")
    assert.Equal(t, "expected_value", output)
}

Stack Testing

For testing a stack of units with dependencies, use the dedicated terragrunt package:

go
func TestStack(t *testing.T) {
    t.Parallel()

    ctx := t.Context()

    testFolder, err := files.CopyTerragruntFolderToTemp("../live/prod", t.Name())
    require.NoError(t, err)

    options := &terragrunt.Options{
        TerragruntDir: testFolder,
    }

    defer terragrunt.DestroyAllContext(t, ctx, options)
    terragrunt.ApplyAllContext(t, ctx, options)

    exitCode := terragrunt.PlanAllExitCodeContext(t, ctx, options)
    require.Equal(t, 0, exitCode)
}

Available Functions

Function Description
Init Run terragrunt init
ApplyAll Run terragrunt apply --all
DestroyAll Run terragrunt destroy --all
PlanAllExitCode Run terragrunt plan --all, return exit code
ValidateAll Run terragrunt validate --all
FormatAll Run terragrunt fmt --all
RunAll Run any command with --all flag

Stack Functions

For Terragrunt stacks:

Function Description
StackGenerate Generate stack from terragrunt.stack.hcl
StackRun Run command on generated stack
StackClean Remove .terragrunt-stack directory
Output Get stack output value
OutputAll Get all stack outputs as map

Further Reading


Docs 01 Getting Started Version Pinning (`docs/_docs/01_getting-started/version-pinning.md`)


Pin Terratest if you need reproducible test builds and deliberate control over when you adopt a new release.

Pin to a release

From the directory that contains your test module's go.mod:

bash
go get github.com/gruntwork-io/[email protected]
go mod tidy

Replace v0.56.0 with the tag you want from the Releases page. The same command upgrades, downgrades, or reverts the pin. Always commit go.mod and go.sum so the pin travels with your code; avoid @latest if you need reproducibility.

Use `go get`, not subpath requires

go get github.com/gruntwork-io/terratest@<tag> is enough; the pin applies to every subpackage your tests import. Avoid writing subpath requires by hand (e.g. go mod edit -require github.com/gruntwork-io/terratest/modules/terraform@<tag>); Go searches for a modules/terraform/<tag> tag and fails with unknown revision.

This applies to v1. In v2 each module is published separately and does carry its own modules/<name>/<tag> tag, so you require them individually. See migrating to v2.


Docs 02 Testing Best Practices Alternative Testing Tools (`docs/_docs/02_testing-best-practices/alternative-testing-tools.md`)


A list of infrastructure testing tools

Below is a list of other infrastructure testing tools you may wish to use in addition to Terratest. Check out How
Terratest compares to other testing tools
to understand the trade-offs.

  1. kitchen-terraform
  2. rspec-terraform
  3. serverspec
  4. inspec
  5. Goss
  6. awspec
  7. Terraform's acceptance testing framework
  8. ruby_terraform

Why Terratest?

Our experience with building the Infrastructure as Code Library
is that the only way to create reliable, maintainable infrastructure code is to have a thorough suite of real-world,
end-to-end acceptance tests. Without these sorts of tests, you simply cannot be confident that the infrastructure code
actually works.

This is especially important with modern DevOps, as all the tools are changing so quickly. Terratest has helped us
catch bugs not only in our own code, but also in AWS, Azure, Terraform, Packer, Kafka, Elasticsearch, CircleCI, and
so on. Moreover, by running tests nightly, we're able to catch backwards incompatible changes and
regressions in our dependencies (e.g., backwards incompatibilities in new versions of Terraform) as early as possible.

How Terratest compares to other testing tools

Most of the other infrastructure testing tools we've seen are focused on making it easy to check the properties of a
single server or resource. For example, the various xxx-spec tools offer a nice, concise language for connecting to
a server and checking if, say, httpd is installed and running. These tools are effectively verifying that individual
"properties" of your infrastructure meet a certain spec.

Terratest approaches the testing problem from a different angle. The question we're trying to answer is, "does the
infrastructure actually work?" Instead of checking individual server properties (e.g., is httpd installed and
running), we'll actually make HTTP requests to the server and check that we get the expected response; or we'll store
data in a database and make sure we can read it back out; or we'll try to deploy a new version of a Docker container
and make sure the orchestration tool can roll out the new container with no downtime.

Moreover, we use Terratest not only with individual servers, but to test entire systems. For example, the automated
tests for the Vault module do the following:

  1. Use Packer to build an AMI.
  2. Use Terraform to create self-signed TLS certificates.
  3. Use Terraform to deploy all the infrastructure: a Vault cluster (which runs the AMI from the previous step), Consul
    cluster, load balancers, security groups, S3 buckets, and so on.
  4. SSH to a Vault node to initialize the cluster.
  5. SSH to all the Vault nodes to unseal them.
  6. Use the Vault SDK to store data in Vault.
  7. Use the Vault SDK to make sure you can read the same data back out of Vault.
  8. Use Terraform to undeploy and clean up all the infrastructure.

The steps above are exactly what you would've done to test the Vault module manually. Terratest helps automate this
process. You can think of Terratest as a way to do end-to-end, acceptance or integration testing, whereas most other
tools are focused on unit or functional testing.


Docs 02 Testing Best Practices Avoid Test Caching (`docs/_docs/02_testing-best-practices/avoid-test-caching.md`)


Since Go 1.10, test results are automatically cached. This can lead to Go not
running your tests again if you haven't changed any of the Go code. Since you're probably mainly manipulating Terraform
files, you should consider turning the caching of test results off. This ensures that the tests are run every time
you run go test and the result is not just read from the cache.

To turn caching off, you can set the -count flag to 1 force the tests to run:

shell
$ go test -count=1 -timeout 30m -p 1 ./...

Docs 02 Testing Best Practices Cleanup (`docs/_docs/02_testing-best-practices/cleanup.md`)


Since automated tests with Terratest deploy real resources into real environments, you'll want to make sure your tests
always cleanup after themselves so you don't leave a bunch of resources lying around. Typically, you should use Go's
defer keyword to ensure that the cleanup code always runs, even if the test hits an error along the way.

For example, if your test runs terraform apply, you should run terraform destroy at the end to clean up:

go
ctx := t.Context()

// Ensure cleanup always runs
defer terraform.DestroyContext(t, ctx, options)

// Deploy
terraform.ApplyContext(t, ctx, options)

// Validate
checkServerWorks(t, options)

Of course, despite your best efforts, occasionally cleanup will fail, perhaps due to the CI server going down, or a bug
in your code, or a temporary network outage. To handle those cases, we run a tool called
cloud-nuke in our test AWS account on a nightly basis to clean up any
leftover resources.


Docs 02 Testing Best Practices Error Handling (`docs/_docs/02_testing-best-practices/error-handling.md`)


Just about every method foo in Terratest comes in two versions: foo and fooE (e.g., terraform.ApplyContext and
terraform.ApplyContextE).

  • foo: The base method takes a t *testing.T and a context.Context as arguments. If the method hits any errors,
    it calls t.Fatal to fail the test.

  • fooE: Methods that end with the capital letter E always return an error as the last argument and never call
    t.Fatal themselves. This allows you to decide how to handle errors.

You will use the base method name most of the time, as it allows you to keep your code more concise by avoiding
if err != nil checks all over the place:

go
ctx := t.Context()
terraform.InitContext(t, ctx, terraformOptions)
terraform.ApplyContext(t, ctx, terraformOptions)
url := terraform.OutputContext(t, ctx, terraformOptions, "url")

In the code above, if InitContext, ApplyContext, or OutputContext hits an error, the method will call t.Fatal
and fail the test immediately, which is typically the behavior you want. However, if you are expecting an error and
don't want it to cause a test failure, use the method name that ends with a capital E:

go
ctx := t.Context()

if _, err := terraform.InitContextE(t, ctx, terraformOptions); err != nil {
  // Do something with err
}

if _, err := terraform.ApplyContextE(t, ctx, terraformOptions); err != nil {
  // Do something with err
}

url, err := terraform.OutputContextE(t, ctx, terraformOptions, "url")
if err != nil {
  // Do something with err
}

As you can see, the code above is more verbose, but gives you more flexibility with how to handle errors.


Docs 02 Testing Best Practices Idempotent (`docs/_docs/02_testing-best-practices/idempotent.md`)


A Terraform configuration is idempotent when a second apply results in 0 changes. An idempotent configuration ensures that:

  1. What you define in Terraform is exactly what is being deployed.
  2. Detection of bugs in Terraform resources and providers that might affect your configuration.

You can use Terratest's terraform.ApplyAndIdempotentContext() function to both apply your Terraform configuration and
test its idempotency.

go
ctx := t.Context()

defer terraform.DestroyContext(t, ctx, terraformOptions)
terraform.ApplyAndIdempotentContext(t, ctx, terraformOptions)

If a second apply of your Terraform configuration results in changes then your test will fail.


Docs 02 Testing Best Practices Iterating Locally Using Docker (`docs/_docs/02_testing-best-practices/iterating-locally-using-docker.md`)


For most infrastructure code, your only option is to deploy into a real environment such as AWS. However, if you're
writing scripts (i.e., Bash, Python, or Go), you should be able to test them locally using Docker. Docker containers
typically build 10x faster and start 100x faster than real servers, so using Docker for testing can help you iterate
much faster.

Here are some techniques we use with Docker:

  • If your script is used in a Packer template, add a Docker
    builder
    to the template so you can create a Docker image from the
    same code. See the [Packer Docker Example](https://github.com/gruntwork-io/terratest/tree/{{ site.stable_ref }}/examples/packer-docker-example) for working sample code.

  • We have prebuilt Docker images for major Linux distros that have many important dependencies (e.g., curl, vim,
    tar, sudo) already installed. See the [test-docker-images folder](https://github.com/gruntwork-io/terratest/tree/{{ site.stable_ref }}/test-docker-images) for more details.

  • Create a docker-compose.yml to make it easier to run your Docker image with all the ports, environment variables,
    and other settings it needs. See the [Packer Docker Example](https://github.com/gruntwork-io/terratest/tree/{{ site.stable_ref }}/examples/packer-docker-example) for working sample code.

  • With scripts in Docker, you can replace some real-world dependencies with mocks! One way to do this is to create
    some "mock scripts" and to bind-mount them in docker-compose.yml in a way that replaces the real dependency. For
    example, if your script calls the aws CLI, you could create a mock script called aws that shows up earlier in the
    PATH. Using mocks allows you to test 100% locally, without external dependencies such as AWS.


Docs 02 Testing Best Practices Iterating Locally Using Test Stages (`docs/_docs/02_testing-best-practices/iterating-locally-using-test-stages.md`)


Most automated tests written with Terratest consist of multiple "stages", such as:

  1. Build an AMI using Packer
  2. Deploy the AMI using Terraform
  3. Validate that the AMI works as expected
  4. Undeploy the AMI using Terraform

Often, while testing locally, you'll want to re-run some subset of these stages over and over again: for example, you
might want to repeatedly run the validation step while you work out the kinks. Having to run all of these stages
each time you change a single line of code can be very slow.

This is where Terratest's teststructure package comes in handy: it allows you to explicitly break up your tests into
stages and to be able to disable any one of those stages by setting an environment variable. Check out the
[terraform_packer_example_test.go](https://github.com/gruntwork-io/terratest/blob/{{ site.stable_ref }}/test/terraform_packer_example_test.go)
for working sample code.

How to skip stages

To skip a stage, set SKIP_<stage_name> to any non-empty value. For example, to re-run deploy and validation without rebuilding the AMI:

bash
SKIP_build_ami=true go test -v -run TestTerraformPackerExample

This works because each stage saves its outputs (AMI IDs, Terraform options, etc.) to the working directory using functions like SaveString and SaveAmiId. Subsequent stages load this cached data using LoadString, LoadAmiId, etc. When any SKIP_* variable is set, Terratest also skips copying to a temp folder, preserving cached state between runs.


Docs 02 Testing Best Practices Namespacing (`docs/_docs/02_testing-best-practices/namespacing.md`)


Just about all resources your tests create (e.g., servers, load balancers, machine images) should be "namespaced" with
a unique name to ensure that:

  1. You don't accidentally overwrite any "production" resources in that environment (though as mentioned in the previous
    section, your test environment should be completely isolated from prod anyway).
  2. You don't accidentally clash with other tests running in parallel.

For example, when deploying AWS infrastructure with Terraform, that typically means exposing variables that allow you
to configure auto scaling group names, security group names, IAM role names, and any other names that must be unique.

You can use Terratest's random.UniqueID() function to generate identifiers that are short enough to use in resource
names (just 6 characters) but random enough to make it unlikely that you'll have a conflict.

go
uniqueID := random.UniqueID()
instanceName := fmt.Sprintf("terratest-http-example-%s", uniqueID)

terraformOptions := &terraform.Options {
  TerraformDir: "../examples/terraform-http-example",
  Vars: map[string]interface{} {
    "instance_name": instanceName,
  },
}

terraform.ApplyContext(t, t.Context(), terraformOptions)

Docs 02 Testing Best Practices Picking Instance Types (`docs/_docs/02_testing-best-practices/picking-instance-types.md`)


It's common to want to test infrastructure code that deploys EC2 instances into AWS.
There are many different instance types, but not all instance types
are available in all regions or availability zones
(AZs)
. For example,
t3.micro is sometimes available only in newer AZs, while t2.micro is sometimes only available in older AZs. If you
are testing code that needs to deploy a "small" instance across many regions, this can make it tricky to know which
region to pick.

To help work around this problem, Terratest includes
GetRecommendedInstanceTypeContext, a Go function that helps you pick a
recommended instance type.

`GetRecommendedInstanceTypeContext`

GetRecommendedInstanceTypeContext takes in an AWS region and a list of EC2 instance types and returns the first
instance type in the list that is available in all Availability Zones (AZs) in the given region. If there's no
instance available in all AZs, this function exits with an error.

Example usage:

go
ctx := t.Context()

aws.GetRecommendedInstanceTypeContext(t, ctx, "eu-west-1", []string{"t2.micro", "t3.micro"})
aws.GetRecommendedInstanceTypeContext(t, ctx, "ap-northeast-2", []string{"t2.micro", "t3.micro"})

Docs 02 Testing Best Practices Testing Environment (`docs/_docs/02_testing-best-practices/testing-environment.md`)


Since most automated tests written with Terratest can make potentially destructive changes in your environment, we
strongly recommend running tests in an environment that is totally separate from production. For example, if you are
testing infrastructure code for AWS, you should run your tests in a completely separate AWS account.

This means that you will have to write your infrastructure code in such a way that you can plug in (dependency
injection
) environment-specific details, such as account IDs,
domain names, IP addresses, etc. Adding support for this will typically make your code cleaner and more flexible.


Docs 02 Testing Best Practices Timeouts And Logging (`docs/_docs/02_testing-best-practices/timeouts-and-logging.md`)


Go's package testing has a default timeout of 10 minutes, after which it forcibly kills your testsβ€”even your cleanup
code won't run! It's not uncommon for infrastructure tests to take longer than 10 minutes, so you'll almost always
want to increase the timeout by using the -timeout option, which takes a go duration string (e.g 10m for 10
minutes or 1h for 1 hour):

bash
go test -timeout 30m

Note that many CI systems will also kill your tests if they don't see any log output for a certain period of time
(e.g., 10 minutes in CircleCI). If you use Go's t.Log and t.Logf for logging in your tests, you'll find that these
functions buffer all log output until the very end of the test (see https://github.com/golang/go/issues/24929 for more
info). If you have a long-running test, this might mean you get no log output for more than 10 minutes, and the CI
system will shut down your tests. Moreover, if your test has a bug that causes it to hang, you won't see any log output
at all to help you debug it.

Therefore, we recommend instead using Terratest's logger.Log and logger.Logf functions, which log to stdout
immediately:

go
func TestFoo(t *testing.T) {
  logger.Log(t, "This will show up in stdout immediately")
}

Finally, if you're testing multiple Go packages, be aware that Go will buffer log outputβ€”even that sent directly to
stdout by logger.Log and logger.Logfβ€”until all the tests in the package are done. This leads to the same
difficulties with CI servers and debugging. The workaround is to tell Go to test each package sequentially using the
-p 1 flag:

bash
go test -timeout 30m -p 1 ./...

See the Cleanup for more information on how to setup robust clean up procedures in the face of test timeouts and instabilities.


Docs 02 Testing Best Practices Tools And Plugins (`docs/_docs/02_testing-best-practices/tools-and-plugins.md`)


Tools and Plugins

This page contains a list of tools and plugins for Terratest to make integration with existing workflows easier. If you've created other tools that integrate with Terratest, a PR to add it to this list is very welcome!

Terratest Maven Plugin

The Terratest Maven Plugin aims to bring Terratest to the JVM world. Create your Go based tests beside your Java code with Maven and run them together. You can export the results into Json or an HTML page. As the plugin is MIT licensed, it is easy and painless to integrate into any Java+Maven combination. To learn more check out the website: Terratest Maven Plugin and the GitHub repository


Docs 02 Testing Best Practices Unit Integration End To End Test (`docs/_docs/02_testing-best-practices/unit-integration-end-to-end-test.md`)


For an introduction to Terratest, including unit tests, integration tests, end-to-end tests, dependency injection, test
parallelism, retries, error handling, and static analysis, see the talk "Automated Testing for Terraform, Docker,
Packer, Kubernetes, and More".

Link to the video at infoq.com.

Slides

Slides to the video can be found here: Slides: How to test infrastructure code{:target="_blank"}.


Docs 03 Migrating To V1 Azure (`docs/_docs/03_migrating-to-v1/azure.md`)


The modules/azure package received the largest set of breaking changes in
the v1.0.0 release. This guide walks through what changed and how to update
your tests.

Why we migrated

The previous version of modules/azure was built on
github.com/Azure/azure-sdk-for-go/services/..., the legacy "track 1" Azure
SDK. Microsoft has archived that SDK; it no longer receives feature updates,
bug fixes, or security patches.

v1.0.0 moves the entire package to
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/..., the modular,
actively maintained "track 2" SDK. The new SDK has a different shape: typed
resource clients are produced by a ClientFactory, response payloads put
most fields on a nested Properties struct, and pagination uses pagers
instead of iterators. We took the opportunity to land a few small API
cleanups at the same time so v1.0.0 ships a coherent, stable surface.

What changed at a glance

  • All Azure service code now imports sdk/resourcemanager/<service>/arm<service> packages instead of services/<service>/mgmt/<api-version>/<service>.
  • Resource fields moved under .Properties (e.g. vm.StorageProfile is now vm.Properties.StorageProfile).
  • Iterator-based list calls (NextWithContext) are replaced with pagers (NewListPager / More / NextPage).
  • 8 deprecated Get*ClientE client-getter functions were removed; the Create*ClientE replacements have been around for a while.
  • 4 CreateNew*ClientContextE factories were renamed to Create*ClientContextE. The old names remain as deprecated aliases.
  • NsgRuleSummary.SourceAdresssPrefixes (triple-s typo) was renamed to SourceAddressPrefixes.
  • A new *WithClient family of functions was added so tests can inject a fake or pre-built SDK client (useful with the Azure SDK's azfake package).
  • GetVirtualMachineImage / GetVirtualMachineImageE now return *VMImage instead of VMImage.

Updating SDK imports

Most Terratest users do not import the underlying Azure SDK directly,
because Terratest wraps it. If you only call terratest/modules/azure
helpers, you can usually skip this section. If your tests do import the SDK
(for example to construct request objects or assert on returned types),
update imports as follows:

Old (services/...) New (sdk/resourcemanager/...)
github.com/Azure/azure-sdk-for-go/services/compute/mgmt/.../compute github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6
github.com/Azure/azure-sdk-for-go/services/network/mgmt/.../network github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v6
github.com/Azure/azure-sdk-for-go/services/storage/mgmt/.../storage github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage
github.com/Azure/azure-sdk-for-go/services/cosmos-db/mgmt/.../documentdb github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/cosmos/armcosmos/v3
github.com/Azure/azure-sdk-for-go/services/servicebus/mgmt/.../servicebus github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/servicebus/armservicebus/v2
github.com/Azure/azure-sdk-for-go/services/preview/containerservice/.../containerservice github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v6
github.com/Azure/azure-sdk-for-go/services/containerregistry/mgmt/.../containerregistry github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerregistry/armcontainerregistry
github.com/Azure/azure-sdk-for-go/services/containerinstance/mgmt/.../containerinstance github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerinstance/armcontainerinstance/v2
github.com/Azure/azure-sdk-for-go/services/preview/operationalinsights/.../operationalinsights github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/operationalinsights/armoperationalinsights/v2
github.com/Azure/azure-sdk-for-go/services/resources/mgmt/.../subscriptions github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armsubscriptions
github.com/Azure/azure-sdk-for-go/services/resources/mgmt/.../resources github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources
github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/.../privatedns github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns
github.com/Azure/azure-sdk-for-go/profiles/latest/frontdoor/mgmt/frontdoor github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/frontdoor/armfrontdoor
github.com/Azure/azure-sdk-for-go/profiles/preview/preview/monitor/mgmt/insights github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/monitor/armmonitor
github.com/Azure/azure-sdk-for-go/services/recoveryservices/mgmt/.../recoveryservices github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/recoveryservices/armrecoveryservices
github.com/Azure/azure-sdk-for-go/services/recoveryservices/mgmt/.../backup github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/recoveryservices/armrecoveryservicesbackup/v4

Once imports are updated, expect three follow-on edits per file:

  1. Type names lose their old prefix and gain arm. For example
    compute.VirtualMachine becomes armcompute.VirtualMachine,
    network.SecurityGroup becomes armnetwork.SecurityGroup, and
    storage.Account becomes armstorage.Account.
  2. Field access moves under .Properties. For example
    vm.StorageProfile becomes vm.Properties.StorageProfile, and
    registry.LoginServer becomes registry.Properties.LoginServer.
  3. List iteration moves to the pager pattern: replace
    iterator.NextWithContext(ctx) loops with
    for pager.More() { page, err := pager.NextPage(ctx); ... }.

Renamed factory functions

Four client factories were renamed to drop the redundant New (a
Create*New*Client reads as redundant). The old names remain as deprecated
aliases for the v1 line; please update at your convenience.

Old name New name
CreateNewNetworkInterfacesClientE CreateNetworkInterfacesClientE
CreateNewNetworkInterfacesClientContextE CreateNetworkInterfacesClientContextE
CreateNewNetworkInterfaceIPConfigurationClientE CreateNetworkInterfaceIPConfigurationClientE
CreateNewNetworkInterfaceIPConfigurationClientContextE CreateNetworkInterfaceIPConfigurationClientContextE
CreateNewSubnetClientE CreateSubnetClientE
CreateNewSubnetClientContextE CreateSubnetClientContextE
CreateNewVirtualNetworkClientE CreateVirtualNetworkClientE
CreateNewVirtualNetworkClientContextE CreateVirtualNetworkClientContextE

Removed deprecated functions

The previous release marked eight client-getter functions for removal
("TODO: remove in next version"). v1.0.0 is that version. Each removed
function has a long-standing Create*ClientE replacement.

Removed Replacement
GetAvailabilitySetClientE CreateAvailabilitySetClientE
GetDiskClientE CreateDisksClientE
GetDiagnosticsSettingsClientE CreateDiagnosticsSettingsClientE
GetVMInsightsClientE CreateVMInsightsClientE
GetActivityLogAlertsClientE CreateActivityLogAlertsClientE
GetResourceGroupClientE CreateResourceGroupClientE
GetStorageAccountClientE CreateStorageAccountClientE
GetStorageBlobContainerClientE CreateStorageBlobContainerClientE

The replacements take the same arguments and return the same client type
(now from the new SDK). The rename is mechanical: Get β†’ Create. Note
that GetDiskClientE becomes CreateDisksClientE (plural) to match the
underlying SDK's DisksClient type.

Typo fix on `NsgRuleSummary`

NsgRuleSummary.SourceAdresssPrefixes (note the three s's) was renamed to
the correctly-spelled SourceAddressPrefixes. The field type
([]string) is unchanged. Update any code that read or set this field:

go
// Before
for _, prefix := range rule.SourceAdresssPrefixes {
    // ...
}

// After
for _, prefix := range rule.SourceAddressPrefixes {
    // ...
}

The paired DestinationAddressPrefixes field was already spelled
correctly and is unchanged.

`VMImage` is now a pointer

GetVirtualMachineImage and GetVirtualMachineImageE now return
*VMImage instead of VMImage, matching every other resource getter in
the package.

go
// Before
img := azure.GetVirtualMachineImage(t, vmName, rg, sub)
fmt.Println(img.Publisher)

// After
img := azure.GetVirtualMachineImage(t, vmName, rg, sub)
if img != nil {
    fmt.Println(img.Publisher)
}

If the resource cannot be loaded the function still fails the test, so
the nil guard is precautionary.

New `WithClient` variants for testability

v1.0.0 adds a parallel family of *WithClient functions across all Azure
modules. Each one accepts a pre-built SDK client and a
context.Context, so you can drive Terratest helpers against the Azure
SDK's azfake fake-server framework in unit tests:

go
import (
    "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6"
    "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v6/fake"
)

// Build a fake client that returns a canned response.
fakeServer := fake.DisksServer{ /* ... */ }
client, _ := armcompute.NewDisksClient("sub-id", nil, &arm.ClientOptions{
    ClientOptions: azcore.ClientOptions{
        Transport: fake.NewDisksServerTransport(&fakeServer),
    },
})

disk, err := azure.GetDiskWithClient(ctx, client, resourceGroup, diskName)

This is purely additive: the existing *ContextE functions still work and
build their own clients from ambient credentials. Use WithClient
variants only if you need test injection.

Search-and-replace cheatsheet

Most projects can do the bulk of the migration with a few find/replace
passes. The snippets below cover the most common edits:

text
/* Detailed source-code truncated for AI context efficiency. */

For the SDK migration itself we recommend doing one Azure service at a
time, starting with the import path, then fixing the resulting compile
errors (type names, .Properties access, pager loops). The Go compiler
is the most reliable migration tool here.

Need help

Open an issue on the Terratest repo with the azure label and a snippet
of the failing code. If you spot a gap in this guide, please send a PR
against docs/_docs/03_migrating-to-v1/azure.md.


Docs 04 Migrating To V2 Behavior Changes (`docs/_docs/04_migrating-to-v2/behavior-changes.md`)


Everything else in the v2 migration is a compile error. These two are not:
your code builds and behaves differently. Both are in k8s, so skip this
page if you do not use it, and see the v2
overview
for the rest of
the migration.

Node addresses prefer `ExternalIP`

k8s.FindNodeHostnameContextE, and GetServiceEndpointContextE for a
NodePort service, now return the ExternalIP recorded on the Node object
when one is present. They fall back to the internal hostname exactly as
before when it is not.

Cloud controller managers record an instance's public IP as an
ExternalIP. Terratest previously ignored that field and, on AWS, called
ec2:DescribeInstances to find the public IP instead. Reading the Node
object is the same answer without the API call, so:

  • ec2:DescribeInstances is no longer needed for this path
  • k8s no longer depends on the aws module, which removes 22 AWS service
    clients from its dependency graph

What to check. If your cluster advertises an ExternalIP and your test
previously received an internal hostname, it now receives the external
address. That is the documented behavior and almost certainly what you
wanted, but it is a different string. Tests that assert on the endpoint
value, or that rely on reaching the node over its internal address, are the
ones to look at.

Signatures are unchanged. The ExternalIP preference applies to every
provider. For AWS-backed nodes that advertise no ExternalIP, a new pair of
functions takes *KubectlOptions and consults
a lookup you provide:

go
options := k8s.NewKubectlOptions("", kubeconfig, "default")
options.NodePublicIPLookup = aws.GetPublicIpsOfEc2InstancesContextE

hostname, err := k8s.FindNodeHostnameWithOptionsContextE(t, ctx, options, node)

NodePublicIPLookup is only consulted after the Node's own ExternalIP
has been checked, so most callers can leave it nil.

`KubectlOptions` carrying a `RestConfig` cannot be saved

json.Marshal of a KubectlOptions built by
NewKubectlOptionsWithRestConfig now fails with an error wrapping
k8s.ErrRestConfigNotSerializable. Match it with errors.Is, not ==:
encoding/json returns a *json.MarshalerError around it. This affects
k8s.SaveKubectlOptions, teststructure.SaveTestData, and any code of
your own that marshals options.

This already failed in v1, with an opaque json: unsupported type: transport.WrapperFunc, because rest.Config holds func-typed fields that
encoding/json rejects. What changed is that the error now says what is
wrong and what to do instead.

It is deliberately an error rather than silently dropping the config.
Dropped, the reloaded options would carry no cluster identity at all, fall
back to the ambient kubeconfig, and run your test against a different
cluster.

What to do. For staged tests, build options from a kubeconfig path or
from in-cluster auth. Both round trip:

go
options := k8s.NewKubectlOptions(contextName, configPath, namespace)
// or
options := k8s.NewKubectlOptionsWithInClusterAuth()

If you need a rest.Config at runtime, keep building one, but rebuild it
in each stage rather than saving it.


Docs 04 Migrating To V2 Import Map (`docs/_docs/04_migrating-to-v2/import-map.md`)


The complete v1 to v2 path mapping. See rewriting
imports
for how
to apply it in bulk.

Collapsed into `core`

Six utility packages became subpackages of one module. The package
identifier at call sites is unchanged.

v1 v2
modules/random modules/core/v2/random
modules/files modules/core/v2/files
modules/logger modules/core/v2/logger
modules/shell modules/core/v2/shell
modules/retry modules/core/v2/retry
modules/testing modules/core/v2/testing

modules/logger/parser becomes modules/core/v2/logger/parser.

modules/core/v2/formatting is new in v2 and has no v1 equivalent to
migrate: it was internal/lib/formatting, which was never importable.

Renamed

Path and package identifier change.

v1 v2
modules/http-helper, http_helper.X modules/httphelper/v2, httphelper.X
modules/dns-helper, dns_helper.X modules/dnshelper/v2, dnshelper.X
modules/test-structure, test_structure.X modules/teststructure/v2, teststructure.X

Suffix only

Path gains /v2; package identifier unchanged.

v1 v2
modules/aws modules/aws/v2
modules/azure modules/azure/v2
modules/gcp modules/gcp/v2
modules/k8s modules/k8s/v2
modules/helm modules/helm/v2
modules/ssh modules/ssh/v2
modules/docker modules/docker/v2
modules/packer modules/packer/v2
modules/database modules/database/v2
modules/opa modules/opa/v2
modules/terraform modules/terraform/v2
modules/terragrunt modules/terragrunt/v2

Removed

v1 Replacement
modules/collections stdlib slices
modules/environment stdlib os.Getenv
modules/git stdlib os/exec
modules/slack none; vendor from v1 if needed
modules/version-checker none; shell out
modules/oci none; Oracle Cloud is not carried forward to v2
cmd/pick-instance-type none
cmd/terratest_log_parser none as a binary; the library survives at modules/core/v2/logger/parser

These were deprecated in v1 first and deleted at the v2 cutover. If you
depend on slack, version-checker or oci, v1 stays available and is
the place to stay.


Docs 04 Migrating To V2 Rewriting Imports (`docs/_docs/04_migrating-to-v2/rewriting-imports.md`)


Every v2 import path changes. This page covers doing that in bulk, then the
symbol relocations, then the cases a scripted rewrite cannot finish on its
own.

The commands below are written for BSD sed, which is what macOS ships.
On Linux, drop the '' after -i. They use # as the delimiter rather
than |, because | collides with regex alternation, and they avoid \b,
which BSD sed does not support and silently ignores.

1. Collapse the utility packages into `core`

bash
find . -name '*.go' -exec sed -i '' -E \
  's#gruntwork-io/terratest/modules/(random|files|logger|shell|retry|testing)#gruntwork-io/terratest/modules/core/v2/\1#g' {} +

2. Rename the three hyphenated packages

Path, package identifier, and any stale alias:

bash
find . -name '*.go' -exec sed -i '' -E \
  -e 's#gruntwork-io/terratest/modules/http-helper#gruntwork-io/terratest/modules/httphelper/v2#g' \
  -e 's#gruntwork-io/terratest/modules/dns-helper#gruntwork-io/terratest/modules/dnshelper/v2#g' \
  -e 's#gruntwork-io/terratest/modules/test-structure#gruntwork-io/terratest/modules/teststructure/v2#g' \
  -e 's#(^|[^A-Za-z0-9_])http_helper\.#\1httphelper.#g' \
  -e 's#(^|[^A-Za-z0-9_])dns_helper\.#\1dnshelper.#g' \
  -e 's#(^|[^A-Za-z0-9_])test_structure\.#\1teststructure.#g' \
  -e 's#^([[:space:]]*)(http_helper|dns_helper|test_structure) "#\1"#' {} +

That last expression matters. These packages were commonly imported under
an explicit alias:

go
test_structure "github.com/gruntwork-io/terratest/modules/test-structure"

Rewriting only the path leaves the old alias bound to the new package, so
every rewritten call site fails with undefined: teststructure. The
expression drops the alias so the package name applies.

3. Add the `/v2` suffix to the rest

bash
find . -name '*.go' -exec sed -i '' -E \
  's#gruntwork-io/terratest/modules/(aws|azure|gcp|k8s|helm|ssh|docker|packer|database|opa|terraform|terragrunt)([^/a-z]|$)#gruntwork-io/terratest/modules/\1/v2\2#g' {} +

4. Reformat

The rewrite reorders import paths alphabetically, so the blocks are no
longer sorted:

bash
gofmt -w .

Symbol relocations

Eight functions moved to the module that owns the type they operate on, so
teststructure no longer requires aws, k8s, packer and ssh.
Signatures and on-disk filenames are unchanged, so this is a qualifier
swap.

v1 v2
test_structure.{Save,Load}Ec2KeyPair aws.{Save,Load}Ec2KeyPair
test_structure.{Save,Load}KubectlOptions k8s.{Save,Load}KubectlOptions
test_structure.{Save,Load}PackerOptions packer.{Save,Load}PackerOptions
test_structure.{Save,Load}SSHKeyPair ssh.{Save,Load}SSHKeyPair

The target module is usually already imported, because the value being
saved came from it. Where it is not, add the import, and re-run go mod tidy afterwards since this can pull in a module you did not previously
require.

Everything else stays in teststructure: RunTestStage,
CopyTerraformFolderToTemp, the Terraform option helpers,
SaveString/LoadString, SaveInt/LoadInt,
SaveArtifactID/LoadArtifactID, and the generic
SaveTestData/LoadTestData.

Files that alias Terratest's `aws`

A file importing both the AWS SDK and Terratest's aws usually binds plain
aws to the SDK:

go
import (
    "github.com/aws/aws-sdk-go-v2/aws"
    terraAws "github.com/gruntwork-io/terratest/modules/aws/v2"
)

Here the relocation above resolves to the SDK and fails to compile. Use
that file's alias: terraAws.LoadEc2KeyPair. This is the one place the
scripted rewrite needs a human, and the compiler will point at it.

Verify

No v1 paths left, and everything still builds:

bash
grep -rn 'gruntwork-io/terratest/modules/' --include='*.go' . | grep -v '/v2'
go test -run '^$' ./...

The grep should print nothing. Use go test -run '^$' rather than
go build: it compiles _test.go files without running anything, and for
a Terratest suite that is where all of your code lives.


Docs 05 Community Contributing (`docs/_docs/05_community/contributing.md`)


layout: collection-browser-doc
title: Contributing
category: community
excerpt: >-
Terratest is an open source project, and contributions from the community are very welcome!
tags: ["contributing", "community"]
order: 500
nav_title: Documentation
nav_title_link: /docs/
custom_js:

  • examples
  • prism
  • collection-browser_scroll
  • collection-browser_search
  • collection-browser_toc

Terratest is an open source project, and contributions from the community are very welcome! Please check out the
Contribution Guidelines and Developing Terratest for
instructions.

Contribution Guidelines

Contributions to this repo are very welcome! We follow a fairly standard pull request
process
for contributions, subject to the following guidelines:

  1. Types of contributions
  2. File a GitHub issue
  3. Update the documentation
  4. Update the tests
  5. Update the code
  6. Create a pull request
  7. Merge and release

Types of contributions

Broadly speaking, Terratest contains two types of helper functions:

  1. Integrations with external tools
  2. Infrastructure and validation helpers

We accept different types of contributions for each of these two types of helper functions, as described next.

Integrations with external tools

These are helper functions that integrate with various DevOps toolsβ€”e.g., Terraform, Docker, Packer, and
Kubernetesβ€”that you can use to deploy infrastructure in your automated tests. Examples:

  • terraform.InitAndApplyContext: run terraform init and terraform apply.
  • packer.BuildArtifactsContext: run packer build.
  • shell.RunCommandContextAndGetOutput: run an arbitrary shell command and return stdout and stderr as a string.

Here are the guidelines for contributions with external tools:

  1. Fixes and improvements to existing integrations: All bug fixes and new features for existing tool integrations
    are very welcome!

  2. New integrations: Before contributing an integration with a totally new tool, please file a GitHub issue to
    discuss with us if it's something we are interested in supporting and maintaining. For example, we may be open to
    new integrations with Docker and Kubernetes tools, but we may not be open to integrations with Chef or Puppet, as
    there are already testing tools available for them.

Infrastructure and validation helpers

These are helper functions for creating, destroying, and validating infrastructure directly via API calls or SDKs.
Examples:

  • httphelper.HTTPGetWithRetryContext: make an HTTP request, retrying until you get a certain expected response.
  • ssh.CheckSSHCommandContext: SSH to a server and execute a command.
  • aws.CreateS3BucketContext: create an S3 bucket.
  • aws.GetPrivateIpsOfEc2InstancesContext: use the AWS APIs to fetch IPs of some EC2 instances.

The number of possible such helpers is nearly infinite, so to avoid Terratest becoming a gigantic, sprawling library
we ask that contributions for new infrastructure helpers are limited to:

  1. Platforms: we currently only support three major public clouds (AWS, GCP, Azure) and Kubernetes. There is some
    code contributed earlier for other platforms (e.g., OCI), but until we have the time/resources to support those
    platforms fully, we will only accept contributions for the major public clouds and Kubernetes.

  2. Complexity: we ask that you only contribute infrastructure and validation helpers for code that is relatively
    complex to do from scratch. For example, a helper that merely wraps an existing function in the AWS or GCP SDK is
    not a great choice, as the wrapper isn't contributing much value, but is bloating the Terratest API. On the other
    hand, helpers that expose simple APIs for complex logic are great contributions: ssh.CheckSSHCommandContext is a
    great example of this, as it provides a simple one-line interface for dozens of lines of complicated SSH logic.

  3. Popularity: Terratest should only contain helpers for common use cases that come up again and again in the
    course of testing. We don't want to bloat the library with lots of esoteric helpers for rarely used tools, so
    here's a quick litmus test: (a) Is this helper something you've used once or twice in your own tests, or is it
    something you're using over and over again? (b) Does this helper only apply to some use case specific to your
    company or is it likely that many other Terratest users are hitting this use case over and over again too?

  4. Creating infrastructure: we try to keep helper functions that create infrastructure (e.g., use the AWS SDK to
    create an S3 bucket or EC2 instance) to a minimum, as those functions typically require maintaining state (so that
    they are idempotent and can clean up that infrastructure at the end of the test) and dealing with asynchronous and
    eventually consistent cloud APIs. This can be surprisingly complicated, so we typically recommend using a tool like
    Terraform, which already handles all that complexity, to create any infrastructure you need at test time, and
    running Terratest's built-in terraform helpers as necessary. If you're considering contributing a function that
    creates infrastructure directly (e.g., using a cloud provider's APIs), please file a GitHub issue to explain why
    such a function would be a better choice than using a tool like Terraform.

File a GitHub issue

Before starting any work, we recommend filing a GitHub issue in this repo. This is your chance to ask questions and
get feedback from the maintainers and the community before you sink a lot of time into writing (possibly the wrong)
code. If there is anything you're unsure about, just ask!

Update the documentation

We recommend updating the documentation before updating any code (see Readme Driven
Development
). This ensures the documentation
stays up to date and allows you to think through the problem at a high level before you get lost in the weeds of
coding.

The documentation is built with Jekyll and hosted on the Github Pages from docs folder on main branch. Check out Terratest website to learn more about working with the documentation.

Update the tests

We also recommend updating the automated tests before updating any code (see Test Driven
Development
). That means you add or update a test case,
verify that it's failing with a clear error message, and then make the code changes to get that test to pass. This
ensures the tests stay up to date and verify all the functionality in this Module, including whatever new
functionality you're adding in your contribution. The instructions for running the automated tests can be
found here.

Update the code

At this point, make your code changes and use your new test case to verify that everything is working. As you work,
please make every effort to avoid unnecessary backwards incompatible changes. This generally means that you should
not delete or rename anything in a public API.

If a backwards incompatible change cannot be avoided, please make sure to call that out when you submit a pull request,
explaining why the change is absolutely necessary.

Note that we use pre-commit hooks with this project. To ensure they run:

  1. Install pre-commit.
  2. Run pre-commit install.

One of the pre-commit hooks we run is goimports. To prevent the
hook from failing, make sure to :

  1. Install goimports
  2. Run goimports -w ..

We have a style guide for the Go programming language,
in which we documented some best practices for writing Go code. Please ensure your code adheres to the guidelines
outlined in the guide.

Create a pull request

Create a pull request with your changes. Please make sure
to include the following:

  1. A description of the change, including a link to your GitHub issue.
  2. The output of your automated test run, preferably in a GitHub Gist. We cannot run
    automated tests for pull requests automatically due to security
    concerns
    , so we need you to manually provide this
    test output so we can verify that everything is working.
  3. Any notes on backwards incompatibility or downtime.

Validate the Pull Request for Azure Platform

If you're contributing code for the Azure Platform and if you have an active Azure subscription, it's recommended to follow the below guidelines after creating a pull request. If you're contributing code for any other platform (e.g., AWS, GCP, etc), you can skip these steps.

Once the Terratest maintainers add Azure tag and Approve the PR, following pipeline will run automatically to perform a full validation of the Azure contribution. You also can run the pipeline manually on your forked repo by following the below guideline.

We have a separate CI pipeline for Azure code. To run it on a forked repo:

  1. Run the following Azure Cli command on your preferred Terminal to create Azure credentials and copy the output:

    bash
    az ad sp create-for-rbac --name "terratest-az-cli" --role contributor --sdk-auth
  2. Go to Secrets settings page under Settings tab in your forked project, https://github.com/<YOUR_GITHUB_ACCOUNT>/terratest/settings, on GitHub.

  3. Create a new Secret named AZURE_CREDENTIALS and paste the Azure credentials you copied from the 1st step as the value

    AZURE_CREDENTIALS will be stored in your GitHub account; neither the Terratest maintainers nor anyone else will have any access to it. Under the hood, GitHub stores your secrets in a secure, encrypted format (see: GitHub Actions Secrets Reference for more information). Once the secret is created, it's only possible to update or delete it; the value of the secret can't be viewed. GitHub uses a libsodium sealed box to help ensure that secrets are encrypted before they reach GitHub.

  4. Create a new Personal Access Token (PAT) page under Settings / Developer Settings, making sure write:discussion and public_repo scopes are checked. Click the Generate token button and copy the generated PAT.

  5. Go back to settings/secrets in your fork and Create a new Secret named PAT. Paste the output from the 4th step as the value

    PAT will be stored in your GitHub account; neither the Terratest maintainers nor anyone else will have any access to it. Under the hood, GitHub stores your secrets in a secure, encrypted format (see: GitHub Actions Secrets Reference for more information). Once the secret is created, it's only possible to update or delete it; the value of the secret can't be viewed. GitHub uses a libsodium sealed box to help ensure that secrets are encrypted before they reach GitHub.

  6. Go to Actions tab on GitHub (https://github.com//terratest/actions)

  7. Click ci-workflow workflow

  8. Click Run workflow button and fill the fields in the drop down

    • Repository Info : name of the forked repo (e.g. xyz/terratest)

    • Name of the branch : branch name on the forked repo (e.g. feature/adding-some-important-module)

    • Name of the official terratest repo : home of the target pr (gruntwork-io/terratest)

    • PR number on the official terratest repo : pr number on the official terratest repo (e.g. 14, 25, etc.). Setting this value will leave a success/failure comment in the PR once CI completes execution.

    • Skip provider registration : set true if you want to skip terraform provider registration for debug purposes (false or true)

  9. Wait for the ci-workflow to be finished

    The pipeline will use the given Azure subscription and deploy real resources in your Azure account as part of running the test. When the tests finish, they will tear down the resources they created. Of course, if there is a bug or glitch that prevents the clean up code from running, some resources may be left behind, but this is rare. Note that these resources may cost you money! You are responsible for all charges in your Azure subscription.

  10. PR with the given PR Number will have the result of the ci-workflow as a comment

Merge and release

The maintainers for this repo will review your code and provide feedback. Once the PR is accepted, they will merge the
code and release a new version, which you'll be able to find in the releases page.

Developing Terratest

  1. Running tests
  2. Versioning
  3. Developing For Azure

Running tests

Terratest itself includes a number of automated tests.

Note #1: Some of these tests create real resources in an AWS account. That means they cost money to run, especially
if you don't clean up after yourself. Please be considerate of the resources you create and take extra care to clean
everything up when you're done!

Note #2: In order to run tests that access your AWS account, you will need to configure your AWS CLI
credentials
. For example, you could
set the credentials as the environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY.

Note #3: Never hit CTRL + C or cancel a build once tests are running or the cleanup tasks won't run!

Prerequisite: The tests expect Terraform, Terragrunt, Packer, and/or Docker to already be installed and in your PATH.

To run all the tests:

bash
go test -v -timeout 30m -p 1 ./...

To run the tests in a specific folder:

bash
cd "<FOLDER_PATH>"
go test -timeout 30m

To run a specific test in a specific folder:

bash
cd "<FOLDER_PATH>"
go test -timeout 30m -run "<TEST_NAME>"

Versioning

This repo follows the principles of Semantic Versioning. You can find each new release,
along with the changelog, in the Releases Page.

Starting with 1.0.0, breaking changes to the public API only happen in major releases. Symbols renamed or replaced
inside the v1 line are kept as // Deprecated: aliases so test code that compiled against an earlier v1.x.y release
will keep compiling against later ones; full removal is deferred to v2.

Developing For Azure

Azure supports multiple cloud environments. In order to properly register the correct environment for you test code, you need to use the Azure SDK Client Factory.

Azure SDK Client Factory

This documentation provides and overview of the client_factory.go module, targeted use cases, and behaviors. This module is intended to provide support for and simplify working with Azure's multiple cloud environments (Azure Public, Azure Government, Azure China, Azure Germany and Azure Stack). Developers looking to contribute to additional support for Azure to Terratest should leverage client_factory and use the patterns below to add a resource REST client from Azure Go SDK. By doing so, it provides a consistent means for developers using Terratest to test their Azure Infrastructure to connect to the correct cloud and its associated REST apis.

Background

The Azure REST APIs support both Public and sovereign cloud environments (at the moment this includes Public, US Government, Germany, China, and Azure Stack environments). If you are interacting with an environment other than public cloud, you need to set the base URI for the Azure REST API you are interacting with.

Base URI

You must use the correct base URI's for the Azure REST API's (either directly or via Azure SDK for GO) to communicate with a cloud environment other than Azure Public. The Azure Go SDK supports this by using the WithBaseURI suffixed calls when creating service clients. For example, when using the VirtualMachinesClient with the public cloud, a developer would normally write code for the public cloud like so:

go
import (
    "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
)

func SomeVMHelperMethod() {
    subscriptionID := "your subscription ID"

    // Create a VM client and return
    vmClient, err := compute.NewVirtualMachinesClient(subscriptionID)

    // Use client / etc
}

However, this code will not work in non-Public cloud environments as the REST endpoints have different URIs depending on environment. Instead, you need to use an alternative method (provided in the Azure REST SDK for Go) to get a properly configured client (all REST API clients should support this alternate method):

go
import (
    "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-07-01/compute"
)

func SomeVMHelperMethod() {
    subscriptionID := "your subscription ID"
    baseURI := "management.azure.com"

    // Create a VM client and return
    vmClient, err := compute.NewVirtualMachinesClientWithBaseURI(baseURI, subscriptionID)

    // Use client / etc
}

Using code similar to above, you can communicate with any Azure cloud environment just by changing the base URI that is passed to the clients (Azure Public shown in above example).

Lookup Environment Metadata

Developers MUST avoid hardcoding these base URI's. Instead, they should be looked up from an authoritative source. The AutoRest-GO library (used by the Go SDK) provides such functionality. The client_factory module makes use of the AutoRest EnvironmentFromName(envName string) function to return the appropriate structure. This method and Environment structure is documented on GoDoc here.

To configure different cloud environments, we will use the same AZURE_ENVIRONMENT environment variable that the Go SDK uses. This can currently be set to one of the following values:

Value Cloud Environment
"AzureChinaCloud" ChinaCloud
"AzureGermanCloud" GermanCloud
"AzurePublicCloud" PublicCloud
"AzureUSGovernmentCloud" USGovernmentCloud
"AzureStackCloud" Azure stack

When using the "AzureStackCloud" setting, you MUST also set the AZURE_ENVIRONMENT_FILEPATH variable to point to a JSON file containing your Azure Stack URI details.

Putting it all together

client_factory implements this pattern described above in order to instantiate and return properly configured REST SDK for GO clients so that test implementers don't have to consider REST API client implementation as long as they have the correct AZURE_ENVIRONMENT env setting. If this environment variable is not set, the client will assume public cloud as the cloud environment to communicate with. We strongly recommend developers creating Terratest helper methods for Azure use this pattern with client factory to create REST API clients. This will reduce effort for Terratest users creating test for Azure resources.

Note the following:

  • TERRAFORM uses ARM_ENVIRONMENT environment variable to set the correct cloud environment.
  • The default behavior of the client_factory is to use the AzurePublicCloud environment. This requires no work from the developer to configure, and ensures consistent behavior with the current SDK code.

Wait, I don't see the client in client factory for the rest api I want to interact with

If you require a client that is not already implemented in client factory for your helper method, you will need to create a corresponding method that instantiates the client and accepts base URI following the patterns discussed. Below is a walkthrough for adding a client to client factory.

Walkthrough, adding a client to client_factory

Add your client namespace to client factory

In the Azure SDK for GO, each service should have a module that implements that services client. You can find the correct module here. Add that module to the client factory imports. Below is an example for client imports that shows clients for compute, container service and subscriptions.

{% include examples/explorer.html example_id='client-factory' file_id='client_factory_code' class='wide quick-start-examples' skip_learn_more=true skip_view_on_github=true skip_tags=true snippet_id='client_factory_example.imports' %}

Add your client method to instantiate the client

The next step is to add your method to instantiate the client. Below is an example of adding the method to create a client for Virtual Machines, note that we lookup the environment using getEnvironmentEndpointE and then pass that base URI to the actual method on the Virtual Machines Module to create the client NewVirtualMachinesClientWithBaseURI.

{% include examples/explorer.html example_id='client-factory' file_id='client_factory_code' class='wide quick-start-examples' skip_learn_more=true skip_view_on_github=true skip_tags=true snippet_id='client_factory_example.CreateClient' %}

Add a unit test to client_factory_test.go

In order to ensure that your CreateClient method works properly, add a unit test to client_factory_test.go. The unit test MUST assert that the base URI is correctly set for your client. Some key points for writing your unit test are:

  • Use table-driven testing to test the various combinations of cloud environments
  • Give the test case a descriptive name so it is easy to identify which test failed.
  • PRs will be rejected if a client is added without a corresponding unit test.

Below is an example of the Virtual Machines client unit test:

{% include examples/explorer.html example_id='client-factory' file_id='client_factory_test' class='wide quick-start-examples' skip_learn_more=true skip_view_on_github=true skip_tags=true snippet_id='client_factory_example.UnitTest' %}

Use your CreateClient method in your helper

We now can use this client creation method in our helpers to create a Virtual Machines client. Below is an example for how to call into this create method from client_factory:

{% include examples/explorer.html example_id='client-factory' file_id='client_factory_helper' class='wide quick-start-examples' skip_learn_more=true skip_view_on_github=true skip_tags=true snippet_id='client_factory_example.helper' %}


Docs 05 Community License (`docs/_docs/05_community/license.md`)


License

This code is released under the Apache 2.0 License. See LICENSE{:target="_blank"} and NOTICE{:target="_blank"} for more details.


Docs 05 Community Support (`docs/_docs/05_community/support.md`)


Github Discussions

Search our Knowledge Base to find existing questions or ask your own. Github Discussions is a good place for general discussions and questions.

Github Issues

Read through existing issues or post a new one. Github issues is a good place to:

  • report a bug,

  • ask for a help,

  • ask for improvements,

  • to start contributing by solving simple issues.

Commercial support

Does your company rely on Terratest in production? If so, you can get commercial support directly from Gruntwork, the creators of Terratest! Check out the Gruntwork Support Page for more details.


Pages 404 404 (`docs/_pages/404/404.md`)


The requested page could not be found.


Assets Img Favicon Manifest.Json (`docs/assets/img/favicon/manifest.json`)

{
"name": "App",
"icons": [
{
"src": "/assets/img/favicon/android-icon-36x36.png",
"sizes": "36x36",
"type": "image/png",
"density": "0.75"
},
{
"src": "/assets/img/favicon/android-icon-48x48.png",
"sizes": "48x48",
"type": "image/png",
"density": "1.0"
},
{
"src": "/assets/img/favicon/android-icon-72x72.png",
"sizes": "72x72",
"type": "image/png",
"density": "1.5"
},
{
"src": "/assets/img/favicon/android-icon-96x96.png",
"sizes": "96x96",
"type": "image/png",
"density": "2.0"
},
{
"src": "/assets/img/favicon/android-icon-144x144.png",
"sizes": "144x144",
"type": "image/png",
"density": "3.0"
},
{
"src": "/assets/img/favicon/android-icon-192x192.png",
"sizes": "192x192",
"type": "image/png",
"density": "4.0"
}
]
}


--- METRICS ---