Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into tofu-1-8
Browse files Browse the repository at this point in the history
  • Loading branch information
denis256 committed Aug 8, 2024
2 parents 2c17b36 + 91e02fb commit e2ae16f
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 8 deletions.
3 changes: 2 additions & 1 deletion examples/terraform-aws-lambda-example/src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
The lambda executable `handler` was built using

``` shell
go build bootstrap.go
go get github.com/aws/aws-lambda-go/lambda
GOOS=linux GOARCH=amd64 go build -tags lambda.norpc -o bootstrap .
```
Binary file modified examples/terraform-aws-lambda-example/src/bootstrap
Binary file not shown.
9 changes: 5 additions & 4 deletions modules/retry/retry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,19 +115,20 @@ func TestDoWithTimeout(t *testing.T) {
func TestDoInBackgroundUntilStopped(t *testing.T) {
t.Parallel()

sleepBetweenRetries := 5 * time.Second
sleepBetweenRetries := 2 * time.Second
waitStop := sleepBetweenRetries*2 + sleepBetweenRetries/2
counter := 0

stop := DoInBackgroundUntilStopped(t, t.Name(), sleepBetweenRetries, func() {
counter++
t.Log(time.Now(), counter)
})

time.Sleep(sleepBetweenRetries * 3)
time.Sleep(waitStop)
stop.Done()

assert.Equal(t, 3, counter)

time.Sleep(sleepBetweenRetries * 3)
time.Sleep(waitStop)
assert.Equal(t, 3, counter)
}

Expand Down
68 changes: 68 additions & 0 deletions modules/terraform/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package terraform

import (
"path/filepath"
"strings"
"testing"
"time"

Expand Down Expand Up @@ -63,6 +64,73 @@ func TestApplyWithErrorWithRetry(t *testing.T) {

require.Contains(t, out, "This is the first run, exiting with an error")
}

func TestApplyWithWarning(t *testing.T) {
scenarios := []struct {
name string
folder string
isError bool
warnings map[string]string
}{
{
name: "Warning",
folder: "../../test/fixtures/terraform-with-warning",
isError: true,
warnings: map[string]string{
"lorem ipsum": "lorem ipsum warning",
},
},
{
name: "WarningNotMatch",
folder: "../../test/fixtures/terraform-with-warning",
isError: false,
warnings: map[string]string{
"lorem ipsum dolor sit amet": "some warning",
},
},
{
name: "Error",
folder: "../../test/fixtures/terraform-with-error",
isError: true,
warnings: map[string]string{
"lorem ipsum": "lorem ipsum warning",
},
},
{
name: "NoError",
folder: "../../test/fixtures/terraform-no-error",
isError: false,
warnings: map[string]string{
"lorem ipsum": "lorem ipsum warning",
},
},
}

for _, scenario := range scenarios {
scenario := scenario
t.Run(scenario.name, func(t *testing.T) {
t.Parallel()

testFolder, err := files.CopyTerraformFolderToTemp(scenario.folder, strings.Replace(t.Name(), "/", "-", -1))
require.NoError(t, err)

options := WithDefaultRetryableErrors(t, &Options{
TerraformDir: testFolder,
NoColor: true,
WarningsAsErrors: scenario.warnings,
})

out, err := InitAndApplyE(t, options)
if scenario.isError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
assert.NotEmpty(t, out)
})
}
}

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

Expand Down
38 changes: 36 additions & 2 deletions modules/terraform/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package terraform
import (
"fmt"
"os/exec"
"regexp"
"strings"

"github.com/gruntwork-io/terratest/modules/collections"
"github.com/gruntwork-io/terratest/modules/retry"
Expand Down Expand Up @@ -81,9 +83,18 @@ func RunTerraformCommandE(t testing.TestingT, additionalOptions *Options, additi

cmd := generateCommand(options, args...)
description := fmt.Sprintf("%s %v", options.TerraformBinary, args)

return retry.DoWithRetryableErrorsE(t, description, options.RetryableTerraformErrors, options.MaxRetries, options.TimeBetweenRetries, func() (string, error) {
return shell.RunCommandAndGetOutputE(t, cmd)
s, err := shell.RunCommandAndGetOutputE(t, cmd)
if err != nil {
return s, err
}
if err := hasWarning(additionalOptions, s); err != nil {
return s, err
}
return s, err
})

}

// RunTerraformCommandAndGetStdoutE runs terraform with the given arguments and options and returns solely its stdout
Expand All @@ -94,7 +105,14 @@ func RunTerraformCommandAndGetStdoutE(t testing.TestingT, additionalOptions *Opt
cmd := generateCommand(options, args...)
description := fmt.Sprintf("%s %v", options.TerraformBinary, args)
return retry.DoWithRetryableErrorsE(t, description, options.RetryableTerraformErrors, options.MaxRetries, options.TimeBetweenRetries, func() (string, error) {
return shell.RunCommandAndGetStdOutE(t, cmd)
s, err := shell.RunCommandAndGetOutputE(t, cmd)
if err != nil {
return s, err
}
if err := hasWarning(additionalOptions, s); err != nil {
return s, err
}
return s, err
})
}

Expand Down Expand Up @@ -137,3 +155,19 @@ func defaultTerraformExecutable() string {
// fallback to Tofu if terraform is not available
return TofuDefaultPath
}

func hasWarning(opts *Options, out string) error {
for k, v := range opts.WarningsAsErrors {
str := fmt.Sprintf("\nWarning: %s[^\n]*\n", k)
re, err := regexp.Compile(str)
if err != nil {
return fmt.Errorf("cannot compile regex for warning detection: %w", err)
}
m := re.FindAllString(out, -1)
if len(m) == 0 {
continue
}
return fmt.Errorf("warning(s) were found: %s:\n%s", v, strings.Join(m, ""))
}
return nil
}
5 changes: 5 additions & 0 deletions modules/terraform/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ type Options struct {
PlanFilePath string // The path to output a plan file to (for the plan command) or read one from (for the apply command)
PluginDir string // The path of downloaded plugins to pass to the terraform init command (-plugin-dir)
SetVarsAfterVarFiles bool // Pass -var options after -var-file options to Terraform commands
WarningsAsErrors map[string]string // Terraform warning messages that should be treated as errors. The keys are a regexp to match against the warning and the value is what to display to a user if that warning is matched.
}

// Clone makes a deep copy of most fields on the Options object and returns it.
Expand Down Expand Up @@ -99,6 +100,10 @@ func (options *Options) Clone() (*Options, error) {
for key, val := range options.RetryableTerraformErrors {
newOptions.RetryableTerraformErrors[key] = val
}
newOptions.WarningsAsErrors = make(map[string]string)
for key, val := range options.WarningsAsErrors {
newOptions.WarningsAsErrors[key] = val
}

return newOptions, nil
}
Expand Down
22 changes: 22 additions & 0 deletions test/fixtures/terraform-with-warning/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
terraform {
required_providers {
validation = {
source = "tlkamp/validation"
version = "1.1.1"
}
null = {
source = "hashicorp/null"
version = "3.2.2"
}
}
}

# this data source will produce warning when `condition` is evaluated to `true`
data "validation_warning" "warn" {
for_each = toset([for i in range(10) : format("%02d", i)])
condition = true
summary = "lorem ipsum ${each.value}"
details = "lorem ipsum dolor sit amet"
}

resource "null_resource" "empty" {}
2 changes: 1 addition & 1 deletion test/helm_keda_remote_example_template_snapshot_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,5 +173,5 @@ func TestHelmKedaRemoteExampleTemplateRenderedPackageDiff(t *testing.T) {
output := helm.RenderRemoteTemplate(t, options, "https://kedacore.github.io/charts", releaseName, []string{})

// run the diff and assert the number of diffs matches the number of diffs in the snapshot
require.Equal(t, 18, helm.DiffAgainstSnapshot(t, options, output, releaseName))
require.Equal(t, 24, helm.DiffAgainstSnapshot(t, options, output, releaseName))
}

0 comments on commit e2ae16f

Please sign in to comment.