# Technical Documentation: gruntwork-io/terratest

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/gruntwork-io/terratest)

### Overview (`README.md`)

# Terratest

[](https://gruntwork.io/?ref=repo_terratest)
[](https://pkg.go.dev/mod/github.com/gruntwork-io/terratest?tab=overview)


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](https://terratest.gruntwork.io/docs/getting-started/version-pinning/).

## Stability and versioning

Starting with v1.0.0, Terratest follows [semantic versioning](https://semver.org/). 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](https://terratest.gruntwork.io/docs/migrating-to-v1/overview/). Migrating from v1 to v2: see the [v2 migration guide](https://terratest.gruntwork.io/docs/migrating-to-v2/overview/).

**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

- [Terratest Website](https://terratest.gruntwork.io)
- [Getting started with Terratest](https://terratest.gruntwork.io/docs/getting-started/quick-start/)
- [Terratest Documentation](https://terratest.gruntwork.io/docs/)
- [Contributing to Terratest](https://terratest.gruntwork.io/docs/community/contributing/)
- [Commercial Support](https://gruntwork.io/support/)

## License

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

Copyright &copy; 2025 Gruntwork, Inc.

---

### Overview (`docs/README.md`)

# Terratest website

This is the code for the [Terratest website](https://terratest.gruntwork.io).

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](https://github.com/gruntwork-io/terratest).

## Run

1. Install [Ruby](https://www.ruby-lang.org/en/documentation/installation/). Version 2.4 or above is recommended.
   Consider using [rbenv](https://github.com/rbenv/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/](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](http://tom.preston-werner.com/2010/08/23/readme-driven-development.html)). 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](#run).

1. [Change content on the existing page](#change-content-on-the-existing-page)
2. [Add a new page](#add-a-new-page)
3. [Remove or rename page](#remove-or-rename-page)
4. [Add custom redirection](#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:

```
---
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.

3. 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:

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


## Navigation

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
```
|-- _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*](https://terratest.gruntwork.io/docs) is implemented as a Jekyll collection and built with [*Collection Browser*](#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`.
```
---
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`:
```
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.
```
2. Create a folder for collection in root directory, e.g: `_my-collection` (change name)
3. Add documents to the `_my-collection` folder and set proper meta tags (see: [Adding new docs to collections](#adding-new-docs-to-collections)).
4. Create folder for collection's index page in `_pages`. Use collection name, e.g: `_pages/my-collection`.
5. Add `index.html` file to newly create folder:
```
---
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' %}
```
6. Change `title`, `subtitle`, `excerpt`, `permalink`, and `slug` in meta tags.
7. 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`
```
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.
```
2. Create a folder for collection in root directory: `_my-collection`
3. Add documents (`.md` format is recommended) to the `_my-collection` folder.
4. In each document add:
```
---
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
---
```
5. Create `index` page for collection. Create folder with collection name in `_pages`: `my-collection`
6. Add `index.html` in `_pages/my-collection`:
```
---
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.

#### Navigation Sidebar

The navigation sidebar is built in `_includes/collection_browser/navigation/_collection_toc.html`. Read more: [Navigation](#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:
```
$ pandoc --from=gfm --to=asciidoc --wrap=none --atx-headers  input.md > output.adoc
```
3. 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:
```
$ 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:

```
$ 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](/README.md#unit-tests), we recommend using [Packer](https://packer.io) to
build a Docker image using the same script [provisioners](https://www.packer.io/docs/templates/provisioners.html) 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](https://docs.docker.com/v17.09/engine/userguide/eng-image/dockerfile_best-practices/).
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/azure/terraform-azure-\*-example_test.go](../../test/azure)
- Test APIs which provide the actual Azure resource property values via the azure-sdk-for-go are located in the folder:
  - [modules/azure](../../modules/azure)

## Go Dependencies

Install [Golang](https://golang.org/) 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](https://github.com/gruntwork-io/terratest/blob/main/go.mod) includes the appropriate [azure-sdk-for-go version](https://github.com/Azure/azure-sdk-for-go/releases/tag/v46.1.0):

```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](https://docs.microsoft.com/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#set-up-terraform-access-to-azure) and also that we set the [environment variables](https://docs.microsoft.com/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#configure-terraform-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](../../modules/azure/client_factory.go) 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](/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](https://www.docker.com/) and make sure it's on your `PATH`.
1. Run `docker build -t gruntwork/docker-hello-world-example .`.
1. Run `docker run -it --rm gruntwork/docker-hello-world-example cat /test.txt`.
1. You should see the text "Hello, World!"




## Running automated tests against the Docker container

1. Install [Docker](https://www.docker.com/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `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:

- [helm_basic_example_template_test.go](/test/helm_basic_example_template_test.go): the template tests for this chart.
- [helm_basic_example_integration_test.go](/test/helm_basic_example_integration_test.go): the integration test for this
  chart. This test will deploy the Helm Chart and verify the `Service` endpoint.

## Running automated tests against this Helm Chart

1. Install and setup [helm](https://docs.helm.sh/using_helm/#installing-helm)
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `go test -v -tags helm -run TestHelmBasicExampleTemplate` for the template test
1. `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:

- [helm_basic_example_template_test.go](/test/helm_basic_example_template_test.go): the template tests for this chart.

## Running automated tests against this Helm Chart

1. Install and setup [helm](https://docs.helm.sh/using_helm/#installing-helm)
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `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:
- [kubernetes_basic_example_test.go](../../test/kubernetes_basic_example_test.go) for the most basic verification
- [kubernetes_basic_example_service_check_test.go](../../test/kubernetes_basic_example_service_check_test.go) for a more
  advanced version of checking the service.


## Deploying the Kubernetes resource

1. Setup a Kubernetes cluster. We recommend using a local version:
    - [minikube](https://github.com/kubernetes/minikube)
    - [Kubernetes on Docker For Mac](https://docs.docker.com/docker-for-mac/kubernetes/)
    - [Kubernetes on Docker For Windows](https://docs.docker.com/docker-for-windows/kubernetes/)

1. Install and setup [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) to talk to the deployed
   Kubernetes cluster.
1. 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:
    - [minikube](https://github.com/kubernetes/minikube)
    - [Kubernetes on Docker For Mac](https://docs.docker.com/docker-for-mac/kubernetes/)
    - [Kubernetes on Docker For Windows](https://docs.docker.com/docker-for-windows/kubernetes/)

1. Install and setup [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) to talk to the deployed
   Kubernetes cluster.
1. Install and setup [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/).
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `go test -v -tags kubernetes -run TestKubernetesBasicExample`
1. 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](/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:
    - [Kubernetes on Docker For Mac](https://docs.docker.com/docker-for-mac/kubernetes/)
    - [Kubernetes on Docker For Windows](https://docs.docker.com/docker-for-windows/kubernetes/)
    - [minikube](https://github.com/kubernetes/minikube)
1. Install and setup [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) to talk to the deployed
   Kubernetes cluster.
1. 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:
    - [Kubernetes on Docker For Mac](https://docs.docker.com/docker-for-mac/kubernetes/)
    - [Kubernetes on Docker For Windows](https://docs.docker.com/docker-for-windows/kubernetes/)
    - [minikube](https://github.com/kubernetes/minikube)
1. Install and setup [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) to talk to the deployed
   Kubernetes cluster.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `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:
- [kubernetes_kustomize_example_test.go](../../test/kubernetes_kustomize_example_test.go)


## Deploying the Kubernetes resource

1. Setup a Kubernetes cluster. We recommend using a local version:
    - [minikube](https://github.com/kubernetes/minikube)
    - [Kubernetes on Docker For Mac](https://docs.docker.com/docker-for-mac/kubernetes/)
    - [Kubernetes on Docker For Windows](https://docs.docker.com/docker-for-windows/kubernetes/)

1. Install and setup [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) to talk to the deployed
   Kubernetes cluster.
1. Run `kubectl apply -k .`


## Running automated tests against this Kubernetes deployment

1. Setup a Kubernetes cluster. We recommend using a local version:
    - [minikube](https://github.com/kubernetes/minikube)
    - [Kubernetes on Docker For Mac](https://docs.docker.com/docker-for-mac/kubernetes/)
    - [Kubernetes on Docker For Windows](https://docs.docker.com/docker-for-windows/kubernetes/)

1. Install and setup [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) to talk to the deployed
   Kubernetes cluster.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `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](../../test/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:
    - [minikube](https://github.com/kubernetes/minikube)
    - [Kubernetes on Docker For Mac](https://docs.docker.com/docker-for-mac/kubernetes/)
    - [Kubernetes on Docker For Windows](https://docs.docker.com/docker-for-windows/kubernetes/)

1. Install and setup [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) to talk to the deployed
   Kubernetes cluster.
1. 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:
    - [minikube](https://github.com/kubernetes/minikube)
    - [Kubernetes on Docker For Mac](https://docs.docker.com/docker-for-mac/kubernetes/)
    - [Kubernetes on Docker For Windows](https://docs.docker.com/docker-for-windows/kubernetes/)

1. Install and setup [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) to talk to the deployed
   Kubernetes cluster.
1. Install and setup [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/).
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `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](/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](/examples/packer-docker-example) and
[terraform-packer-example](/examples/terraform-packer-example).



## Installation steps
1. Sign up for [AWS](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), such as setting the
   `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables.
1. Install [Packer](https://www.packer.io/) 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
1. 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](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), such as setting the
   `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables.
1. Install [Packer](https://www.packer.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `go test -v -run TestPackerBasicExample`




## Running automated tests against this Packer template for the GCP builder

1. Sign up for [GCP](https://cloud.google.com/).
1. Configure your GCP credentials using one of the
   [Authentication](https://www.packer.io/docs/builders/googlecompute.html#authentication) methods.
1. Install [Packer](https://www.packer.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `go test -v -run TestPackerGCPBasicExample`




## Running automated tests against this Packer template for the OCI builder

1. Sign up for [OCI](https://cloud.oracle.com/cloud-infrastructure).
1. Configure your OCI credentials via [CLI Configuration
   Information](https://docs.cloud.oracle.com/iaas/Content/API/Concepts/sdkconfig.htm).
1. Create [VCN](https://docs.cloud.oracle.com/iaas/Content/GSG/Tasks/creatingnetwork.htm) and subnet
   resources in your tenancy (a.k.a. a root compartment).
1. (Optional) Create `TF_VAR_pass_phrase` environment property with the pass phrase for decrypting of the OCI [API signing
      key](https://docs.cloud.oracle.com/iaas/Content/API/Concepts/apisigningkey.htm) (can be omitted
      if the key is not protected).
1. Install [Packer](https://www.packer.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `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](/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](/examples/terraform-packer-example).


## Installation steps
1. Install [Packer](https://www.packer.io/) and make sure it's on your `PATH`.
1. Install [Docker](https://www.docker.com/) 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`.
1. 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`.
1. 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](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), such as setting the
   `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables.
1. Install [Packer](https://www.packer.io/) and make sure it's on your `PATH`.
1. Run `packer build -only=ubuntu-ami build.json`.




## Running automated tests locally against this Packer template

1. Install [Packer](https://www.packer.io/) and make sure it's on your `PATH`.
1. Install [Docker](https://www.docker.com/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `go test -v -run TestPackerDockerExampleLocal`




## Running automated tests in AWS against this Packer template

See [terraform-packer-example](/examples/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](/test/packer_hello_world_example_test.go) to see how you can write
automated tests for this simple template.


## Installation steps
1. Install [Packer](https://www.packer.io/) and make sure it's on your `PATH`.
1. Install [Docker](https://www.docker.com/) and make sure it's on your `PATH`.


## Building the Packer template (Packer >= 1.7.0)
1. Run `packer init build.pkr.hcl`.
1. 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`.
1. You should see the text "Hello, World!"


## Running automated tests against the Packer template

1. Install [Packer](https://www.packer.io/) and make sure it's on your `PATH`.
1. Install [Docker](https://www.docker.com/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `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](https://aws.amazon.com/) 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](/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](/examples/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](https://aws.amazon.com/free/), 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](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.




## Running automated tests against this module

1. Sign up for [AWS](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `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](https://aws.amazon.com/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](/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](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Set the AWS region you want to use as the environment variable `AWS_DEFAULT_REGION`.
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.

## Running automated tests against this module

1. Sign up for [AWS](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `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: 

- The [Chocolately package manager](https://chocolatey.org/why-chocolatey) which makes it easy to install additional software packages onto Windows
- Git
- Python 3

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: 

- [Packer version v1.8.1 or newer](https://github.com/hashicorp/packer)
- [Terraform v1.0 or newer](https://github.com/hashicorp/terraform)
- An AWS account with valid security credentials

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](https://blog.gruntwork.io/authenticating-to-aws-with-environment-variables-e793d6f6d02e).

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](https://aws.amazon.com/)
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](https://aws.amazon.com/fargate/) launch type and associates it with a [service](https://docs.aws.amazon.com/AmazonECS/latest/userguide/ecs_services.html)
to run and maintain a specified number of instances.

Check out [test/terraform_aws_ecs_example_test.go](/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](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Set the AWS region you want to use as the environment variable `AWS_DEFAULT_REGION`.
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.

## Running automated tests against this module

1. Sign up for [AWS](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `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](https://aws.amazon.com/) to demonstrate
how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys an [EC2
Instance](https://aws.amazon.com/ec2/) and gives that Instance a `Name` tag with the value specified in the
`instance_name` variable.

Check out [test/terraform_aws_example_test.go](/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](/examples/terraform-http-example) and [terraform-ssh-example](/examples/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](https://aws.amazon.com/free/), 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](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Set the AWS region you want to use as the environment variable `AWS_DEFAULT_REGION`.
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.




## Running automated tests against this module

1. Sign up for [AWS](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `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](https://aws.amazon.com/) to demonstrate
how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys an [EC2
Instance](https://aws.amazon.com/ec2/) which runs a web server that responds with "Hello, World!" on port 8080.

Check out [test/terraform_aws_hello_world_example_test.go](/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](https://aws.amazon.com/free/), 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](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.




## Running automated tests against this module

1. Sign up for [AWS](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `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](/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](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.

## Running automated tests against this module

1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `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](/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](https://aws.amazon.com/rds/free/), 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](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Set the AWS region you want to use as the environment variable `AWS_DEFAULT_REGION`.
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.




## Running automated tests against this module

1. Sign up for [AWS](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `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](https://aws.amazon.com/)
to demonstrate how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys an [RDS
Instance](https://aws.amazon.com/rds/) and associates it with an option group and parameter group to customize it.

Check out [test/terraform_aws_rds_example_test.go](/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](https://aws.amazon.com/rds/free/), 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](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Set the AWS region you want to use as the environment variable `AWS_DEFAULT_REGION`.
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.




## Running automated tests against this module

1. Sign up for [AWS](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `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](https://aws.amazon.com/) to demonstrate
how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys 2 [S3
Buckets](https://aws.amazon.com/s3/) - 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](/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](/examples/terraform-http-example) and 
[terraform-ssh-example](/examples/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](https://aws.amazon.com/free/), 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](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Set the AWS region you want to use as the environment variable `AWS_DEFAULT_REGION`.
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.




## Running automated tests against this module

1. Sign up for [AWS](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `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](https://aws.amazon.com/)
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](/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](https://aws.amazon.com/free/), 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](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.




## Running automated tests against this module

1. Sign up for [AWS](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `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](https://www.terraform.io/docs/backends/) 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](/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](https://aws.amazon.com/free/), 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](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Set the AWS region you want to use as the environment variable `AWS_DEFAULT_REGION`.
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.




## Running automated tests against this module

1. Sign up for [AWS](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `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](/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](/examples/terraform-aws-example).




## Running this module manually

1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.




## Running automated tests against this module

1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `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](https://cloud.google.com/) to demonstrate
how you can use Terratest to write automated tests for your GCP Terraform code. This module deploys a [Compute
Instance](https://cloud.google.com/compute/) 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](/test/gcp/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](/examples/terraform-http-example) and [terraform-ssh-example](/examples/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](https://cloud.google.com/free/), 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](https://cloud.google.com/).
1. Configure your GCP credentials using one of the [supported methods for GCP CLI
   tools](https://cloud.google.com/sdk/docs/quickstarts).
1. Install [Terraform](https://www.terraform.io/) and make sure it's in your `PATH`.
1. Ensure the desired Project ID is set: `export GOOGLE_CLOUD_PROJECT=terratest-ABCXYZ`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.

## Running automated tests against this module

1. Sign up for [GCP](https://cloud.google.com/free/).
1. Configure your GCP credentials using the [GCP CLI
   tools](https://cloud.google.com/sdk/docs/quickstarts).
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. Set `GOOGLE_CLOUD_PROJECT` environment variable to your project name.
1. `cd test`
1. `dep ensure`
1. `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](https://cloud.google.com/) to demonstrate
how you can use Terratest to write automated tests for your GCP Terraform code. This module deploys a [Compute
Instance](https://cloud.google.com/compute/) 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](/test/gcp/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](/examples/terraform-http-example) and [terraform-ssh-example](/examples/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](https://cloud.google.com/free/), 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](https://cloud.google.com/).
1. Configure your GCP credentials using one of the [supported methods for GCP CLI
   tools](https://cloud.google.com/sdk/docs/quickstarts).
1. Install [Terraform](https://www.terraform.io/) and make sure it's in your `PATH`.
1. Ensure the desired Project ID is set: `export GOOGLE_CLOUD_PROJECT=terratest-ABCXYZ`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.




## Running automated tests against this module

1. Sign up for [GCP](https://cloud.google.com/free/).
1. Configure your GCP credentials using the [GCP CLI
   tools](https://cloud.google.com/sdk/docs/quickstarts).
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. Set `GOOGLE_CLOUD_PROJECT` environment variable to your project name.
1. `cd test`
1. `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](https://cloud.google.com/) to demonstrate
how you can use Terratest to write automated tests for your GCP Terraform code. This module deploys an [Instance Group](
https://cloud.google.com/compute/docs/instance-groups/).

Check out [test/terraform_gcp_ig_example_test.go](/test/gcp/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](/examples/terraform-http-example) and [terraform-ssh-example](/examples/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](
https://cloud.google.com/free/). Naturally, you are completely responsible for all GCP charges.

## Running this module manually

1. Sign up for [GCP](https://cloud.google.com/).
1. Configure your GCP credentials using one of the [supported methods for GCP CLI
   tools](https://cloud.google.com/sdk/docs/quickstarts).
1. Install [Terraform](https://www.terraform.io/) and make sure it's in your `PATH`.
1. Ensure the desired Project ID is set: `export GOOGLE_CLOUD_PROJECT=terratest-ABCXYZ`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.

## Running automated tests against this module

1. Sign up for [GCP](https://cloud.google.com/free/).
1. Configure your GCP credentials using the [GCP CLI
   tools](https://cloud.google.com/sdk/docs/quickstarts).
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. Set `GOOGLE_CLOUD_PROJECT` environment variable to your project name.
1. `cd test`
1. `dep ensure`
1. `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](https://cloud.google.com/) to demonstrate
how you can use Terratest to write automated tests for your GCP Terraform code. This module deploys a [Pub/Sub Topic](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.topics) and a [Pub/Sub Subscription](https://cloud.google.com/pubsub/docs/reference/rest/v1/projects.subscriptions) attached to that topic.

Check out [test/gcp/terraform_gcp_pubsub_example_test.go](../../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](https://cloud.google.com/free/), 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](https://cloud.google.com/).
1. Configure your GCP credentials using one of the [supported methods for GCP CLI
   tools](https://cloud.google.com/sdk/docs/quickstarts).
1. Install [Terraform](https://www.terraform.io/) and make sure it's in your `PATH`.
1. Ensure the desired Project ID is set: `export GOOGLE_CLOUD_PROJECT=your-project-id`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.

## Running automated tests against this module

1. Sign up for [GCP](https://cloud.google.com/free/).
1. Configure your GCP credentials using the [GCP CLI
   tools](https://cloud.google.com/sdk/docs/quickstarts).
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. Set `GOOGLE_CLOUD_PROJECT` environment variable to your project name.
1. `cd test/gcp`
1. `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](/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](/examples/terraform-basic-example).




## Running this module manually

1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.




## Running automated tests against this module

1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `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](https://aws.amazon.com/) to demonstrate
how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys an [EC2
Instance](https://aws.amazon.com/ec2/) 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](/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](/examples/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](https://aws.amazon.com/free/), 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](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. The `instance_url` output variable shows you the URL of the web server. Try opening it in your browser!
1. When you're done, run `terraform destroy`.




## Running automated tests against this module

1. Sign up for [AWS](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `go test -v -run TestTerraformHttpExample`

---

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

# Terraform OPA Example

This folder contains an [OPA](https://www.openpolicyagent.org/) policy that validates that all module blocks use a
source that comes from the `gruntwork-io` GitHub org (the [enforce_source.rego](./policy/enforce_source.rego) file).
To test this policy, we provided two Terraform modules, [pass](./pass) and [fail](./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](/test/terraform_opa_example_test.go) to see how you can write automated
tests for this module.


## Running this module manually

1. Install [OPA](https://www.openpolicyagent.org/) and make sure it's on your `PATH`.
1. Install [hcl2json](https://github.com/tmccombs/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.
1. Convert each terraform source code in the `pass` or `fail` folder to json by feeding it to `hcl2json`:

       hcl2json pass/main.tf > pass/main.json

1. Run each converted terraform json file against the OPA policy:

       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](https://www.openpolicyagent.org/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/).
1. `cd test`
1. `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](https://aws.amazon.com/) to demonstrate
how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys an [EC2
Instance](https://aws.amazon.com/ec2/) 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](/examples/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](/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](https://aws.amazon.com/free/), 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](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Packer](https://www.packer.io/) and make sure it's on your `PATH`.
1. Follow the instructions in [packer-docker-example](/examples/packer-docker-example) to build an AMI. Note down the
   AMI ID.
1. Open `variables.tf` and set the `ami_id` variable to the ID of the AMI you just built.
1. Run `terraform init`.
1. Run `terraform apply`.
1. The `instance_url` output variable shows you the URL of the web server. Try opening it in your browser!
1. When you're done, run `terraform destroy`.




## Running automated tests against this module

1. Sign up for [AWS](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Packer](https://www.packer.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `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](https://aws.amazon.com/) to demonstrate
how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys an [Auto Scaling
Group (ASG)](https://docs.aws.amazon.com/autoscaling/ec2/userguide/AutoScalingGroup.html) in the AWS region specified
in the `aws_region` variable and a [Load Balancer](https://aws.amazon.com/elasticloadbalancing/) 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](/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](/examples/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](https://aws.amazon.com/free/), 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](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. The `url` output variable shows you the URL of the load balancer. Try opening it in your browser!
1. When you're done, run `terraform destroy`.




## Running automated tests against this module

1. Sign up for [AWS](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `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](https://aws.amazon.com/) to demonstrate
how you can use Terratest to test modules which use `remote-exec`, `files`, and other ssh-based 
[provisioners](https://www.terraform.io/docs/provisioners/index.html).

Check out [test/terraform_remote_exec_example_test.go](/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](https://aws.amazon.com/free/), 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](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.

## Running automated tests against this module

1. Sign up for [AWS](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `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](https://aws.amazon.com/) to demonstrate
how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys an [EC2
Instance](https://aws.amazon.com/ec2/) 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](/examples/terraform-ssh-certificate) 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](/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](/examples/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](https://aws.amazon.com/free/), 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](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.

## Running automated tests against this module

1. Sign up for [AWS](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `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](https://aws.amazon.com/) to demonstrate
how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys two [EC2
Instances](https://aws.amazon.com/ec2/), 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](/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](/examples/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](https://aws.amazon.com/free/), 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](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.




## Running automated tests against this module

1. Sign up for [AWS](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `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](https://aws.amazon.com/) to demonstrate
how you can use Terratest to write automated tests for your AWS Terraform code. This module deploys an [EC2
Instance](https://aws.amazon.com/ec2/) 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](/examples/terraform-ssh-password-example) 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](/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](/examples/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](https://aws.amazon.com/free/), 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](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.

## Running automated tests against this module

1. Sign up for [AWS](https://aws.amazon.com/).
1. Configure your AWS credentials using one of the [supported methods for AWS CLI
   tools](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html), 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".
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `dep ensure`
1. `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](/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](/examples/terragrunt-multi-module-example).




## Running this module manually

1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Terragrunt](https://terragrunt.gruntwork.io/) and make sure it's on your `PATH`.
1. Run `terragrunt apply`.
1. When you're done, run `terragrunt destroy`.




## Running automated tests against this module

1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [Terragrunt](https://terragrunt.gruntwork.io/) and make sure it's on your `PATH`.
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `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](/modules/terragrunt/terragrunt_example_test.go) to see how you can write automated tests
for this configuration using `ApplyAll` and `DestroyAll`.

## Structure

```
.
├── 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](https://www.terraform.io/) and [Terragrunt](https://terragrunt.gruntwork.io/).
1. `cd live`
1. Run `terragrunt apply --all`.
1. When you're done, run `terragrunt destroy --all`.

## Running automated tests against this module

1. Install [Terraform](https://www.terraform.io/) and [Terragrunt](https://terragrunt.gruntwork.io/).
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. `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](https://terragrunt.gruntwork.io/docs/features/stacks/#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](https://terragrunt.gruntwork.io/docs/features/stacks/#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](../../examples/) for complete working examples:
- [terragrunt-example](../../examples/terragrunt-example/) - Single unit testing
- [terragrunt-multi-module-example](../../examples/terragrunt-multi-module-example/) - Multi-module testing
- [terragrunt-second-example](../../examples/terragrunt-second-example/) - Additional patterns

### 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

- [Terragrunt Documentation](https://terragrunt.gruntwork.io/)
- [Terratest Documentation](https://terratest.gruntwork.io/)

---

### 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 .`
1. `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](https://www.freedesktop.org/wiki/Software/systemd/)
to run, which, in turn, allows you to run one or more services as [systemd units](https://www.freedesktop.org/software/systemd/man/systemd.unit.html).

### 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 .`
1. `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:

```
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](
  https://docs.docker.com/engine/docker-overview/#the-underlying-technology) 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 .`
1. `docker push gruntwork/ubuntu-test:18.04`

---

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

# Moto

This docker image runs [moto](https://github.com/spulec/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](
https://aws.amazon.com/cli/)[].

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](https://github.com/boto/boto3) 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](/README.md#unit-tests), 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 .`
1. `docker push gruntwork/moto:v1`

#### Run a Docker container

```
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:
- See the [moto stand-alone server usage docs](https://github.com/spulec/moto#stand-alone-server-mode)
- See [which AWS services are supported](https://github.com/spulec/moto#in-a-nutshell)

#### 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:

```
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](https://localstack.cloud/) is a (coming soon) commercial service intending to offer "local AWS as a service".
It is based on the open source [localstack](https://github.com/localstack/localstack) project.

Local stack seems to offer a [small set of advantages](https://github.com/localstack/localstack#why-localstack) 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](https://azure.microsoft.com/) to demonstrate
how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys an [Azure Container Instance](https://azure.microsoft.com/en-us/services/container-instances/).

Check out [test/azure/terraform_azure_aci_example_test.go](/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](https://azure.microsoft.com/en-us/free/), 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](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`

## Running automated tests against this module

1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your Terratest [Go test environment](../README.md) 
1. `cd test/azure`
1. `go build terraform_azure_aci_example_test.go`
1. `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](https://azure.microsoft.com/) to demonstrate
how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys an [Azure Container Registry](https://azure.microsoft.com/en-us/services/container-registry/).

Check out [test/azure/terraform_azure_acr_example_test.go](/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](https://azure.microsoft.com/en-us/free/), 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](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`


## Running automated tests against this module

1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your Terratest [Go test environment](../README.md)
1. `cd test/azure`
1. `go build terraform_azure_acr_example_test.go`
1. `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](https://docs.microsoft.com/en-us/azure/azure-monitor/platform/action-groups) in [Azure](https://azure.microsoft.com/) 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](/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](https://azure.microsoft.com/).
1. Install [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest)
2. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
3. 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](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli?view=azure-cli-latest) then set the value to the environment variables. 
1. Run `terraform init`.
2. Run `terraform apply`.
3. Log into Azure to validate resource was created.
4. 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](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli?view=azure-cli-latest) then set the value to the environment variables. 
1. Install [Golang](https://golang.org/) version `1.13+` required. 
1. `cd test/azure`
1. `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](https://azure.microsoft.com/) to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code. 

This module deploys [Azure Kubernetes Service](https://azure.microsoft.com/en-us/services/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](/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](https://azure.microsoft.com/).
1. Install [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Install [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) and make sure it's on your `PATH`.
1. 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](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli?view=azure-cli-latest) then set the value to the environment variables. 
1. Run `terraform init`
1. Run `terraform apply`
1. Apply `nginx-deployment.yml`
1. Watch the service until Public IPAddress is assigned.
1. Send http request to the Public IPAddress, make sure it returns 200.
1. 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](https://docs.microsoft.com/en-us/cli/azure/create-an-azure-service-principal-azure-cli?view=azure-cli-latest) then set the value to the environment variables. 
1. Install [Golang](https://golang.org/) version `1.13+` required. 
1. `cd test`
1. `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](https://azure.microsoft.com/) 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](https://docs.microsoft.com/en-us/azure/virtual-machines/availability) 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](https://azure.microsoft.com/en-us/services/virtual-machines/) that gives the Availability Set the following:
  - [Virtual Machine](https://docs.microsoft.com/en-us/azure/virtual-machines/) with the name specified in the `vm_name` output variable.

Check out [test/azure/terraform_azure_availabilityset_example_test.go](/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](https://azure.microsoft.com/en-us/free/), 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](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`

## Running automated tests against this module

1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your Terratest [Go test environment](../README.md)
1. `cd test/azure`
1. `go build terraform_azure_availabilityset_example_test.go`
1. `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](https://azure.microsoft.com/) to demonstrate
how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys two [Azure Container Apps](https://learn.microsoft.com/en-us/azure/container-apps/overview) (one app and a job).

Check out [test/azure/terraform_azure_container_apps_example_test.go](./../../../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](https://azure.microsoft.com/).
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`.

## Running automated tests against this module

1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your Terratest [Go test environment](../README.md)
1. `cd test/azure`
1. `go build terraform_azure_container_apps_example_test.go`
1. `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](https://azure.microsoft.com/) to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys the following resources:

- A [Cosmos DB Account](https://azure.microsoft.com/services/cosmos-db/) configured with:
  - A [SQL Database](https://docs.microsoft.com/en-gb/azure/cosmos-db/account-databases-containers-items#azure-cosmos-databases)
  - Three [SQL Containers](https://docs.microsoft.com/en-gb/azure/cosmos-db/account-databases-containers-items#azure-cosmos-containers)

Check out [test/azure/terraform_azure_cosmosdb_example_test.go](./../../../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](https://azure.microsoft.com/).
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`.

## Running automated tests against this module

1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your Terratest [Go test environment](../README.md) 
1. `cd test/azure`
1. `go build terraform_azure_cosmosdb_example_test.go`
1. `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](https://azure.microsoft.com/) to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code.
This module deploys a Data Factory.

- A [Azure MySQL Database](https://azure.microsoft.com/en-us/products/data-factory).

Check out [test/azure/terraform_azure_datafactory_example_test.go](./../../../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](https://azure.microsoft.com/).
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`.


## Running automated tests against this module
1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your Terratest [Go test environment](../README.md)
1. `cd test/azure`
1. `go build terraform_azure_datafactory_example_test.go`
2. `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](https://azure.microsoft.com/) to demonstrate
how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys an [Azure managed disk](https://azure.microsoft.com/services/storage/disks).

Check out [test/azure/terraform_azure_disk_example_test.go](/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](https://azure.microsoft.com/free/), 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](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`

## Running automated tests against this module

1. Sign up for [Azure](https://azure.microsoft.com/).
2. Configure your Azure credentials using one of the [supported methods for Azure CLI tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest).

3. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
4. [Review environment variables](#review-environment-variables).
5. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
6. `cd test`
7. Make sure [the azure-sdk-for-go versions match](#check-go-dependencies) in [/test/go.mod](/test/go.mod) and in [test/azure/terraform_azure_disk_example_test.go](/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](https://azure.microsoft.com/) to demonstrate
how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys a [Virtual
Machine](https://azure.microsoft.com/en-us/services/virtual-machines/) 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](/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](/examples/terraform-http-example) and [terraform-ssh-example](/examples/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](https://azure.microsoft.com/en-us/free/), 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](https://azure.microsoft.com/).
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest).
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Run `terraform init`.
1. Run `terraform apply`.
1. When you're done, run `terraform destroy`.

## Running automated tests against this module

1. Sign up for [Azure](https://azure.microsoft.com/).
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest).
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. [Review environment variables](#review-environment-variables).
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. Make sure [the azure-sdk-for-go versions match](#check-go-dependencies) in [/test/go.mod](/test/go.mod) and in [test/azure/terraform_azure_example_test.go](/test/azure/terraform_azure_example_test.go).
1. `go build terraform_azure_example_test.go`
1. `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](https://github.com/gruntwork-io/terratest/blob/main/go.mod) file.

> This was tested with **go1.14.1**.

### Check Azure-sdk-for-go version

Let's make sure [go.mod](https://github.com/gruntwork-io/terratest/blob/main/go.mod) includes the appropriate [azure-sdk-for-go version](https://github.com/Azure/azure-sdk-for-go/releases/tag/v38.1.0):

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

We should check that [test/azure/terraform_azure_example_test.go](/test/azure/terraform_azure_example_test.go) includes the corresponding [azure-sdk-for-go package](https://github.com/Azure/azure-sdk-for-go/tree/master/services/compute/mgmt/2019-07-01/compute):

```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](https://docs.microsoft.com/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#set-up-terraform-access-to-azure) and also that we set the [environment variables](https://docs.microsoft.com/azure/terraform/terraform-install-configure?toc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fterraform%2Ftoc.json&bc=https%3A%2F%2Fdocs.microsoft.com%2Fen-us%2Fazure%2Fbread%2Ftoc.json#configure-terraform-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](../../modules/azure/client_factory.go) 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](https://azure.microsoft.com/) to demonstrate
how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys an [Azure Front Door](https://azure.microsoft.com/en-us/services/frontdoor/).

Check out [test/azure/terraform_azure_frontdoor_example_test.go](./../../../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](https://azure.microsoft.com/).
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`.

## Running automated tests against this module

1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your Terratest [Go test environment](../README.md) 
1. `cd test/azure`
1. `go build terraform_azure_frontdoor_example_test.go`
1. `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](https://azure.microsoft.com/) to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code.

This module deploys [Azure Storage](https://azure.microsoft.com/en-us/services/storage/), [Azure Function App](https://azure.microsoft.com/en-us/services/functions/), [Azure Function App](https://azure.microsoft.com/en-us/services/functions/).

Check out [test/azure/terraform_azure_functionapp_example_test.go](/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](https://azure.microsoft.com/free/), 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](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`

## Running automated tests against this module

1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your Terratest [Go test environment](../README.md)
1. `cd test/azure`
1. `go build terraform_azure_functionapp_example_test.go`
1. `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](https://azure.microsoft.com/) 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](https://azure.microsoft.com/services/key-vault/) that gives the module the following:
  - [Secret](https://docs.microsoft.com/azure/key-vault/general/about-keys-secrets-certificates)  with the value specified in the `secret_name`  output variable.
  - [Key](https://docs.microsoft.com/azure/key-vault/general/about-keys-secrets-certificates)  with the value specified in the `key_name`  output variable.
  - [Certificate](https://docs.microsoft.com/azure/key-vault/general/about-keys-secrets-certificates)  with the value specified in the `certificate_name`  output variable.

Check out [test/azure/terraform_azure_keyvault_example_test.go](/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](https://azure.microsoft.com/free/), 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](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`

## Running automated tests against this module

1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your Terratest [Go test environment](../README.md)
1. `cd test/azure`
1. `go build terraform_azure_keyvault_example_test.go`
1. `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](https://azure.microsoft.com/) 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](https://docs.microsoft.com/azure/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](https://docs.microsoft.com/azure/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](https://docs.microsoft.com/azure/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](https://docs.microsoft.com/azure/virtual-network/) with the name specified in the `vnet_name` output variable.
  - [Subnet](https://docs.microsoft.com/azure/virtual-network/virtual-network-manage-subnet) with the name specified in the `subnet_name` output variable.
  - [Public IP Address](https://docs.microsoft.com/azure/virtual-network/virtual-network-public-ip-address) with the name specified in the `public_address_name` output variable.

Check out [test/azure/terraform_azure_loadbalancer_example_test.go](/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](https://azure.microsoft.com/free/), 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](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`

## Running automated tests against this module

1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your Terratest [Go test environment](../README.md)
1. `cd test/azure`
1. `go build terraform_azure_loadbalancer_example_test.go`
1. `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](https://azure.microsoft.com/) 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](https://docs.microsoft.com/azure/azure-monitor/platform/log-analytics-agent) that gives the module the following:
  - [Name](https://docs.microsoft.com/azure/azure-monitor/learn/quick-create-workspace#:~:text=%20Create%20a%20Log%20Analytics%20workspace%20in%20the,and%20region%20as%20in%20the%20deleted...%20More%20)  with the value specified in the `loganalytics_workspace_name`  output variable.
  - [Sku](https://docs.microsoft.com/azure/azure-monitor/learn/quick-create-workspace#:~:text=%20Create%20a%20Log%20Analytics%20workspace%20in%20the,and%20region%20as%20in%20the%20deleted...%20More%20)  with the value specified in the `loganalytics_workspace_sku`  output variable.
  - [RetentionPeriodInDays](https://docs.microsoft.com/azure/azure-monitor/learn/quick-create-workspace#:~:text=%20Create%20a%20Log%20Analytics%20workspace%20in%20the,and%20region%20as%20in%20the%20deleted...%20More%20)  with the value specified in the `loganalytics_workspace_retention`  output variable.

Check out [test/azure/terraform_azure_loganalytics_example_test.go](/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](https://azure.microsoft.com/free/), 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](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`

## Running automated tests against this module

1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your TerraTest [Go test environment](../README.md)
1. `cd test/azure`
1. `go build terraform_azure_loganalytics_example_test.go`
1. `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](https://azure.microsoft.com/) 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.

- A [Diagnostic Setting](https://docs.microsoft.com/azure/azure-monitor/platform/diagnostic-settings-template)

Check out [test/azure/terraform_azure_monitor_example_test.go](/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](https://azure.microsoft.com/free/), 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](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`

## Running automated tests against this module

1. Sign up for [Azure](https://azure.microsoft.com/).
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest).
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. [Review environment variables](#review-environment-variables).
1. Install [Golang](https://golang.org/) and make sure this code is checked out into your `GOPATH`.
1. `cd test`
1. Make sure [the azure-sdk-for-go versions match](#check-go-dependencies) in [/go.mod](/go.mod) and in [test/azure/terraform_azure_monitor_example_test.go](/test/azure/terraform_azure_monitor_example_test.go).
1. `go build test/azure/terraform_azure_monitor_example_test.go`
1. `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](https://azure.microsoft.com/) to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code.
This module deploys a database for MySQL.

- A [Azure MySQL Database](https://azure.microsoft.com/services/mysql/).

Check out [test/azure/terraform_azure_mysqldb_example_test.go](./../../../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](https://azure.microsoft.com/).
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`.


## Running automated tests against this module
1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your Terratest [Go test environment](../README.md) 
1. `cd test/azure`
1. `go build terraform_azure_mysqldb_example_test.go`
1. `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](https://azure.microsoft.com/) 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.

- A [Virtual Network](https://azure.microsoft.com/en-us/services/virtual-network/) module that includes the following resources:
  - [Virtual Network](https://docs.microsoft.com/en-us/azure/virtual-network/) with the name specified in the `virtual_network_name` variable.
  - [Subnet](https://docs.microsoft.com/en-us/rest/api/virtualnetwork/subnets) with the name specified in the `subnet_name` variable.
  - [Public Address](https://docs.microsoft.com/en-us/azure/virtual-network/public-ip-addresses) with the name specified in the `public_ip_name` variable.
  - [Internal Network Interface](https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-network-interface) with the name specified in the `network_interface_internal` variable.
  - [ExternalNetwork Interface](https://docs.microsoft.com/en-us/azure/virtual-network/virtual-network-network-interface) with the name specified in the `network_interface_external` variable.

Check out [test/azure/terraform_azure_network_example_test.go](/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](https://azure.microsoft.com/en-us/free/), 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](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`

## Running automated tests against this module

1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your Terratest [Go test environment](../README.md)
1. `cd test/azure`
1. `go build terraform_azure_network_example_test.go`
1. `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](https://azure.microsoft.com/) to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code. This module deploys the following:

* A [Virtual Machine](https://azure.microsoft.com/en-us/services/virtual-machines/) that gives the module the following:
    * [Virtual Machine](https://docs.microsoft.com/en-us/azure/virtual-machines/) 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](https://docs.microsoft.com/en-us/azure/virtual-network/network-security-groups-overview) 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](/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](https://azure.microsoft.com/en-us/free/), 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](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`

## Running automated tests against this module

1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your Terratest [Go test environment](../README.md)
1. `cd test/azure`
1. `go build terraform_azure_nsg_example_test.go`
1. `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](https://azure.microsoft.com/) to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code.
This module deploys a database for PostgreSQL.

- A [Azure PostgreSQL Database](https://azure.microsoft.com/services/postgresql/).

Check out [test/azure/terraform_azure_postgresqldb_example_test.go](./../../../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](https://azure.microsoft.com/).
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`.


## Running automated tests against this module
1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your Terratest [Go test environment](../README.md) 
1. `cd test/azure`
1. `go build terraform_azure_postgresql_example_test.go`
1. `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](https://azure.microsoft.com/) 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](https://azure.microsoft.com/services/backup/) that gives the module the following:
  - [Backup Vault](https://docs.microsoft.com/azure/backup/backup-azure-recovery-services-vault-overview)  with the value specified in the `recovery_service_vault_name` output variable.
  - [Backup VM Policy](https://azure.microsoft.com/en-in/updates/azure-vm-backup-policy-management/)  with the value specified in the `backup_policy_vm_name`  output variable.

Check out [test/azure/terraform_azure_recoveryservices_example_test.go](/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](https://azure.microsoft.com/free/), 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](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`

## Running automated tests against this module

1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your Terratest [Go test environment](../README.md)
1. `cd test/azure`
1. `go build terraform_azure_recoveryservices_example_test.go`
1. `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](https://azure.microsoft.com/) to demonstrate
how you can use TerraTest to write automated tests for your Azure Terraform code. This module deploys a Resource Group.

- A [Resource Group](https://docs.microsoft.com/azure/azure-resource-manager/management/overview) with no other resources.

Check out [test/azure/terraform_azure_resourcegroup_example_test.go](/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](https://azure.microsoft.com/free/), 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](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`

## Running automated tests against this module

1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your TerraTest [Go test environment](../README.md)
1. `cd test/azure`
1. `go build terraform_azure_resourcegroup_example_test.go`
1. `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](https://azure.microsoft.com/) 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](https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-messaging-overview) with the namespace specified in the `namespace_name` variable.

Check out [test/azure/terraform_azure_servicebus_example_test.go](./../../../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](https://azure.microsoft.com/en-us/free/), 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](https://azure.microsoft.com/).
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`.


## Running automated tests against this module
1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your Terratest [Go test environment](../README.md) 
1. `cd test/azure`
1. `go build terraform_azure_servicebus_example_test.go`
1. `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](https://azure.microsoft.com/) 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](https://azure.microsoft.com/services/sql-database/campaign/) with the name specified in the `sql_server_name` variable.
- A [SQL Database](https://azure.microsoft.com/services/sql-database/) with the name specified in the `sql_database_name` variable.

Check out [test/azure/terraform_azure_sqldb_example_test.go](./../../../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](https://azure.microsoft.com/en-us/free/), 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](https://azure.microsoft.com/).
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`.


## Running automated tests against this module
1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your Terratest [Go test environment](../README.md) 
1. `cd test/azure`
1. `go build terraform_azure_sqldb_example_test.go`
1. `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](https://azure.microsoft.com/) 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.

- A [SQL Managed Instance](https://azure.microsoft.com/en-us/products/azure-sql/managed-instance/).
- A SQL Managed Database.

Check out [test/azure/terraform_azure_sqlmanagedinstance_example_test.go](./../../../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](https://azure.microsoft.com/en-us/free/), 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](https://azure.microsoft.com/).
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. 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](https://learn.microsoft.com/en-us/azure/azure-sql/managed-instance/management-operations-overview?view=azuresql#duration), so please make sure to set the timeout accordingly in the below go test command.

1. Sign up for [Azure](https://azure.microsoft.com/)
2. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
3. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
4. Configure your Terratest [Go test environment](../README.md) 
5. `cd test/azure`
6. `go build terraform_azure_sqlmanagedinstance_example_test.go`
7. `go test -v -run TestTerraformAzureSQLManagedInstanceExample -timeout <in hours>`

---

### 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](https://azure.microsoft.com/) to demonstrate
how you can use TerraTest to write automated tests for your Azure Terraform code. This module deploys a
Storage Account.

- An [Azure Storage Account](https://azure.microsoft.com/services/storage/) that gives the module the following:
  - [Stock Account Name](https://azure.microsoft.com/services/storage/)  with the value specified in the `storage_account_name`  output variable.
  - [Storage Account Tier](https://azure.microsoft.com/services/storage/)  with the value specified in the `"storage_account_account_tier`  output variable.
  - [Storage Account Kind](https://azure.microsoft.com/services/storage/)  with the value specified in the `"storage_account_account_kind`  output variable.
  - [Storage Container](https://azure.microsoft.com/services/storage/)  with the value specified in the `"storage_container_name`  output variable.

Check out [test/azure/terraform_azure_storage_example_test.go](/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](https://azure.microsoft.com/free/), 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](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`

## Running automated tests against this module

1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your TerraTest [Go test environment](../README.md)
1. `cd test/azure`
1. `go build terraform_azure_storage_example_test.go`
1. `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](https://azure.microsoft.com/) to demonstrate how you can use Terratest to write automated tests for your Azure Terraform code.
This module deploys below resource:

- A [Azure Synapse Analytics](https://azure.microsoft.com/en-us/products/synapse-analytics/).

Check out [test/azure/terraform_azure_synapse_example_test.go](./../../../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](https://azure.microsoft.com/).
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`.
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`.

## Running automated tests against this module

1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/en-us/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your Terratest [Go test environment](../README.md)
1. `cd test/azure`
1. `go build terraform_azure_synapse_example_test.go`
1. `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](https://azure.microsoft.com/) 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](https://azure.microsoft.com/services/virtual-machines/) and gives that VM the following resources:
  - [Virtual Machine](https://docs.microsoft.com/azure/virtual-machines/) with the name specified in the `vm_name` variable.
  - [Managed Disk](https://docs.microsoft.com/azure/virtual-machines/managed-disks-overview) with the name specified in the `managed_disk_name` variable.
  - [Availability Set](https://docs.microsoft.com/azure/virtual-machines/availability) with the name specified in the `availability_set_name` variable.
- A [Virtual Network](https://azure.microsoft.com/services/virtual-network/) module that contains the following resources:
  - [Virtual Network](https://docs.microsoft.com/azure/virtual-network/) with the name specified in the `virtual_network_name` variable.
  - [Subnet](https://docs.microsoft.com/rest/api/virtualnetwork/subnets) with the name specified in the `subnet_name` variable.
  - [Public Address](https://docs.microsoft.com/azure/virtual-network/public-ip-addresses) with the name specified in the `public_ip_name` variable.
  - [Network Interface](https://docs.microsoft.com/azure/virtual-network/virtual-network-network-interface) with the name specified in the `network_interface_name` variable.

Check out [test/azure/terraform_azure_vm_test.go](/test/azure/terraform_azure_vm_example_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](https://azure.microsoft.com/free/), 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](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CL
   tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Ensure [environment variables](../README.md#review-environment-variables) are available
1. Run `terraform init`
1. Run `terraform apply`
1. When you're done, run `terraform destroy`

## Running automated tests against this module

1. Sign up for [Azure](https://azure.microsoft.com/)
1. Configure your Azure credentials using one of the [supported methods for Azure CLI
   tools](https://docs.microsoft.com/cli/azure/azure-cli-configuration?view=azure-cli-latest)
1. Install [Terraform](https://www.terraform.io/) and make sure it's on your `PATH`
1. Configure your Terratest [Go test environment](../README.md)
1. `cd test/azure`
1. `go build terraform_azure_vm_test.go`
1. `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`)

---
layout: collection-browser-doc
title: Package by package overview
category: getting-started
excerpt: >-
  Learn more about Terratest modules and how they can help you test different types infrastructure.
tags: ["packages"]
order: 103
nav_title: Documentation
nav_title_link: /docs/
---

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](https://github.com/gruntwork-io/terratest/tree/main/modules) 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`)

---
layout: collection-browser-doc
title: Overview
category: migrating-to-v1
excerpt: >-
  Summary of breaking changes in Terratest v1.0.0 and where to look first.
tags: ["migration", "v1"]
order: 300
nav_title: Documentation
nav_title_link: /docs/
---

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](https://semver.org/). 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]({{site.baseurl}}/docs/migrating-to-v2/overview/).

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](./azure/).

### 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/<id>/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](https://github.com/gruntwork-io/terratest/issues) 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`)

---
layout: collection-browser-doc
title: v2 overview
category: migrating-to-v2
excerpt: >-
  What changes when you move from Terratest v1 to v2, and the order to do
  it in.
tags: ["migration", "v2"]
order: 400
nav_title: Documentation
nav_title_link: /docs/
---

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]({{site.baseurl}}/docs/migrating-to-v1/overview/) 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]({{site.baseurl}}/docs/migrating-to-v2/import-map/#renamed).

**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/v2@v2.0.0-beta.2
go get github.com/gruntwork-io/terratest/modules/aws/v2@v2.0.0-beta.2
```

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](https://github.com/gruntwork-io/terratest/releases). 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]({{site.baseurl}}/docs/migrating-to-v2/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]({{site.baseurl}}/docs/migrating-to-v2/rewriting-imports/).
4. Add a `require` per module, then `go mod tidy`.
5. Review the [behavior
   changes]({{site.baseurl}}/docs/migrating-to-v2/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](https://github.com/gruntwork-io/terratest/issues) 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/`.

---

###  Pages Cookie Policy Index (`docs/_pages/cookie-policy/index.md`)

---
layout: subpage
permalink: /cookie-policy/
slug: cookie-policy
redirect_to:
  - https://gruntwork.io/cookie-policy/
---

---

###  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: info@gruntwork.io
name: "Terratest | Automated tests for your infrastructure code."
description: >- # this means to ignore newlines until "baseurl:"
  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"
# The Git ref (tag) that documentation examples and "View on GitHub" links point at.
# 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
repository: "github.com/gruntwork-io/terratest"
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](#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/<util>/...` -> `modules/core/v2/<util>/...`
- 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 `require`s 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 `replace`s 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 `replace`s. 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`)

- id: terraform-hello-world
  name: Terraform Hello, World Example
  image: /assets/img/logos/terraform-logo.png
  files:
    - url: /examples/terraform-hello-world-example/main.tf
      id: terraform_code
    - url: /test/terraform_hello_world_example_test.go
      id: test_code
      default: true
  learn_more:
    - name: Terraform Hello, World
      url: https://github.com/gruntwork-io/terratest/tree/v1.0.1/examples/terraform-hello-world-example

- id: packer-hello-world
  name: Packer Hello, World Example
  image: /assets/img/logos/packer-logo.png
  files:
    - url: /examples/packer-hello-world-example/build.pkr.hcl
      id: packer_code
    - url: /test/packer_hello_world_example_test.go
      id: test_code
      default: true
  learn_more:
    - name: Packer Hello, World
      url: https://github.com/gruntwork-io/terratest/tree/v1.0.1/examples/packer-hello-world-example

- id: docker-hello-world
  name: Docker Hello, World Example
  image: /assets/img/logos/docker-logo.png
  files:
    - url: /examples/docker-hello-world-example/Dockerfile
      id: docker_code
      prism_lang: docker
    - url: /test/docker_hello_world_example_test.go
      id: test_code
      default: true
  learn_more:
    - name: Docker Hello, World
      url: https://github.com/gruntwork-io/terratest/tree/v1.0.1/examples/docker-hello-world-example

- id: kubernetes-hello-world
  name: Kubernetes Hello, World Example
  image: /assets/img/logos/kubernetes-logo.png
  files:
    - url: /examples/kubernetes-hello-world-example/hello-world-deployment.yml
      id: k8s_code
    - url: /test/kubernetes_hello_world_example_test.go
      id: test_code
      default: true
  learn_more:
    - name: Kubernetes Hello, World
      url: https://github.com/gruntwork-io/terratest/tree/v1.0.1/examples/kubernetes-hello-world-example

- id: terragrunt-hello-world
  name: Terragrunt Example
  image: /assets/img/logos/terragrunt-logo.png
  files:
    - url: /examples/terragrunt-example/terragrunt.hcl
      id: terragrunt_code
    - url: /examples/terragrunt-example/main.tf
      id: terraform_code
    - url: /modules/terragrunt/terragrunt_example_test.go
      id: test_code
      default: true
  learn_more:
    - name: Terragrunt Unit
      url: https://github.com/gruntwork-io/terratest/tree/v1.0.1/examples/terragrunt-example
    - name: Terragrunt Stack
      url: https://github.com/gruntwork-io/terratest/tree/v1.0.1/examples/terragrunt-multi-module-example

- id: aws-hello-world
  name: AWS Hello, World Example
  image: /assets/img/logos/aws-logo.png
  files:
    - url: /examples/terraform-aws-hello-world-example/main.tf
      id: terraform_code
    - url: /test/terraform_aws_hello_world_example_test.go
      id: test_code
      default: true
  learn_more:
    - name: AWS Hello, World
      url: https://github.com/gruntwork-io/terratest/tree/v1.0.1/examples/terraform-aws-hello-world-example

- id: gcp-hello-world
  name: GCP Hello, World Example
  image: /assets/img/logos/gcp-logo.png
  files:
    - url: /examples/terraform-gcp-hello-world-example/main.tf
      id: terraform_code
    - url: /test/gcp/terraform_gcp_hello_world_example_test.go
      id: test_code
      default: true
  learn_more:
    - name: GCP Hello, World
      url: https://github.com/gruntwork-io/terratest/tree/v1.0.1/examples/terraform-gcp-hello-world-example

- id: azure-basic
  name: Azure Hello, World Example
  image: /assets/img/logos/azure-logo.png
  files:
    - url: /examples/azure/terraform-azure-example/main.tf
      id: terraform_main_code
    - url: /examples/azure/terraform-azure-example/outputs.tf
      id: terraform_output_code
    - url: /examples/azure/terraform-azure-example/variables.tf
      id: terraform_var_code
    - url: /test/azure/terraform_azure_example_test.go
      id: test_code
      default: true
  learn_more:
    - name: Terraform Azure Example
      url: https://github.com/gruntwork-io/terratest/tree/v1.0.1/examples/azure/terraform-azure-example

- id: opa-terraform
  name: OPA Terraform Example
  image: /assets/img/logos/opa-logo.png
  files:
    - url: /examples/terraform-opa-example/pass/main_pass.tf
      id: pass_terraform_main_code
    - url: /examples/terraform-opa-example/fail/main_fail.tf
      id: fail_terraform_main_code
    - url: /examples/terraform-opa-example/policy/enforce_source.rego
      id: policy_main_code
    - url: /test/terraform_opa_example_test.go
      id: test_code
      default: true
  learn_more:
    - name: Terraform OPA Example
      url: https://github.com/gruntwork-io/terratest/tree/v1.0.1/examples/terraform-opa-example

- id: client-factory
  name: Azure Client Factory
  display_in_examples: false
  files:
    - url: /modules/azure/client_factory.go
      id: client_factory_code
    - url: /modules/azure/client_factory_test.go
      id: client_factory_test
    - url: /modules/azure/compute.go
      id: client_factory_helper

---

###  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:
  - https://godoc.org/github.com/gruntwork-io/terratest
target_blank: true
order: 104
nav_title: Documentation
nav_title_link: /docs/
---

---

###  Docs 01 Getting Started Introduction (`docs/_docs/01_getting-started/introduction.md`)

---
layout: collection-browser-doc
title: Introduction
category: getting-started
toc: true
excerpt: >-
  Terratest provides a variety of helper functions and patterns for common infrastructure testing tasks. Learn more about Terratest basic usage.
tags: ["basic-usage"]
order: 100
nav_title: Documentation
nav_title_link: /docs/
---

## 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/.

<iframe width="100%" height="450" allowfullscreen src="https://www.youtube.com/embed/xhHOW0EF5u8"></iframe>

### Slides

Slides to the video can be found here: [Slides: How to test infrastructure code](https://www.slideshare.net/brikis98/how-to-test-infrastructure-code-automated-testing-for-terraform-kubernetes-docker-packer-and-more){:target="\_blank"}.


## Gruntwork

Terratest was developed at [Gruntwork](https://gruntwork.io/) to help maintain the [Infrastructure as Code
Library](https://gruntwork.io/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.

<div class="cb-post-cta">
  <span class="title">See how to get started with Terratest</span>
  <a class="btn btn-primary" href="{{site.baseurl}}/docs/getting-started/quick-start/">Quick Start</a>
</div>

---

###  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](https://opentofu.org/). To follow
along, you need:

- [Go](https://golang.org/) (requires version >=1.26)
- [OpenTofu](https://opentofu.org/docs/intro/install/) (or [Terraform](https://www.terraform.io/), if you prefer)

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](#preferring-opentofu)).

The rest of this guide uses [mise](https://mise.jdx.dev/) 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](#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
    ```

1. 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 go@1.26
    mise use opentofu@1.12.3
    ```

    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.

1. 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
    ```

1. 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>`.

1. 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]({{site.baseurl}}/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.

1. 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.

1. 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/).

1. 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](https://golang.org/pkg/testing/): you create a file ending in `_test.go` and run tests with the `go test` command. E.g., `go test my_test.go`.
1. 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).
1. 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.
1. 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](https://opentofu.org/) code, which just outputs the text,
"Hello, World" (if you’re new to OpenTofu or Terraform, check out our [Comprehensive Guide to
Terraform](https://blog.gruntwork.io/a-comprehensive-guide-to-terraform-b3d32832baca), 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.
1. When `apply` finishes, check that the output variable says, "Hello, World".
1. 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`](https://blog.golang.org/defer-panic-and-recover) 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](https://aws.amazon.com/ec2/) that is running an Ubuntu 
[Amazon Machine Image (AMI)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIs.html). To keep this example 
simple, we specify a [User Data](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html#user-data-api-cli) 
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.
1. When `apply` finishes, get the IP of the web server by reading the `public_ip` output variable.
1. 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.
1. 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](https://www.docker.com/) 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.
1. Run the image via `docker run`.
1. 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](https://kubernetes.io/) 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](https://hub.docker.com/r/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.
1. Use the Kubernetes APIs to figure out the endpoint to hit for the load balancer.
1. 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.
1. 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](https://github.com/gruntwork-io/terratest). To 
learn more:

1. Check out the [examples]({{site.baseurl}}/examples/) and the corresponding automated tests for those examples for fully working (and tested!) sample code.
1. Browse through the list of [Terratest packages]({{site.baseurl}}/docs/getting-started/packages-overview/) to get a sense of all the tools available in Terratest.
1. Read our [Testing Best Practices Guide]({{site.baseurl}}/docs/#testing-best-practices).
1. Check out real-world examples of Terratest usage in our open source infrastructure modules: [Consul](https://github.com/hashicorp/terraform-aws-consul), [Vault](https://github.com/hashicorp/terraform-aws-vault), [Nomad](https://github.com/hashicorp/terraform-aws-nomad).

Happy testing!

---

###  Docs 01 Getting Started Testing Terragrunt (`docs/_docs/01_getting-started/testing-terragrunt.md`)

---
layout: collection-browser-doc
title: Testing Terragrunt
category: getting-started
excerpt: >-
  Learn how to test Terragrunt configurations with Terratest.
tags: ["terragrunt", "testing", "quick-start"]
order: 105
nav_title: Documentation
nav_title_link: /docs/
---

## 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](https://terragrunt.gruntwork.io/docs/features/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

- [Terragrunt Documentation](https://terragrunt.gruntwork.io/)
- [Stack example](https://github.com/gruntwork-io/terratest/tree/{{ site.stable_ref }}/examples/terragrunt-multi-module-example)
- [terragrunt package reference](https://pkg.go.dev/github.com/gruntwork-io/terratest/modules/terragrunt)

---

###  Docs 01 Getting Started Version Pinning (`docs/_docs/01_getting-started/version-pinning.md`)

---
layout: collection-browser-doc
title: Pinning a Terratest version
category: getting-started
excerpt: Lock your tests to a specific Terratest release.
tags: ["versioning", "go-modules", "pinning"]
order: 106
nav_title: Documentation
nav_title_link: /docs/
---

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/terratest@v0.56.0
go mod tidy
```

Replace `v0.56.0` with the tag you want from the [Releases page](https://github.com/gruntwork-io/terratest/releases). 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]({{site.baseurl}}/docs/migrating-to-v2/overview/).

---

###  Docs 02 Testing Best Practices Alternative Testing Tools (`docs/_docs/02_testing-best-practices/alternative-testing-tools.md`)

---
layout: collection-browser-doc
title: Alternative testing tools
category: testing-best-practices
excerpt: >-
  Learn more about alternatives to Terratest, and how Terratest compares to other testing tools.
tags: ["testing-best-practices", "alternatives"]
order: 211
nav_title: Documentation
nav_title_link: /docs/
---

## 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]({{site.baseurl}}/docs/testing-best-practices/alternative-testing-tools/#how-terratest-compares-to-other-testing-tools) to understand the trade-offs.

1.  [kitchen-terraform](https://github.com/newcontext-oss/kitchen-terraform)
1.  [rspec-terraform](https://github.com/bsnape/rspec-terraform)
1.  [serverspec](https://serverspec.org/)
1.  [inspec](https://www.inspec.io/)
1.  [Goss](https://github.com/aelsabbahy/goss)
1.  [awspec](https://github.com/k1LoW/awspec)
1.  [Terraform's acceptance testing framework](https://github.com/hashicorp/terraform/blob/master/.github/CONTRIBUTING.md#acceptance-tests-testing-interactions-with-external-services)
1.  [ruby_terraform](https://github.com/infrablocks/ruby_terraform)



## Why Terratest?

Our experience with building the [Infrastructure as Code Library](https://gruntwork.io/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](https://github.com/hashicorp/terraform-aws-vault/tree/master/modules) do the following:

1.  Use Packer to build an AMI.
1.  Use Terraform to create self-signed TLS certificates.
1.  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.
1.  SSH to a Vault node to initialize the cluster.
1.  SSH to all the Vault nodes to unseal them.
1.  Use the Vault SDK to store data in Vault.
1.  Use the Vault SDK to make sure you can read the same data back out of Vault.
1.  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`)

---
layout: collection-browser-doc
title: Avoid test caching
category: testing-best-practices
excerpt: >-
  Since Go 1.10, test results are automatically cached. See how to turn off caching test results.
tags: ["testing-best-practices", "cache"]
order: 207
nav_title: Documentation
nav_title_link: /docs/
---

Since Go 1.10, test results are automatically [cached](https://golang.org/doc/go1.10#test). 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`)

---
layout: collection-browser-doc
title: Cleanup
category: testing-best-practices
excerpt: >-
  Since automated tests with Terratest deploy real resources into real environments, you'll want to make sure your tests
  always cleanup after themselves.
tags: ["testing-best-practices", "clean", "terraform-destroy", "terraform-apply"]
order: 204
nav_title: Documentation
nav_title_link: /docs/
---

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](https://github.com/gruntwork-io/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`)

---
layout: collection-browser-doc
title: Error handling
category: testing-best-practices
excerpt: >-
  Learn how to handle errors.
tags: ["testing-best-practices", "terraform", "error"]
order: 208
nav_title: Documentation
nav_title_link: /docs/
---

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`)

---
layout: collection-browser-doc
title: Idempotent
category: testing-best-practices
excerpt: >-
  Test that your Terraform configuration results in consistent deployments.
tags: ["testing-best-practices", "idempotent", "terraform"]
order: 212
nav_title: Documentation
nav_title_link: /docs/
---

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. 
1.  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`)

---
layout: collection-browser-doc
title: Iterating locally using Docker
category: testing-best-practices
excerpt: >-
  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.
tags: ["testing-best-practices", "docker"]
order: 209
nav_title: Documentation
nav_title_link: /docs/
---

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](https://www.packer.io/docs/builders/docker.html) 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`)

---
layout: collection-browser-doc
title: Iterating locally using test stages
category: testing-best-practices
excerpt: >-
  Learn more about Terratest's `teststructure`.
tags: ["testing-best-practices", "teststructure"]
order: 210
nav_title: Documentation
nav_title_link: /docs/
---

Most automated tests written with Terratest consist of multiple "stages", such as:

1.  Build an AMI using Packer
1.  Deploy the AMI using Terraform
1.  Validate that the AMI works as expected
1.  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`)

---
layout: collection-browser-doc
title: Namespacing
category: testing-best-practices
excerpt: >-
  Learn how to avoid conflicts due to duplicated identifiers.
tags: ["testing-best-practices", "namespace", "id", "identifiers"]
order: 203
nav_title: Documentation
nav_title_link: /docs/
---

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).
1.  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`)

---
layout: collection-browser-doc
title: Picking EC2 instance types
category: testing-best-practices
excerpt: >-
  Pick EC2 instance types that are available in the current AWS region.
tags: ["testing-best-practices", "aws", "ec2"]
order: 213
nav_title: Documentation
nav_title_link: /docs/
---

It's common to want to test infrastructure code that deploys [EC2 instances](https://aws.amazon.com/ec2/) into AWS.
There are many different [instance types](https://aws.amazon.com/ec2/instance-types/), but not all instance types
are available in all [regions or availability zones
(AZs)](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/using-regions-availability-zones.html). 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`](#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`)

---
layout: collection-browser-doc
title: Testing environment
category: testing-best-practices
excerpt: >-
  Learn more about testing environments.
tags: ["testing-best-practices"]
order: 202
nav_title: Documentation
nav_title_link: /docs/
---

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](https://en.wikipedia.org/wiki/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`)

---
layout: collection-browser-doc
title: Timeouts and logging
category: testing-best-practices
excerpt: >-
  Long-running infrastructure tests may exceed timeouts or can be killed if they do not prompt logs.
tags: ["testing-best-practices", "timeout", "error"]
order: 205
nav_title: Documentation
nav_title_link: /docs/
---

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]({{site.baseurl}}/docs/testing-best-practices/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`)

---
layout: collection-browser-doc
title: Tools and Plugins
category: testing-best-practices
excerpt: >-
  Additional tools and plugins for terratest to make integration with existing workflows easier.
tags: ["testing-best-practices", "alternatives","plugins","tooling"]
order: 214
nav_title: Documentation
nav_title_link: /docs/
---

## 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!

- [Tools and Plugins](#tools-and-plugins)
  - [Terratest Maven Plugin](#terratest-maven-plugin)

### 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](https://terratest-maven-plugin.github.io) and the [GitHub repository](https://github.com/terratest-maven-plugin/terratest-maven-plugin)

---

###  Docs 02 Testing Best Practices Unit Integration End To End Test (`docs/_docs/02_testing-best-practices/unit-integration-end-to-end-test.md`)

---
layout: collection-browser-doc
title: Unit tests, integration tests, end-to-end tests
category: testing-best-practices
excerpt: >-
  See the talk about unit tests, integration tests, end-to-end tests, dependency injection, test parallelism, retries, error handling, and static analysis.
tags: ["testing-best-practices"]
order: 201
nav_title: Documentation
nav_title_link: /docs/
---


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".

<iframe width="100%" height="450" allowfullscreen src="https://www.youtube.com/embed/xhHOW0EF5u8"></iframe>

Link to the video at [infoq.com](https://www.infoq.com/presentations/automated-testing-terraform-docker-packer/).

## Slides

Slides to the video can be found here: [Slides: How to test infrastructure code](https://www.slideshare.net/brikis98/how-to-test-infrastructure-code-automated-testing-for-terraform-kubernetes-docker-packer-and-more){:target="_blank"}.

---

###  Docs 03 Migrating To V1 Azure (`docs/_docs/03_migrating-to-v1/azure.md`)

---
layout: collection-browser-doc
title: Azure modules
category: migrating-to-v1
excerpt: >-
  Migrate Azure tests from Terratest pre-v1 to v1.0.0.
tags: ["azure", "migration", "v1"]
order: 301
nav_title: Documentation
nav_title_link: /docs/
---

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:

```
/* 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`)

---
layout: collection-browser-doc
title: Behavior changes
category: migrating-to-v2
excerpt: >-
  The two v2 changes the compiler will not find for you. Both are in the
  k8s module.
tags: ["migration", "v2"]
order: 403
nav_title: Documentation
nav_title_link: /docs/
---

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]({{site.baseurl}}/docs/migrating-to-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`)

---
layout: collection-browser-doc
title: Import map
category: migrating-to-v2
excerpt: >-
  Every v1 import path and what it becomes in v2.
tags: ["migration", "v2"]
order: 402
nav_title: Documentation
nav_title_link: /docs/
---

The complete v1 to v2 path mapping. See [rewriting
imports]({{site.baseurl}}/docs/migrating-to-v2/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`)

---
layout: collection-browser-doc
title: Rewriting imports
category: migrating-to-v2
excerpt: >-
  The mechanical part of the v2 migration, and the places a blind
  find-and-replace gets it wrong.
tags: ["migration", "v2"]
order: 401
nav_title: Documentation
nav_title_link: /docs/
---

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](#contribution-guidelines) and [Developing Terratest](#developing-terratest) for
instructions.

## Contribution Guidelines

Contributions to this repo are very welcome! We follow a fairly standard [pull request
process](https://help.github.com/articles/about-pull-requests/) for contributions, subject to the following guidelines:

1. [Types of contributions](#types-of-contributions)
1. [File a GitHub issue](#file-a-github-issue)
1. [Update the documentation](#update-the-documentation)
1. [Update the tests](#update-the-tests)
1. [Update the code](#update-the-code)
1. [Create a pull request](#create-a-pull-request)
1. [Merge and release](#merge-and-release)

### Types of contributions

Broadly speaking, Terratest contains two types of helper functions:

1. Integrations with external tools
1. 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!  

1. **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.

1. **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.

1. **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?

1. **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](http://tom.preston-werner.com/2010/08/23/readme-driven-development.html)). 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](https://github.com/gruntwork-io/terratest/tree/main/docs#working-with-the-documentation) 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](https://en.wikipedia.org/wiki/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](https://terratest.gruntwork.io/docs/community/contributing/#developing-terratest).

### 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](https://pre-commit.com/).
1. Run `pre-commit install`.

One of the pre-commit hooks we run is [goimports](https://godoc.org/golang.org/x/tools/cmd/goimports). To prevent the
hook from failing, make sure to :

1. Install [goimports](https://godoc.org/golang.org/x/tools/cmd/goimports)
1. Run `goimports -w .`.

We have a [style guide](https://gruntwork.io/guides/style%20guides/golang-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](https://help.github.com/articles/creating-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.
1. The output of your automated test run, preferably in a [GitHub Gist](https://gist.github.com/). We cannot run
   automated tests for pull requests automatically due to [security
   concerns](https://circleci.com/docs/2.0/oss/#security), so we need you to manually provide this
   test output so we can verify that everything is working.
1. Any notes on backwards incompatibility or downtime.

#### Validate the Pull Request for Azure Platform

If you're contributing code for the [Azure Platform](https://azure.com) and if you have an active _Azure subscription_, it's recommended to follow the below guidelines after [creating a pull request](https://help.github.com/articles/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](https://docs.microsoft.com/cli/azure/) 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
    ```

1. Go to Secrets settings page under `Settings` tab in your forked project, `https://github.com/<YOUR_GITHUB_ACCOUNT>/terratest/settings`, on GitHub.

1. Create a new `Secret` named `AZURE_CREDENTIALS` and paste the Azure credentials you copied from the 1<sup>st</sup> 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](https://docs.github.com/en/free-pro-team@latest/actions/reference/encrypted-secrets) 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](https://libsodium.gitbook.io/doc/public-key_cryptography/sealed_boxes) to help ensure that secrets are encrypted before they reach GitHub.

1. Create a [new Personal Access Token (PAT)](https://github.com/settings/tokens/new) page under [Settings](https://github.com/settings/profile) / [Developer Settings](https://github.com/settings/apps), making sure `write:discussion` and `public_repo` scopes are checked. Click the _Generate token_ button and copy the generated PAT.

1. Go back to settings/secrets in your fork and [Create a new Secret](https://docs.github.com/actions/reference/encrypted-secrets#creating-encrypted-secrets-for-a-repository) named `PAT`.  Paste the output from the 4<sup>th</sup> 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](https://docs.github.com/en/free-pro-team@latest/actions/reference/encrypted-secrets) 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](https://libsodium.gitbook.io/doc/public-key_cryptography/sealed_boxes) to help ensure that secrets are encrypted before they reach GitHub.

1. Go to Actions tab on GitHub (https://github.com/<GITHUB_ACCOUNT>/terratest/actions)

1. Click `ci-workflow` workflow

1. 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_)

1. 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.

1. 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](https://github.com/gruntwork-io/terratest/releases).

## Developing Terratest

1. [Running tests](#running-tests)
1. [Versioning](#versioning)
1. [Developing For Azure](#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](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html). 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](http://semver.org/). You can find each new release,
along with the changelog, in the [Releases Page](https://github.com/gruntwork-io/terratest/releases).

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](https://godoc.org/github.com/Azure/go-autorest/autorest/azure#EnvironmentFromName).

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](https://www.terraform.io/docs/backends/types/azurerm.html#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](https://godoc.org/github.com/Azure/azure-sdk-for-go).  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`)

---
layout: collection-browser-doc
title: License
category: community
excerpt: >-
  This code is released under the Apache 2.0 License. Read more here.
tags: ["license"]
order: 502
nav_title: Documentation
nav_title_link: /docs/
---

## License

This code is released under the Apache 2.0 License. See [LICENSE](https://github.com/gruntwork-io/terratest/blob/main/LICENSE){:target="_blank"} and [NOTICE](https://github.com/gruntwork-io/terratest/blob/main/NOTICE){:target="_blank"} for more details.

---

###  Docs 05 Community Support (`docs/_docs/05_community/support.md`)

---
layout: collection-browser-doc
title: Support
category: community
excerpt: >-
  Need help?
tags: ["support", "community"]
order: 501
nav_title: Documentation
nav_title_link: /docs/
---

## Github Discussions

Search our [Knowledge Base](https://github.com/gruntwork-io/knowledge-base/discussions) 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](https://github.com/gruntwork-io/terratest/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](https://gruntwork.io/support) for more details.

---

###  Pages 404 404 (`docs/_pages/404/404.md`)

---
permalink: /404.html
slug: 404
layout: subpage
title: 404
subtitle: Page not found :(
classes: text-large text-center subpage-404
---

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 ---
- Files Extracted: 113
- Estimated Token Budget: ~85851 tokens
- Canonical Reference: https://codewiki.google/github.com/gruntwork-io/terratest
