Skip to content

Commit f1b4488

Browse files
authored
Merge branch 'main' into james/terratest-v2-deprecate-git-versionchecker-slack
2 parents d8ec244 + 9581f3a commit f1b4488

11 files changed

Lines changed: 109 additions & 50 deletions

File tree

README.md

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
Terratest is a Go library that makes it easier to write automated tests for your infrastructure code. It provides a
99
variety of helper functions and patterns for common infrastructure testing tasks, including:
1010

11-
- Testing Terraform code
11+
- Testing OpenTofu and Terraform code
1212
- Testing Packer templates
1313
- Testing Docker images
1414
- Executing commands on servers over SSH
@@ -21,6 +21,23 @@ variety of helper functions and patterns for common infrastructure testing tasks
2121
- Running shell commands
2222
- And much more
2323

24+
## What Terratest is for
25+
26+
Terratest is a Go library for writing automated tests of infrastructure code. It covers five workflows that, together,
27+
let you test infrastructure end to end:
28+
29+
- **Deploy** OpenTofu, Terragrunt, Packer, or Docker from Go and capture their output.
30+
- **Inspect** what got deployed by calling cloud provider APIs (AWS, Azure, GCP, Kubernetes).
31+
- **Interact** with it over the network: SSH, HTTP, DNS, and database checks that cloud SDKs alone can't do.
32+
- **Validate** behavior and policy: OPA against OpenTofu plans, test-stage orchestration, retry-with-backoff for
33+
eventual consistency.
34+
- **Tear down** with `tofu destroy` and cleanup helpers.
35+
36+
Terratest is deliberately scoped. It is not a unit-testing framework (Go's standard `testing` covers that), a mocking
37+
library, a general-purpose utility collection, or a CI/notification tool. Helpers that fall outside the five workflows
38+
above, including ones the standard library already covers, are being deprecated and removed in v2. See
39+
[What Terratest is for](https://terratest.gruntwork.io/docs/getting-started/what-terratest-is-for/) for the full picture.
40+
2441
## Install
2542

2643
```bash

docs/Gemfile.lock

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ GEM
3737
ffi (>= 1.3.0)
3838
eventmachine (1.2.7)
3939
execjs (2.7.0)
40-
faraday (2.14.2)
40+
faraday (2.14.3)
4141
faraday-net_http (>= 2.0, < 3.5)
4242
json
4343
logger
44-
faraday-net_http (3.4.2)
44+
faraday-net_http (3.4.4)
4545
net-http (~> 0.5)
4646
ffi (1.13.1)
4747
forwardable-extended (2.6.0)
@@ -213,7 +213,7 @@ GEM
213213
gemoji (~> 3.0)
214214
html-pipeline (~> 2.2)
215215
jekyll (>= 3.0, < 5.0)
216-
json (2.19.5)
216+
json (2.20.0)
217217
kramdown (2.3.2)
218218
rexml
219219
kramdown-parser-gfm (1.1.0)

docs/_docs/01_getting-started/examples.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ excerpt: Examples are the best way to start testing Terraform, Docker, Packer, K
55
tags: ["example"]
66
redirect_to:
77
- /examples/
8-
order: 102
8+
order: 103
99
nav_title: Documentation
1010
nav_title_link: /docs/
1111
---

docs/_docs/01_getting-started/godoc.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ tags: ["packages"]
88
redirect_to:
99
- https://godoc.org/github.com/gruntwork-io/terratest
1010
target_blank: true
11-
order: 104
11+
order: 105
1212
nav_title: Documentation
1313
nav_title_link: /docs/
1414
---

docs/_docs/01_getting-started/packages-overview.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,29 @@ layout: collection-browser-doc
33
title: Package by package overview
44
category: getting-started
55
excerpt: >-
6-
Learn more about Terratest modules and how they can help you test different types infrastructure.
6+
Learn more about Terratest modules and how they can help you test different types of infrastructure.
77
tags: ["packages"]
8-
order: 103
8+
order: 104
99
nav_title: Documentation
1010
nav_title_link: /docs/
1111
---
1212

1313
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
14-
Terratest's [modules folder](https://github.com/gruntwork-io/terratest/tree/main/modules) and how they can help you test different types infrastructure:
14+
Terratest's [modules folder](https://github.com/gruntwork-io/terratest/tree/main/modules) and how they can help you test different types of infrastructure:
15+
16+
Some packages are **deprecated** and scheduled for removal in v2 because they fall outside [what Terratest is for]({{ site.baseurl }}/docs/getting-started/what-terratest-is-for/) (for example, helpers the Go standard library already covers). They keep working for the rest of v1; their GoDoc points at the recommended replacement.
1517

1618
{:.doc-styled-table}
1719
| Package | Description |
1820
| ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
1921
| **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. |
2022
| **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. |
21-
| **collections** | Go doesn't have much of a collections library built-in, so this package has a few helper methods for working with lists and maps. Examples: subtract two lists from each other. |
23+
| **collections** | _Deprecated (removed in v2): use the standard library `slices`/`strings`._ A few helper methods for working with lists. Examples: subtract two lists from each other. |
2224
| **docker** | Functions that make it easier to work with Docker and Docker Compose. Examples: run `docker compose` commands. |
23-
| **environment** | Functions for interacting with os environment. Examples: check for first non empty environment variable in a list. |
25+
| **environment** | _Deprecated (removed in v2): use the standard library `os.Getenv`._ Functions for interacting with os environment. Examples: check for first non empty environment variable in a list. |
2426
| **files** | Functions for manipulating files and folders. Examples: check if a file exists, copy a folder and all of its contents. |
2527
| **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. |
26-
| **git** | Functions for working with Git. Examples: get the name of the current Git branch. |
28+
| **git** | _Deprecated (removed in v2): shell out to `git` with `os/exec`._ Functions for working with Git. Examples: get the name of the current Git branch. |
2729
| **helm** | Functions for working with Helm. Examples: Install a Helm chart. |
2830
| **http-helper** | 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. |
2931
| **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. |
@@ -34,7 +36,9 @@ Terratest's [modules folder](https://github.com/gruntwork-io/terratest/tree/main
3436
| **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. |
3537
| **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. |
3638
| **shell** | Functions to run shell commands. Examples: run a shell command and return its `stdout` and `stderr`. |
39+
| **slack** | _Deprecated (removed in v2): use the slack-go client directly._ Functions for validating Slack messages posted during a test. |
3740
| **ssh** | Functions to SSH to servers. Examples: SSH to a server, execute a command, and return `stdout` and `stderr`. |
38-
| **terraform** | Functions for working with Terraform. Examples: run `terraform init`, `terraform apply`, `terraform destroy`. |
41+
| **terraform** | Functions for working with OpenTofu and Terraform. Examples: run `init`, `apply`, and `destroy`. |
3942
| **terragrunt** | Functions for working with Terragrunt. Examples: run `terragrunt apply --all`, `terragrunt destroy --all`, test stack configurations with dependencies, and work with Terragrunt stacks. |
4043
| **test_structure** | 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. |
44+
| **version-checker** | _Deprecated (removed in v2): shell out to check a binary's version yourself._ Functions for checking a binary's version against a constraint. |

docs/_docs/01_getting-started/quick-start.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ title: Quick start
44
category: getting-started
55
excerpt: Learn how to start with Terratest.
66
tags: ["quick-start"]
7-
order: 101
7+
order: 102
88
nav_title: Documentation
99
nav_title_link: /docs/
1010
custom_js:

docs/_docs/01_getting-started/testing-terragrunt.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ category: getting-started
55
excerpt: >-
66
Learn how to test Terragrunt configurations with Terratest.
77
tags: ["terragrunt", "testing", "quick-start"]
8-
order: 105
8+
order: 106
99
nav_title: Documentation
1010
nav_title_link: /docs/
1111
---

docs/_docs/01_getting-started/version-pinning.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ title: Pinning a Terratest version
44
category: getting-started
55
excerpt: Lock your tests to a specific Terratest release.
66
tags: ["versioning", "go-modules", "pinning"]
7-
order: 106
7+
order: 107
88
nav_title: Documentation
99
nav_title_link: /docs/
1010
---
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
---
2+
layout: collection-browser-doc
3+
title: What Terratest is for
4+
category: getting-started
5+
toc: true
6+
excerpt: >-
7+
Terratest is a Go library for writing automated tests of infrastructure code. Learn the five workflows it covers, and what it is deliberately not.
8+
tags: ["basic-usage"]
9+
order: 101
10+
nav_title: Documentation
11+
nav_title_link: /docs/
12+
---
13+
14+
Terratest is a Go library for writing automated tests of infrastructure code. You write ordinary `_test.go` files, and
15+
Terratest gives you the helpers that make infrastructure-as-code (IaC) testing practical. Once you know what the library
16+
is for, it is easier to decide which helpers to reach for, and to understand why some packages are being trimmed over
17+
time.
18+
19+
## The five workflows
20+
21+
Terratest covers five workflows. Together, they let you test infrastructure from end to end.
22+
23+
- **Deploy.** Run `tofu`, `terragrunt`, `packer`, or `docker` from Go and capture their output.
24+
- **Inspect.** Call cloud provider APIs (AWS, Azure, GCP, and Kubernetes) to verify that resources were created as
25+
expected.
26+
- **Interact.** Run the post-deploy connectivity checks that cloud SDKs alone can't do: SSH into instances, hit HTTP
27+
endpoints, resolve DNS records, and query databases.
28+
- **Validate.** Check OpenTofu plans against policy with OPA, orchestrate test stages with `test_structure`, and retry
29+
with backoff to handle eventual consistency.
30+
- **Tear down.** Run `tofu destroy` and clean up with related helpers.
31+
32+
## The primitives underneath
33+
34+
Every IaC test leans on a handful of generic building blocks: unique IDs for resource names, file and fixture helpers,
35+
shell execution, the `TestingT` interface, retry with backoff, and a small logging wrapper around the `Logf` method on
36+
`*testing.T`. None of these are specific to infrastructure, but every Terratest test depends on them, so they ship with
37+
the library in the `random`, `files`, `shell`, `testing`, `retry`, and `logger` packages.
38+
39+
## What Terratest is not
40+
41+
Terratest is deliberately narrow in scope. It is not:
42+
43+
- A unit-testing framework. Go's standard `testing` package already covers that.
44+
- A mocking library.
45+
- A general-purpose utility collection. Anything the standard library already handles (slice and map helpers,
46+
environment-variable lookups, thin wrappers around `git`, and the like) does not belong here.
47+
- A CI or notification tool.
48+
49+
The rule of thumb: everything in Terratest should serve one of the five workflows above, or directly support them.
50+
Helpers that don't (standard-library wrappers, standalone CLI tools, and anything unrelated to IaC testing) are
51+
candidates for removal.
52+
53+
## Scope and deprecations
54+
55+
As Terratest moves toward v2, packages that fall outside this scope are being deprecated and will eventually be removed.
56+
A deprecated package carries a `// Deprecated:` note in its GoDoc that points to the recommended replacement, which is
57+
usually the standard library. These packages keep working for the rest of v1, so you get a full release cycle to
58+
migrate. If you need to stay on a specific release while you do, see
59+
[Pinning a Terratest version]({{ site.baseurl }}/docs/getting-started/version-pinning/).

modules/shell/command.go

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import (
1010
"os/exec"
1111
"strings"
1212
"sync"
13-
"syscall"
1413

1514
"github.com/gruntwork-io/terratest/modules/logger"
1615
"github.com/gruntwork-io/terratest/modules/testing"
@@ -240,7 +239,7 @@ func readStdoutAndStderr(t testing.TestingT, log *logger.Logger, stdout, stderr
240239
stdoutReader := bufio.NewReader(stdout)
241240
stderrReader := bufio.NewReader(stderr)
242241

243-
wg := &sync.WaitGroup{}
242+
var wg sync.WaitGroup
244243

245244
wg.Add(2) //nolint:mnd // 2 goroutines: one for stdout, one for stderr
246245

@@ -260,15 +259,7 @@ func readStdoutAndStderr(t testing.TestingT, log *logger.Logger, stdout, stderr
260259

261260
wg.Wait()
262261

263-
if stdoutErr != nil {
264-
return out, stdoutErr
265-
}
266-
267-
if stderrErr != nil {
268-
return out, stderrErr
269-
}
270-
271-
return out, nil
262+
return out, errors.Join(stdoutErr, stderrErr)
272263
}
273264

274265
func readData(t testing.TestingT, log *logger.Logger, reader *bufio.Reader, writer io.StringWriter) error {
@@ -316,28 +307,16 @@ func readData(t testing.TestingT, log *logger.Logger, reader *bufio.Reader, writ
316307
return nil
317308
}
318309

319-
// GetExitCodeForRunCommandError tries to read the exit code for the error object returned from running a shell command. This is a bit tricky to do
320-
// in a way that works across platforms.
310+
// GetExitCodeForRunCommandError tries to read the exit code for the error object returned from running a shell command.
321311
func GetExitCodeForRunCommandError(err error) (int, error) {
322312
var errWithOutput *ErrWithCmdOutput
323313
if errors.As(err, &errWithOutput) {
324314
err = errWithOutput.Underlying
325315
}
326316

327-
// http://stackoverflow.com/a/10385867/483528
328317
var exitErr *exec.ExitError
329318
if errors.As(err, &exitErr) {
330-
// The program has exited with an exit code != 0
331-
332-
// This works on both Unix and Windows. Although package
333-
// syscall is generally platform dependent, WaitStatus is
334-
// defined for both Unix and Windows and in both cases has
335-
// an ExitStatus() method with the same signature.
336-
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
337-
return status.ExitStatus(), nil
338-
}
339-
340-
return 1, errors.New("could not determine exit code")
319+
return exitErr.ExitCode(), nil
341320
}
342321

343322
return 0, nil
@@ -346,7 +325,7 @@ func GetExitCodeForRunCommandError(err error) (int, error) {
346325
func formatEnvVars(command *Command) []string {
347326
env := os.Environ()
348327
for key, value := range command.Env {
349-
env = append(env, fmt.Sprintf("%s=%s", key, value))
328+
env = append(env, key+"="+value)
350329
}
351330

352331
return env

0 commit comments

Comments
 (0)