diff --git a/.golangci.yml b/.golangci.yml index decfd75ea..2e40af8e7 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -70,12 +70,16 @@ linters: - depguard - gosec - gocyclo + - exhaustruct fast: false mnd: ignored-functions: strconv.Format*,os.*,strconv.Parse*,strings.SplitN,bytes.SplitN presets: - bugs - performance + - unused + - test + issues: exclude-dirs: - docs diff --git a/aws_helper/config_test.go b/aws_helper/config_test.go index 86d4a4025..b25a004e2 100644 --- a/aws_helper/config_test.go +++ b/aws_helper/config_test.go @@ -1,10 +1,11 @@ -package aws_helper +package aws_helper_test import ( "testing" "github.com/aws/aws-sdk-go/aws/request" "github.com/aws/aws-sdk-go/service/sts" + "github.com/gruntwork-io/terragrunt/aws_helper" "github.com/gruntwork-io/terragrunt/options" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -13,7 +14,7 @@ import ( func TestTerragruntIsAddedInUserAgent(t *testing.T) { t.Parallel() - sess, err := CreateAwsSession(nil, options.NewTerragruntOptions()) + sess, err := aws_helper.CreateAwsSession(nil, options.NewTerragruntOptions()) require.NoError(t, err) op := &request.Operation{ @@ -33,7 +34,7 @@ func TestTerragruntIsAddedInUserAgent(t *testing.T) { func TestAwsSessionValidationFail(t *testing.T) { t.Parallel() - err := ValidateAwsSession(&AwsSessionConfig{ + err := aws_helper.ValidateAwsSession(&aws_helper.AwsSessionConfig{ Region: "not-existing-region", CredsFilename: "/tmp/not-existing-file", }, options.NewTerragruntOptions()) diff --git a/aws_helper/policy_test.go b/aws_helper/policy_test.go index 8e53fc7c0..3df869f50 100644 --- a/aws_helper/policy_test.go +++ b/aws_helper/policy_test.go @@ -1,8 +1,9 @@ -package aws_helper +package aws_helper_test import ( "testing" + "github.com/gruntwork-io/terragrunt/aws_helper" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -53,7 +54,7 @@ const arraysPolicy = ` func TestUnmarshalStringActionResource(t *testing.T) { t.Parallel() - bucketPolicy, err := UnmarshalPolicy(simplePolicy) + bucketPolicy, err := aws_helper.UnmarshalPolicy(simplePolicy) require.NoError(t, err) assert.NotNil(t, bucketPolicy) assert.Len(t, bucketPolicy.Statement, 1) @@ -74,14 +75,14 @@ func TestUnmarshalStringActionResource(t *testing.T) { assert.Fail(t, "Expected string type for Resource") } - out, err := MarshalPolicy(bucketPolicy) + out, err := aws_helper.MarshalPolicy(bucketPolicy) require.NoError(t, err) assert.NotContains(t, string(out), "null") } func TestUnmarshalActionResourceList(t *testing.T) { t.Parallel() - bucketPolicy, err := UnmarshalPolicy(arraysPolicy) + bucketPolicy, err := aws_helper.UnmarshalPolicy(arraysPolicy) require.NoError(t, err) assert.NotNil(t, bucketPolicy) assert.Len(t, bucketPolicy.Statement, 1) @@ -104,7 +105,7 @@ func TestUnmarshalActionResourceList(t *testing.T) { assert.Fail(t, "Expected []string type for Resource") } - out, err := MarshalPolicy(bucketPolicy) + out, err := aws_helper.MarshalPolicy(bucketPolicy) require.NoError(t, err) assert.NotContains(t, string(out), "null") } diff --git a/cli/app.go b/cli/app.go index f3b77ff75..db26750d1 100644 --- a/cli/app.go +++ b/cli/app.go @@ -79,11 +79,11 @@ func NewApp(writer io.Writer, errWriter io.Writer) *App { commands.NewGlobalFlags(opts), commands.NewHelpVersionFlags(opts)...) app.Commands = append( - deprecatedCommands(opts), - terragruntCommands(opts)...).WrapAction(wrapWithTelemetry(opts)) + DeprecatedCommands(opts), + TerragruntCommands(opts)...).WrapAction(WrapWithTelemetry(opts)) app.Before = beforeAction(opts) - app.DefaultCommand = terraformCmd.NewCommand(opts).WrapAction(wrapWithTelemetry(opts)) // by default, if no terragrunt command is specified, run the Terraform command - app.OsExiter = osExiter + app.DefaultCommand = terraformCmd.NewCommand(opts).WrapAction(WrapWithTelemetry(opts)) // by default, if no terragrunt command is specified, run the Terraform command + app.OsExiter = OSExiter return &App{app} } @@ -146,7 +146,7 @@ func (app *App) RunContext(ctx context.Context, args []string) error { } // This set of commands is also used in unit tests -func terragruntCommands(opts *options.TerragruntOptions) cli.Commands { +func TerragruntCommands(opts *options.TerragruntOptions) cli.Commands { cmds := cli.Commands{ runall.NewCommand(opts), // runAction-all terragruntinfo.NewCommand(opts), // terragrunt-info @@ -171,7 +171,7 @@ func terragruntCommands(opts *options.TerragruntOptions) cli.Commands { } // Wrap CLI command execution with setting of telemetry context and labels, if telemetry is disabled, just runAction the command. -func wrapWithTelemetry(opts *options.TerragruntOptions) func(ctx *cli.Context, action cli.ActionFunc) error { +func WrapWithTelemetry(opts *options.TerragruntOptions) func(ctx *cli.Context, action cli.ActionFunc) error { return func(ctx *cli.Context, action cli.ActionFunc) error { return telemetry.Telemetry(ctx.Context, opts, fmt.Sprintf("%s %s", ctx.Command.Name, opts.TerraformCommand), map[string]interface{}{ "terraformCommand": opts.TerraformCommand, @@ -391,7 +391,7 @@ func initialSetup(cliCtx *cli.Context, opts *options.TerragruntOptions) error { return nil } -func osExiter(exitCode int) { +func OSExiter(exitCode int) { // Do nothing. We just need to override this function, as the default value calls os.Exit, which // kills the app (or any automated test) dead in its tracks. } diff --git a/cli/app_test.go b/cli/app_test.go index 7f0fe2e69..296ced684 100644 --- a/cli/app_test.go +++ b/cli/app_test.go @@ -1,4 +1,4 @@ -package cli +package cli_test import ( "bytes" @@ -9,6 +9,7 @@ import ( "testing" "github.com/gruntwork-io/go-commons/errors" + "github.com/gruntwork-io/terragrunt/cli" "github.com/gruntwork-io/terragrunt/cli/commands" awsproviderpatch "github.com/gruntwork-io/terragrunt/cli/commands/aws-provider-patch" "github.com/gruntwork-io/terragrunt/cli/commands/hclfmt" @@ -17,7 +18,7 @@ import ( terraformcmd "github.com/gruntwork-io/terragrunt/cli/commands/terraform" "github.com/gruntwork-io/terragrunt/config" "github.com/gruntwork-io/terragrunt/options" - "github.com/gruntwork-io/terragrunt/pkg/cli" + cliPkg "github.com/gruntwork-io/terragrunt/pkg/cli" "github.com/gruntwork-io/terragrunt/terraform" "github.com/gruntwork-io/terragrunt/util" "github.com/sirupsen/logrus" @@ -285,8 +286,8 @@ func TestFilterTerragruntArgs(t *testing.T) { {[]string{"foo", doubleDashed(commands.TerragruntNonInteractiveFlagName)}, []string{"foo"}}, {[]string{"foo", doubleDashed(commands.TerragruntDebugFlagName)}, []string{"foo"}}, {[]string{"foo", doubleDashed(commands.TerragruntNonInteractiveFlagName), "-bar", doubleDashed(commands.TerragruntWorkingDirFlagName), "/some/path", "--baz", doubleDashed(commands.TerragruntConfigFlagName), "/some/path/" + config.DefaultTerragruntConfigPath}, []string{"foo", "-bar", "-baz"}}, - {[]string{CommandNameApplyAll, "foo", "bar"}, []string{terraform.CommandNameApply, "foo", "bar"}}, - {[]string{CommandNameDestroyAll, "foo", "-foo", "--bar"}, []string{terraform.CommandNameDestroy, "foo", "-foo", "-bar"}}, + {[]string{cli.CommandNameApplyAll, "foo", "bar"}, []string{terraform.CommandNameApply, "foo", "bar"}}, + {[]string{cli.CommandNameDestroyAll, "foo", "-foo", "--bar"}, []string{terraform.CommandNameDestroy, "foo", "-foo", "-bar"}}, } for _, testCase := range testCases { @@ -307,10 +308,10 @@ func TestParseMultiStringArg(t *testing.T) { expectedVals []string expectedErr error }{ - {[]string{CommandNameApplyAll, flagName, "bar"}, []string{"default_bar"}, []string{"bar"}, nil}, - {[]string{CommandNameApplyAll, "--test", "bar"}, []string{"default_bar"}, []string{"default_bar"}, nil}, - {[]string{CommandNamePlanAll, "--test", flagName, "bar1", flagName, "bar2"}, []string{"default_bar"}, []string{"bar1", "bar2"}, nil}, - {[]string{CommandNamePlanAll, "--test", "value", flagName, "bar1", flagName}, []string{"default_bar"}, nil, argMissingValueError(commands.TerragruntModulesThatIncludeFlagName)}, + {[]string{cli.CommandNameApplyAll, flagName, "bar"}, []string{"default_bar"}, []string{"bar"}, nil}, + {[]string{cli.CommandNameApplyAll, "--test", "bar"}, []string{"default_bar"}, []string{"default_bar"}, nil}, + {[]string{cli.CommandNamePlanAll, "--test", flagName, "bar1", flagName, "bar2"}, []string{"default_bar"}, []string{"bar1", "bar2"}, nil}, + {[]string{cli.CommandNamePlanAll, "--test", "value", flagName, "bar1", flagName}, []string{"default_bar"}, nil, argMissingValueError(commands.TerragruntModulesThatIncludeFlagName)}, } for _, testCase := range testCases { @@ -343,7 +344,7 @@ func TestParseMutliStringKeyValueArg(t *testing.T) { {[]string{awsproviderpatch.CommandName, "--other", "arg"}, map[string]string{"default": "value"}, map[string]string{"default": "value"}, nil}, {[]string{awsproviderpatch.CommandName, flagName, "key=value"}, map[string]string{"default": "value"}, map[string]string{"key": "value"}, nil}, {[]string{awsproviderpatch.CommandName, flagName, "key1=value1", flagName, "key2=value2", flagName, "key3=value3"}, map[string]string{"default": "value"}, map[string]string{"key1": "value1", "key2": "value2", "key3": "value3"}, nil}, - {[]string{awsproviderpatch.CommandName, flagName, "invalidvalue"}, map[string]string{"default": "value"}, nil, cli.NewInvalidKeyValueError(cli.MapFlagKeyValSep, "invalidvalue")}, + {[]string{awsproviderpatch.CommandName, flagName, "invalidvalue"}, map[string]string{"default": "value"}, nil, cliPkg.NewInvalidKeyValueError(cliPkg.MapFlagKeyValSep, "invalidvalue")}, } for _, testCase := range testCases { @@ -375,7 +376,7 @@ func TestTerragruntVersion(t *testing.T) { for _, testCase := range testCases { output := &bytes.Buffer{} - app := NewApp(output, os.Stderr) + app := cli.NewApp(output, os.Stderr) app.Version = version err := app.Run(testCase.args) @@ -388,7 +389,7 @@ func TestTerragruntVersion(t *testing.T) { func TestTerragruntHelp(t *testing.T) { t.Parallel() - app := NewApp(os.Stdout, os.Stderr) + app := cli.NewApp(os.Stdout, os.Stderr) testCases := []struct { args []string @@ -399,12 +400,12 @@ func TestTerragruntHelp(t *testing.T) { {[]string{"terragrunt", "-help"}, app.UsageText, awsproviderpatch.FlagNameTerragruntOverrideAttr}, {[]string{"terragrunt", "-h"}, app.UsageText, awsproviderpatch.FlagNameTerragruntOverrideAttr}, {[]string{"terragrunt", awsproviderpatch.CommandName, "-h"}, commands.TerragruntConfigFlagName, hclfmt.CommandName}, - {[]string{"terragrunt", CommandNamePlanAll, "--help"}, runall.CommandName, ""}, + {[]string{"terragrunt", cli.CommandNamePlanAll, "--help"}, runall.CommandName, ""}, } for _, testCase := range testCases { output := &bytes.Buffer{} - app := NewApp(output, os.Stderr) + app := cli.NewApp(output, os.Stderr) err := app.Run(testCase.args) require.NoError(t, err, testCase) @@ -431,7 +432,7 @@ func TestTerraformHelp(t *testing.T) { for _, testCase := range testCases { output := &bytes.Buffer{} - app := NewApp(output, os.Stderr) + app := cli.NewApp(output, os.Stderr) err := app.Run(testCase.args) require.NoError(t, err) @@ -445,7 +446,7 @@ func TestTerraformHelp(t *testing.T) { func TestTerraformHelp_wrongHelpFlag(t *testing.T) { t.Parallel() - app := NewApp(os.Stdout, os.Stderr) + app := cli.NewApp(os.Stdout, os.Stderr) output := &bytes.Buffer{} app.Writer = output @@ -455,9 +456,9 @@ func TestTerraformHelp_wrongHelpFlag(t *testing.T) { } func runAppTest(args []string, opts *options.TerragruntOptions) (*options.TerragruntOptions, error) { - emptyAction := func(ctx *cli.Context) error { return nil } + emptyAction := func(ctx *cliPkg.Context) error { return nil } - terragruntCommands := terragruntCommands(opts) + terragruntCommands := cli.TerragruntCommands(opts) for _, command := range terragruntCommands { command.Action = emptyAction for _, cmd := range command.Subcommands { @@ -468,17 +469,17 @@ func runAppTest(args []string, opts *options.TerragruntOptions) (*options.Terrag defaultCommand := terraformcmd.NewCommand(opts) defaultCommand.Action = emptyAction - app := cli.NewApp() + app := cliPkg.NewApp() app.Writer = &bytes.Buffer{} app.ErrWriter = &bytes.Buffer{} app.Flags = append( commands.NewGlobalFlags(opts), commands.NewHelpVersionFlags(opts)...) app.Commands = append( - deprecatedCommands(opts), - terragruntCommands...).WrapAction(wrapWithTelemetry(opts)) - app.DefaultCommand = defaultCommand.WrapAction(wrapWithTelemetry(opts)) - app.OsExiter = osExiter + cli.DeprecatedCommands(opts), + terragruntCommands...).WrapAction(cli.WrapWithTelemetry(opts)) + app.DefaultCommand = defaultCommand.WrapAction(cli.WrapWithTelemetry(opts)) + app.OsExiter = cli.OSExiter err := app.Run(append([]string{"--"}, args...)) return opts, err @@ -495,6 +496,8 @@ func (err argMissingValueError) Error() string { } func TestAutocomplete(t *testing.T) { + t.Parallel() + defer os.Unsetenv("COMP_LINE") testCases := []struct { @@ -523,7 +526,7 @@ func TestAutocomplete(t *testing.T) { os.Setenv("COMP_LINE", "terragrunt "+testCase.compLine) output := &bytes.Buffer{} - app := NewApp(output, os.Stderr) + app := cli.NewApp(output, os.Stderr) app.Commands = app.Commands.Filter([]string{"aws-provider-patch", "graph-dependencies", "hclfmt", "output-module-groups", "render-json", "run-all", "terragrunt-info", "validate-inputs"}) err := app.Run([]string{"terragrunt"}) diff --git a/cli/commands/aws-provider-patch/action.go b/cli/commands/aws-provider-patch/action.go index a55106601..86303cfcb 100644 --- a/cli/commands/aws-provider-patch/action.go +++ b/cli/commands/aws-provider-patch/action.go @@ -72,7 +72,7 @@ func runAwsProviderPatch(ctx context.Context, opts *options.TerragruntOptions, c return err } - updatedTerraformFileContents, codeWasUpdated, err := patchAwsProviderInTerraformCode(originalTerraformFileContents, terraformFile, opts.AwsProviderPatchOverrides) + updatedTerraformFileContents, codeWasUpdated, err := PatchAwsProviderInTerraformCode(originalTerraformFileContents, terraformFile, opts.AwsProviderPatchOverrides) if err != nil { return err } @@ -153,7 +153,7 @@ func findAllTerraformFilesInModules(opts *options.TerragruntOptions) ([]string, return terraformFiles, nil } -// patchAwsProviderInTerraformCode looks for provider "aws" { ... } blocks in the given Terraform code and overwrites +// PatchAwsProviderInTerraformCode looks for provider "aws" { ... } blocks in the given Terraform code and overwrites // the attributes in those provider blocks with the given attributes. It returns the new Terraform code and a boolean // true if that code was updated. // @@ -172,7 +172,7 @@ func findAllTerraformFilesInModules(opts *options.TerragruntOptions) ([]string, // This is a temporary workaround for a Terraform bug (https://github.com/hashicorp/terraform/issues/13018) where // any dynamic values in nested provider blocks are not handled correctly when you call 'terraform import', so by // temporarily hard-coding them, we can allow 'import' to work. -func patchAwsProviderInTerraformCode(terraformCode string, terraformFilePath string, attributesToOverride map[string]string) (string, bool, error) { +func PatchAwsProviderInTerraformCode(terraformCode string, terraformFilePath string, attributesToOverride map[string]string) (string, bool, error) { if len(attributesToOverride) == 0 { return terraformCode, false, nil } diff --git a/cli/commands/aws-provider-patch/action_test.go b/cli/commands/aws-provider-patch/action_test.go index ed5e7a643..3e5033273 100644 --- a/cli/commands/aws-provider-patch/action_test.go +++ b/cli/commands/aws-provider-patch/action_test.go @@ -1,8 +1,9 @@ -package awsproviderpatch +package awsproviderpatch_test import ( "testing" + awsproviderpatch "github.com/gruntwork-io/terragrunt/cli/commands/aws-provider-patch" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -318,7 +319,7 @@ func TestPatchAwsProviderInTerraformCodeHappyPath(t *testing.T) { testCase := testCase t.Run(testCase.testName, func(t *testing.T) { t.Parallel() - actualTerraformCode, actualCodeWasUpdated, err := patchAwsProviderInTerraformCode(testCase.originalTerraformCode, "test.tf", testCase.attributesToOverride) + actualTerraformCode, actualCodeWasUpdated, err := awsproviderpatch.PatchAwsProviderInTerraformCode(testCase.originalTerraformCode, "test.tf", testCase.attributesToOverride) require.NoError(t, err) assert.Equal(t, testCase.expectedCodeWasUpdated, actualCodeWasUpdated) diff --git a/cli/commands/catalog/module/doc.go b/cli/commands/catalog/module/doc.go index a17164e1a..de4837b88 100644 --- a/cli/commands/catalog/module/doc.go +++ b/cli/commands/catalog/module/doc.go @@ -55,7 +55,7 @@ type Doc struct { frontmatterReg *regexp.Regexp } -func newDoc(rawContent, fileExt string) *Doc { +func NewDoc(rawContent, fileExt string) *Doc { doc := &Doc{ rawContent: rawContent, fileExt: fileExt, @@ -169,7 +169,7 @@ func FindDoc(dir string) (*Doc, error) { } rawContent := string(contentByte) - return newDoc(rawContent, fileExt), nil + return NewDoc(rawContent, fileExt), nil } func (doc *Doc) Title() string { diff --git a/cli/commands/catalog/module/doc_test.go b/cli/commands/catalog/module/doc_test.go index d7cc08b15..7b24fd780 100644 --- a/cli/commands/catalog/module/doc_test.go +++ b/cli/commands/catalog/module/doc_test.go @@ -1,9 +1,10 @@ -package module +package module_test import ( "fmt" "testing" + "github.com/gruntwork-io/terragrunt/cli/commands/catalog/module" "github.com/stretchr/testify/assert" ) @@ -68,7 +69,7 @@ func TestFrontmatter(t *testing.T) { t.Run(fmt.Sprintf("testCase-%d", i), func(t *testing.T) { t.Parallel() - doc := newDoc(testCase.content, "") + doc := module.NewDoc(testCase.content, "") assert.Equal(t, testCase.expectedName, doc.Title(), "Frontmatter Name") assert.Equal(t, testCase.expectedDesc, doc.Description(0), "Frontmatter Description") @@ -223,7 +224,7 @@ func TestElement(t *testing.T) { t.Run(fmt.Sprintf("testCase-%d", i), func(t *testing.T) { t.Parallel() - doc := newDoc(testCase.content, testCase.fileExt) + doc := module.NewDoc(testCase.content, testCase.fileExt) assert.Equal(t, testCase.expectedTitle, doc.Title(), "Title") assert.Equal(t, testCase.expectedDescription, doc.Description(testCase.maxDescriptionLength), "Description") diff --git a/cli/commands/catalog/module/module.go b/cli/commands/catalog/module/module.go index cc204b3d2..d4b390778 100644 --- a/cli/commands/catalog/module/module.go +++ b/cli/commands/catalog/module/module.go @@ -44,7 +44,7 @@ func NewModule(repo *Repo, moduleDir string) (*Module, error) { log.Debugf("Found module in directory %q", moduleDir) - moduleURL, err := repo.moduleURL(moduleDir) + moduleURL, err := repo.ModuleURL(moduleDir) if err != nil { return nil, err } @@ -115,3 +115,7 @@ func (module *Module) isValid() (bool, error) { return false, nil } + +func (module *Module) ModuleDir() string { + return module.moduleDir +} diff --git a/cli/commands/catalog/module/repo.go b/cli/commands/catalog/module/repo.go index 809128e11..ba1bfb720 100644 --- a/cli/commands/catalog/module/repo.go +++ b/cli/commands/catalog/module/repo.go @@ -109,8 +109,8 @@ func (repo *Repo) FindModules(ctx context.Context) (Modules, error) { return modules, nil } -// moduleURL returns the URL of the module in this repository. `moduleDir` is the path from the repository root. -func (repo *Repo) moduleURL(moduleDir string) (string, error) { +// ModuleURL returns the URL of the module in this repository. `moduleDir` is the path from the repository root. +func (repo *Repo) ModuleURL(moduleDir string) (string, error) { if repo.remoteURL == "" { return filepath.Join(repo.path, moduleDir), nil } diff --git a/cli/commands/catalog/module/repo_test.go b/cli/commands/catalog/module/repo_test.go index 1e9609e9a..2388cdc0d 100644 --- a/cli/commands/catalog/module/repo_test.go +++ b/cli/commands/catalog/module/repo_test.go @@ -1,4 +1,4 @@ -package module +package module_test import ( "context" @@ -6,6 +6,7 @@ import ( "path/filepath" "testing" + "github.com/gruntwork-io/terragrunt/cli/commands/catalog/module" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -61,7 +62,7 @@ func TestFindModules(t *testing.T) { ctx := context.Background() - repo, err := NewRepo(ctx, testCase.repoPath, "") + repo, err := module.NewRepo(ctx, testCase.repoPath, "") require.NoError(t, err) modules, err := repo.FindModules(ctx) @@ -75,7 +76,7 @@ func TestFindModules(t *testing.T) { title: module.Title(), description: module.Description(), url: module.URL(), - moduleDir: module.moduleDir, + moduleDir: module.ModuleDir(), }) } diff --git a/cli/commands/graph-dependencies/action_test.go b/cli/commands/graph-dependencies/action_test.go index 963f0e870..f0a7e1c92 100644 --- a/cli/commands/graph-dependencies/action_test.go +++ b/cli/commands/graph-dependencies/action_test.go @@ -1,4 +1,4 @@ -package graphdependencies +package graphdependencies_test import ( "context" @@ -6,6 +6,7 @@ import ( "path/filepath" "testing" + graphdependencies "github.com/gruntwork-io/terragrunt/cli/commands/graph-dependencies" "github.com/gruntwork-io/terragrunt/options" "github.com/stretchr/testify/require" ) @@ -45,7 +46,7 @@ func BenchmarkRunGraphDependencies(b *testing.B) { b.ResetTimer() b.StartTimer() - err = Run(context.Background(), terragruntOptions) + err = graphdependencies.Run(context.Background(), terragruntOptions) b.StopTimer() require.NoError(b, err) }) diff --git a/cli/commands/hclfmt/action_test.go b/cli/commands/hclfmt/action_test.go index f44ee0309..a47d29468 100644 --- a/cli/commands/hclfmt/action_test.go +++ b/cli/commands/hclfmt/action_test.go @@ -1,4 +1,4 @@ -package hclfmt +package hclfmt_test import ( "os" @@ -9,6 +9,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/gruntwork-io/terragrunt/cli/commands/hclfmt" "github.com/gruntwork-io/terragrunt/options" "github.com/gruntwork-io/terragrunt/util" ) @@ -17,7 +18,11 @@ func TestHCLFmt(t *testing.T) { t.Parallel() tmpPath, err := files.CopyFolderToTemp("../../../test/fixture-hclfmt", t.Name(), func(path string) bool { return true }) - defer os.RemoveAll(tmpPath) + + t.Cleanup(func() { + os.RemoveAll(tmpPath) + }) + require.NoError(t, err) expected, err := util.ReadFileAsString("../../../test/fixture-hclfmt/expected.hcl") @@ -28,10 +33,12 @@ func TestHCLFmt(t *testing.T) { tgOptions.WorkingDir = tmpPath - err = Run(tgOptions) + err = hclfmt.Run(tgOptions) require.NoError(t, err) t.Run("group", func(t *testing.T) { + t.Parallel() + dirs := []string{ "terragrunt.hcl", "a/terragrunt.hcl", @@ -43,8 +50,6 @@ func TestHCLFmt(t *testing.T) { // Capture range variable into for block so it doesn't change while looping dir := dir - // Create a synchronous subtest to group the child tests so that they can run in parallel while honoring cleanup - // routines in the main test. t.Run(dir, func(t *testing.T) { t.Parallel() @@ -77,7 +82,9 @@ func TestHCLFmtErrors(t *testing.T) { t.Parallel() tmpPath, err := files.CopyFolderToTemp("../../../test/fixture-hclfmt-errors", t.Name(), func(path string) bool { return true }) - defer os.RemoveAll(tmpPath) + t.Cleanup(func() { + os.RemoveAll(tmpPath) + }) require.NoError(t, err) tgOptions, err := options.NewTerragruntOptionsForTest("") @@ -92,19 +99,15 @@ func TestHCLFmtErrors(t *testing.T) { // Capture range variable into for block so it doesn't change while looping dir := dir - // Create a synchronous subtest to group the child tests so that they can run in parallel while honoring cleanup - // routines in the main test. - t.Run("group", func(t *testing.T) { - t.Run(dir, func(t *testing.T) { - t.Parallel() + t.Run(dir, func(t *testing.T) { + t.Parallel() - tgHclDir := filepath.Join(tmpPath, dir) - newTgOptions := tgOptions.Clone(tgOptions.TerragruntConfigPath) - newTgOptions.WorkingDir = tgHclDir + tgHclDir := filepath.Join(tmpPath, dir) + newTgOptions := tgOptions.Clone(tgOptions.TerragruntConfigPath) + newTgOptions.WorkingDir = tgHclDir - err := Run(newTgOptions) - require.Error(t, err) - }) + err := hclfmt.Run(newTgOptions) + require.Error(t, err) }) } } @@ -113,7 +116,11 @@ func TestHCLFmtCheck(t *testing.T) { t.Parallel() tmpPath, err := files.CopyFolderToTemp("../../../test/fixture-hclfmt-check", t.Name(), func(path string) bool { return true }) - defer os.RemoveAll(tmpPath) + + t.Cleanup(func() { + os.RemoveAll(tmpPath) + }) + require.NoError(t, err) expected, err := os.ReadFile("../../../test/fixture-hclfmt-check/expected.hcl") @@ -125,7 +132,7 @@ func TestHCLFmtCheck(t *testing.T) { tgOptions.Check = true tgOptions.WorkingDir = tmpPath - err = Run(tgOptions) + err = hclfmt.Run(tgOptions) require.NoError(t, err) dirs := []string{ @@ -140,17 +147,13 @@ func TestHCLFmtCheck(t *testing.T) { // Capture range variable into for block so it doesn't change while looping dir := dir - // Create a synchronous subtest to group the child tests so that they can run in parallel while honoring cleanup - // routines in the main test. - t.Run("group", func(t *testing.T) { - t.Run(dir, func(t *testing.T) { - t.Parallel() + t.Run(dir, func(t *testing.T) { + t.Parallel() - tgHclPath := filepath.Join(tmpPath, dir) - actual, err := os.ReadFile(tgHclPath) - require.NoError(t, err) - assert.Equal(t, expected, actual) - }) + tgHclPath := filepath.Join(tmpPath, dir) + actual, err := os.ReadFile(tgHclPath) + require.NoError(t, err) + assert.Equal(t, expected, actual) }) } } @@ -159,7 +162,11 @@ func TestHCLFmtCheckErrors(t *testing.T) { t.Parallel() tmpPath, err := files.CopyFolderToTemp("../../../test/fixture-hclfmt-check-errors", t.Name(), func(path string) bool { return true }) - defer os.RemoveAll(tmpPath) + + t.Cleanup(func() { + os.RemoveAll(tmpPath) + }) + require.NoError(t, err) expected, err := os.ReadFile("../../../test/fixture-hclfmt-check-errors/expected.hcl") @@ -171,7 +178,7 @@ func TestHCLFmtCheckErrors(t *testing.T) { tgOptions.Check = true tgOptions.WorkingDir = tmpPath - err = Run(tgOptions) + err = hclfmt.Run(tgOptions) require.Error(t, err) dirs := []string{ @@ -186,17 +193,13 @@ func TestHCLFmtCheckErrors(t *testing.T) { // Capture range variable into for block so it doesn't change while looping dir := dir - // Create a synchronous subtest to group the child tests so that they can run in parallel while honoring cleanup - // routines in the main test. - t.Run("group", func(t *testing.T) { - t.Run(dir, func(t *testing.T) { - t.Parallel() + t.Run(dir, func(t *testing.T) { + t.Parallel() - tgHclPath := filepath.Join(tmpPath, dir) - actual, err := os.ReadFile(tgHclPath) - require.NoError(t, err) - assert.Equal(t, expected, actual) - }) + tgHclPath := filepath.Join(tmpPath, dir) + actual, err := os.ReadFile(tgHclPath) + require.NoError(t, err) + assert.Equal(t, expected, actual) }) } } @@ -205,7 +208,11 @@ func TestHCLFmtFile(t *testing.T) { t.Parallel() tmpPath, err := files.CopyFolderToTemp("../../../test/fixture-hclfmt", t.Name(), func(path string) bool { return true }) - defer os.RemoveAll(tmpPath) + + t.Cleanup(func() { + os.RemoveAll(tmpPath) + }) + require.NoError(t, err) expected, err := os.ReadFile("../../../test/fixture-hclfmt/expected.hcl") @@ -217,7 +224,7 @@ func TestHCLFmtFile(t *testing.T) { // format only the hcl file contained within the a subdirectory of the fixture tgOptions.HclFile = "a/terragrunt.hcl" tgOptions.WorkingDir = tmpPath - err = Run(tgOptions) + err = hclfmt.Run(tgOptions) require.NoError(t, err) // test that the formatting worked on the specified file @@ -244,16 +251,12 @@ func TestHCLFmtFile(t *testing.T) { // Capture range variable into for block so it doesn't change while looping dir := dir - // Create a synchronous subtest to group the child tests so that they can run in parallel while honoring cleanup - // routines in the main test. - t.Run("original", func(t *testing.T) { - t.Run(dir, func(t *testing.T) { - t.Parallel() - testingPath := filepath.Join(tmpPath, dir) - actual, err := os.ReadFile(testingPath) - require.NoError(t, err) - assert.Equal(t, original, actual) - }) + t.Run(dir, func(t *testing.T) { + t.Parallel() + testingPath := filepath.Join(tmpPath, dir) + actual, err := os.ReadFile(testingPath) + require.NoError(t, err) + assert.Equal(t, original, actual) }) } } @@ -273,7 +276,7 @@ func TestHCLFmtHeredoc(t *testing.T) { tgOptions.WorkingDir = tmpPath - err = Run(tgOptions) + err = hclfmt.Run(tgOptions) require.NoError(t, err) tgHclPath := filepath.Join(tmpPath, "terragrunt.hcl") diff --git a/cli/commands/run-all/action_test.go b/cli/commands/run-all/action_test.go index d1819a177..95b7141c8 100644 --- a/cli/commands/run-all/action_test.go +++ b/cli/commands/run-all/action_test.go @@ -1,4 +1,4 @@ -package runall +package runall_test import ( "context" @@ -6,6 +6,7 @@ import ( "fmt" "testing" + runall "github.com/gruntwork-io/terragrunt/cli/commands/run-all" "github.com/gruntwork-io/terragrunt/options" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -19,10 +20,10 @@ func TestMissingRunAllArguments(t *testing.T) { tgOptions.TerraformCommand = "" - err = Run(context.Background(), tgOptions) + err = runall.Run(context.Background(), tgOptions) require.Error(t, err) - var missingCommand MissingCommand + var missingCommand runall.MissingCommand ok := errors.As(err, &missingCommand) fmt.Println(err, errors.Unwrap(err)) assert.True(t, ok) diff --git a/cli/commands/scaffold/action.go b/cli/commands/scaffold/action.go index 1a53529f3..ebfd80ac7 100644 --- a/cli/commands/scaffold/action.go +++ b/cli/commands/scaffold/action.go @@ -39,14 +39,14 @@ const ( moduleUrlPattern = `(?:git|hg|s3|gcs)::([^:]+)://([^/]+)(/.*)` moduleUrlParts = 4 - defaultBoilerplateConfig = ` + DefaultBoilerplateConfig = ` variables: - name: EnableRootInclude description: Should include root module type: bool default: true ` - defaultTerragruntTemplate = ` + DefaultTerragruntTemplate = ` # This is a Terragrunt module generated by boilerplate. terraform { source = "{{ .sourceUrl }}" @@ -234,10 +234,10 @@ func prepareBoilerplateFiles(ctx context.Context, opts *options.TerragruntOption } boilerplateDir = defaultTempDir const ownerWriteGlobalReadPerms = 0644 - if err := os.WriteFile(util.JoinPath(boilerplateDir, "terragrunt.hcl"), []byte(defaultTerragruntTemplate), ownerWriteGlobalReadPerms); err != nil { + if err := os.WriteFile(util.JoinPath(boilerplateDir, "terragrunt.hcl"), []byte(DefaultTerragruntTemplate), ownerWriteGlobalReadPerms); err != nil { return "", errors.WithStackTrace(err) } - if err := os.WriteFile(util.JoinPath(boilerplateDir, "boilerplate.yml"), []byte(defaultBoilerplateConfig), ownerWriteGlobalReadPerms); err != nil { + if err := os.WriteFile(util.JoinPath(boilerplateDir, "boilerplate.yml"), []byte(DefaultBoilerplateConfig), ownerWriteGlobalReadPerms); err != nil { return "", errors.WithStackTrace(err) } } diff --git a/cli/commands/scaffold/action_test.go b/cli/commands/scaffold/action_test.go index d9efcadc8..04cd6119c 100644 --- a/cli/commands/scaffold/action_test.go +++ b/cli/commands/scaffold/action_test.go @@ -1,4 +1,4 @@ -package scaffold +package scaffold_test import ( "context" @@ -9,6 +9,7 @@ import ( boilerplateoptions "github.com/gruntwork-io/boilerplate/options" "github.com/gruntwork-io/boilerplate/templates" "github.com/gruntwork-io/boilerplate/variables" + "github.com/gruntwork-io/terragrunt/cli/commands/scaffold" "github.com/gruntwork-io/terragrunt/config" "github.com/gruntwork-io/terragrunt/options" "github.com/gruntwork-io/terragrunt/util" @@ -53,10 +54,10 @@ func TestDefaultTemplateVariables(t *testing.T) { err = os.Mkdir(outputDir, 0755) require.NoError(t, err) - err = os.WriteFile(util.JoinPath(templateDir, "terragrunt.hcl"), []byte(defaultTerragruntTemplate), 0644) + err = os.WriteFile(util.JoinPath(templateDir, "terragrunt.hcl"), []byte(scaffold.DefaultTerragruntTemplate), 0644) require.NoError(t, err) - err = os.WriteFile(util.JoinPath(templateDir, "boilerplate.yml"), []byte(defaultBoilerplateConfig), 0644) + err = os.WriteFile(util.JoinPath(templateDir, "boilerplate.yml"), []byte(scaffold.DefaultBoilerplateConfig), 0644) require.NoError(t, err) boilerplateOpts := &boilerplateoptions.BoilerplateOptions{ diff --git a/cli/commands/terraform/action.go b/cli/commands/terraform/action.go index ea0368102..ae89b1a84 100644 --- a/cli/commands/terraform/action.go +++ b/cli/commands/terraform/action.go @@ -212,7 +212,7 @@ func runTerraform(ctx context.Context, terragruntOptions *options.TerragruntOpti } } - if err := checkFolderContainsTerraformCode(updatedTerragruntOptions); err != nil { + if err := CheckFolderContainsTerraformCode(updatedTerragruntOptions); err != nil { return target.runErrorCallback(terragruntOptions, terragruntConfig, err) } @@ -261,14 +261,14 @@ func generateConfig(terragruntConfig *config.TerragruntConfig, updatedTerragrunt func runTerragruntWithConfig(ctx context.Context, originalTerragruntOptions *options.TerragruntOptions, terragruntOptions *options.TerragruntOptions, terragruntConfig *config.TerragruntConfig, target *Target) error { // Add extra_arguments to the command if terragruntConfig.Terraform != nil && terragruntConfig.Terraform.ExtraArgs != nil && len(terragruntConfig.Terraform.ExtraArgs) > 0 { - args := filterTerraformExtraArgs(terragruntOptions, terragruntConfig) + args := FilterTerraformExtraArgs(terragruntOptions, terragruntConfig) terragruntOptions.InsertTerraformCliArgs(args...) for k, v := range filterTerraformEnvVarsFromExtraArgs(terragruntOptions, terragruntConfig) { terragruntOptions.Env[k] = v } } - if err := setTerragruntInputsAsEnvVars(terragruntOptions, terragruntConfig); err != nil { + if err := SetTerragruntInputsAsEnvVars(terragruntOptions, terragruntConfig); err != nil { return err } @@ -304,7 +304,7 @@ func runTerragruntWithConfig(ctx context.Context, originalTerragruntOptions *opt } return runActionWithHooks(ctx, "terraform", terragruntOptions, terragruntConfig, func(ctx context.Context) error { - runTerraformError := runTerraformWithRetry(ctx, terragruntOptions) + runTerraformError := RunTerraformWithRetry(ctx, terragruntOptions) var lockFileError error if shouldCopyLockFile(terragruntOptions.TerraformCliArgs) { @@ -396,8 +396,8 @@ func runActionWithHooks(ctx context.Context, description string, terragruntOptio // The Terragrunt configuration can contain a set of inputs to pass to Terraform as environment variables. This method // sets these environment variables in the given terragruntOptions. -func setTerragruntInputsAsEnvVars(terragruntOptions *options.TerragruntOptions, terragruntConfig *config.TerragruntConfig) error { - asEnvVars, err := toTerraformEnvVars(terragruntConfig.Inputs) +func SetTerragruntInputsAsEnvVars(terragruntOptions *options.TerragruntOptions, terragruntConfig *config.TerragruntConfig) error { + asEnvVars, err := ToTerraformEnvVars(terragruntConfig.Inputs) if err != nil { return err } @@ -415,11 +415,11 @@ func setTerragruntInputsAsEnvVars(terragruntOptions *options.TerragruntOptions, return nil } -func runTerraformWithRetry(ctx context.Context, terragruntOptions *options.TerragruntOptions) error { +func RunTerraformWithRetry(ctx context.Context, terragruntOptions *options.TerragruntOptions) error { // Retry the command configurable time with sleep in between for i := 0; i < terragruntOptions.RetryMaxAttempts; i++ { if out, err := shell.RunTerraformCommandWithOutput(ctx, terragruntOptions, terragruntOptions.TerraformCliArgs...); err != nil { - if out == nil || !isRetryable(terragruntOptions, out) { + if out == nil || !IsRetryable(terragruntOptions, out) { terragruntOptions.Logger.WithError(err).Errorf("%s invocation failed in %s", terragruntOptions.TerraformImplementation, terragruntOptions.WorkingDir) return err } else { @@ -439,8 +439,8 @@ func runTerraformWithRetry(ctx context.Context, terragruntOptions *options.Terra return errors.WithStackTrace(MaxRetriesExceeded{terragruntOptions}) } -// isRetryable checks whether there was an error and if the output matches any of the configured RetryableErrors -func isRetryable(opts *options.TerragruntOptions, out *util.CmdOutput) bool { +// IsRetryable checks whether there was an error and if the output matches any of the configured RetryableErrors +func IsRetryable(opts *options.TerragruntOptions, out *util.CmdOutput) bool { if !opts.AutoRetry { return false } @@ -469,7 +469,7 @@ func prepareInitCommand(ctx context.Context, terragruntOptions *options.Terragru return nil } -func checkFolderContainsTerraformCode(terragruntOptions *options.TerragruntOptions) error { +func CheckFolderContainsTerraformCode(terragruntOptions *options.TerragruntOptions) error { files := []string{} hclFiles, err := zglob.Glob(terragruntOptions.WorkingDir + "/**/*.tf") if err != nil { @@ -595,7 +595,7 @@ func runTerraformInit(ctx context.Context, originalTerragruntOptions *options.Te return err } - moduleNeedInit := util.JoinPath(terragruntOptions.WorkingDir, moduleInitRequiredFile) + moduleNeedInit := util.JoinPath(terragruntOptions.WorkingDir, ModuleInitRequiredFile) if util.FileExists(moduleNeedInit) { return os.Remove(moduleNeedInit) } @@ -633,7 +633,7 @@ func modulesNeedInit(terragruntOptions *options.TerragruntOptions) (bool, error) return false, nil } - moduleNeedInit := util.JoinPath(terragruntOptions.WorkingDir, moduleInitRequiredFile) + moduleNeedInit := util.JoinPath(terragruntOptions.WorkingDir, ModuleInitRequiredFile) if util.FileExists(moduleNeedInit) { return true, nil } @@ -673,7 +673,7 @@ func checkProtectedModule(terragruntOptions *options.TerragruntOptions, terragru return nil } -func filterTerraformExtraArgs(terragruntOptions *options.TerragruntOptions, terragruntConfig *config.TerragruntConfig) []string { +func FilterTerraformExtraArgs(terragruntOptions *options.TerragruntOptions, terragruntConfig *config.TerragruntConfig) []string { out := []string{} cmd := util.FirstArg(terragruntOptions.TerraformCliArgs) @@ -736,7 +736,7 @@ func filterTerraformEnvVarsFromExtraArgs(terragruntOptions *options.TerragruntOp // Convert the given variables to a map of environment variables that will expose those variables to Terraform. The // keys will be of the format TF_VAR_xxx and the values will be converted to JSON, which Terraform knows how to read // natively. -func toTerraformEnvVars(vars map[string]interface{}) (map[string]string, error) { +func ToTerraformEnvVars(vars map[string]interface{}) (map[string]string, error) { out := map[string]string{} for varName, varValue := range vars { diff --git a/cli/commands/terraform/action_test.go b/cli/commands/terraform/action_test.go index aed18b7af..9af58e6ce 100644 --- a/cli/commands/terraform/action_test.go +++ b/cli/commands/terraform/action_test.go @@ -1,4 +1,4 @@ -package terraform +package terraform_test import ( "context" @@ -7,6 +7,7 @@ import ( "testing" "github.com/gruntwork-io/go-commons/errors" + "github.com/gruntwork-io/terragrunt/cli/commands/terraform" "github.com/gruntwork-io/terragrunt/config" "github.com/gruntwork-io/terragrunt/options" "github.com/gruntwork-io/terragrunt/util" @@ -67,13 +68,15 @@ func TestSetTerragruntInputsAsEnvVars(t *testing.T) { // get updated due to concurrency within the scope of t.Run(..) below testCase := testCase t.Run(testCase.description, func(t *testing.T) { + t.Parallel() + opts, err := options.NewTerragruntOptionsForTest("mock-path-for-test.hcl") require.NoError(t, err) opts.Env = testCase.envVarsInOpts cfg := &config.TerragruntConfig{Inputs: testCase.inputsInConfig} - require.NoError(t, setTerragruntInputsAsEnvVars(opts, cfg)) + require.NoError(t, terraform.SetTerragruntInputsAsEnvVars(opts, cfg)) assert.Equal(t, testCase.expected, opts.Env) }) @@ -117,7 +120,7 @@ func TestTerragruntTerraformCodeCheck(t *testing.T) { opts, err := options.NewTerragruntOptionsForTest("mock-path-for-test.hcl") require.NoError(t, err) opts.WorkingDir = testCase.workingDir - err = checkFolderContainsTerraformCode(opts) + err = terraform.CheckFolderContainsTerraformCode(opts) if (err != nil) && testCase.valid { t.Error("valid terraform returned error") } @@ -126,7 +129,11 @@ func TestTerragruntTerraformCodeCheck(t *testing.T) { t.Error("invalid terraform did not return error") } } - t.Run(testCase.description, testFunc) + t.Run(testCase.description, func(t *testing.T) { + t.Parallel() + + testFunc(t) + }) } } @@ -145,7 +152,7 @@ func TestErrorRetryableOnStdoutError(t *testing.T) { Stderr: "error is here", } - retryable := isRetryable(tgOptions, out) + retryable := terraform.IsRetryable(tgOptions, out) require.True(t, retryable, "The error should have retried") } @@ -164,7 +171,7 @@ func TestErrorMultipleRetryableOnStderrError(t *testing.T) { Stderr: "error is here", } - retryable := isRetryable(tgOptions, out) + retryable := terraform.IsRetryable(tgOptions, out) require.True(t, retryable, "The error should have retried") } @@ -183,7 +190,7 @@ func TestEmptyRetryablesOnStderrError(t *testing.T) { Stderr: "error is here", } - retryable := isRetryable(tgOptions, out) + retryable := terraform.IsRetryable(tgOptions, out) require.False(t, retryable, "The error should not have retried, the list of retryable errors was empty") } @@ -202,7 +209,7 @@ func TestErrorRetryableOnStderrError(t *testing.T) { Stderr: "error is here", } - retryable := isRetryable(tgOptions, out) + retryable := terraform.IsRetryable(tgOptions, out) require.True(t, retryable, "The error should have retried") } @@ -221,7 +228,7 @@ func TestErrorNotRetryableOnStdoutError(t *testing.T) { Stderr: "", } - retryable := isRetryable(tgOptions, out) + retryable := terraform.IsRetryable(tgOptions, out) require.False(t, retryable, "The error should not retry") } @@ -240,7 +247,7 @@ func TestErrorNotRetryableOnStderrError(t *testing.T) { Stderr: "error is here", } - retryable := isRetryable(tgOptions, out) + retryable := terraform.IsRetryable(tgOptions, out) require.False(t, retryable, "The error should not retry") } @@ -252,7 +259,7 @@ func TestTerragruntHandlesCatastrophicTerraformFailure(t *testing.T) { // Use a path that doesn't exist to induce error tgOptions.TerraformPath = "i-dont-exist" - err = runTerraformWithRetry(context.Background(), tgOptions) + err = terraform.RunTerraformWithRetry(context.Background(), tgOptions) require.Error(t, err) } @@ -311,7 +318,9 @@ func TestToTerraformEnvVars(t *testing.T) { // get updated due to concurrency within the scope of t.Run(..) below testCase := testCase t.Run(testCase.description, func(t *testing.T) { - actual, err := toTerraformEnvVars(testCase.vars) + t.Parallel() + + actual, err := terraform.ToTerraformEnvVars(testCase.vars) require.NoError(t, err) assert.Equal(t, testCase.expected, actual) }) @@ -319,6 +328,8 @@ func TestToTerraformEnvVars(t *testing.T) { } func TestFilterTerraformExtraArgs(t *testing.T) { + t.Parallel() + workingDir, err := os.Getwd() if err != nil { t.Fatal(err) @@ -426,7 +437,7 @@ func TestFilterTerraformExtraArgs(t *testing.T) { Terraform: &config.TerraformConfig{ExtraArgs: []config.TerraformExtraArguments{testCase.extraArgs}}, } - out := filterTerraformExtraArgs(testCase.options, &config) + out := terraform.FilterTerraformExtraArgs(testCase.options, &config) assert.Equal(t, testCase.expectedArgs, out) } diff --git a/cli/commands/terraform/command.go b/cli/commands/terraform/command.go index cdaf236c5..db7c6e1b4 100644 --- a/cli/commands/terraform/command.go +++ b/cli/commands/terraform/command.go @@ -24,11 +24,11 @@ func NewCommand(opts *options.TerragruntOptions) *cli.Command { Name: CommandName, HelpName: CommandHelpName, Usage: "Terragrunt forwards all other commands directly to Terraform", - Action: action(opts), + Action: Action(opts), } } -func action(opts *options.TerragruntOptions) cli.ActionFunc { +func Action(opts *options.TerragruntOptions) cli.ActionFunc { return func(ctx *cli.Context) error { if opts.TerraformCommand == terraform.CommandNameDestroy { opts.CheckDependentModules = true diff --git a/cli/commands/terraform/command_test.go b/cli/commands/terraform/command_test.go index 35b3bce9e..9e4ec3077 100644 --- a/cli/commands/terraform/command_test.go +++ b/cli/commands/terraform/command_test.go @@ -1,9 +1,10 @@ -package terraform +package terraform_test import ( "context" "testing" + "github.com/gruntwork-io/terragrunt/cli/commands/terraform" "github.com/gruntwork-io/terragrunt/options" "github.com/gruntwork-io/terragrunt/pkg/cli" "github.com/stretchr/testify/require" @@ -23,7 +24,7 @@ func TestAction(t *testing.T) { TerraformCommand: "foo", TerraformPath: "tofu", }, - expectedErr: WrongTofuCommand("foo"), + expectedErr: terraform.WrongTofuCommand("foo"), }, { name: "wrong terraform command", @@ -31,13 +32,17 @@ func TestAction(t *testing.T) { TerraformCommand: "foo", TerraformPath: "terraform", }, - expectedErr: WrongTerraformCommand("foo"), + expectedErr: terraform.WrongTerraformCommand("foo"), }, } for _, tc := range tt { + tc := tc + t.Run(tc.name, func(t *testing.T) { - fn := action(tc.opts) + t.Parallel() + + fn := terraform.Action(tc.opts) ctx := cli.Context{ Context: context.Background(), diff --git a/cli/commands/terraform/download_source.go b/cli/commands/terraform/download_source.go index e576674ef..dccd8717e 100644 --- a/cli/commands/terraform/download_source.go +++ b/cli/commands/terraform/download_source.go @@ -18,10 +18,10 @@ import ( ) // manifest for files copied from terragrunt module folder (i.e., the folder that contains the current terragrunt.hcl) -const MODULE_MANIFEST_NAME = ".terragrunt-module-manifest" +const ModuleManifestName = ".terragrunt-module-manifest" // file to indicate that init should be executed -const moduleInitRequiredFile = ".terragrunt-init-required" +const ModuleInitRequiredFile = ".terragrunt-init-required" const tfLintConfig = ".tflint.hcl" @@ -38,7 +38,7 @@ func downloadTerraformSource(ctx context.Context, source string, terragruntOptio return nil, err } - if err := downloadTerraformSourceIfNecessary(ctx, terraformSource, terragruntOptions, terragruntConfig); err != nil { + if err := DownloadTerraformSourceIfNecessary(ctx, terraformSource, terragruntOptions, terragruntConfig); err != nil { return nil, err } @@ -49,7 +49,7 @@ func downloadTerraformSource(ctx context.Context, source string, terragruntOptio } // Always include the .tflint.hcl file, if it exists includeInCopy = append(includeInCopy, tfLintConfig) - if err := util.CopyFolderContents(terragruntOptions.WorkingDir, terraformSource.WorkingDir, MODULE_MANIFEST_NAME, includeInCopy); err != nil { + if err := util.CopyFolderContents(terragruntOptions.WorkingDir, terraformSource.WorkingDir, ModuleManifestName, includeInCopy); err != nil { return nil, err } @@ -62,7 +62,7 @@ func downloadTerraformSource(ctx context.Context, source string, terragruntOptio } // Download the specified TerraformSource if the latest code hasn't already been downloaded. -func downloadTerraformSourceIfNecessary(ctx context.Context, terraformSource *terraform.Source, terragruntOptions *options.TerragruntOptions, terragruntConfig *config.TerragruntConfig) error { +func DownloadTerraformSourceIfNecessary(ctx context.Context, terraformSource *terraform.Source, terragruntOptions *options.TerragruntOptions, terragruntConfig *config.TerragruntConfig) error { if terragruntOptions.SourceUpdate { terragruntOptions.Logger.Debugf("The --%s flag is set, so deleting the temporary folder %s before downloading source.", commands.TerragruntSourceUpdateFlagName, terraformSource.DownloadDir) if err := os.RemoveAll(terraformSource.DownloadDir); err != nil { @@ -70,13 +70,13 @@ func downloadTerraformSourceIfNecessary(ctx context.Context, terraformSource *te } } - alreadyLatest, err := alreadyHaveLatestCode(terraformSource, terragruntOptions) + alreadyLatest, err := AlreadyHaveLatestCode(terraformSource, terragruntOptions) if err != nil { return err } if alreadyLatest { - if err := validateWorkingDir(terraformSource); err != nil { + if err := ValidateWorkingDir(terraformSource); err != nil { return err } terragruntOptions.Logger.Debugf("%s files in %s are up to date. Will not download again.", terragruntOptions.TerraformImplementation, terraformSource.WorkingDir) @@ -110,7 +110,7 @@ func downloadTerraformSourceIfNecessary(ctx context.Context, terraformSource *te return err } - if err := validateWorkingDir(terraformSource); err != nil { + if err := ValidateWorkingDir(terraformSource); err != nil { return err } @@ -118,7 +118,7 @@ func downloadTerraformSourceIfNecessary(ctx context.Context, terraformSource *te // if source versions are different or calculating version failed, create file to run init // https://github.com/gruntwork-io/terragrunt/issues/1921 if previousVersion != currentVersion || err != nil { - initFile := util.JoinPath(terraformSource.WorkingDir, moduleInitRequiredFile) + initFile := util.JoinPath(terraformSource.WorkingDir, ModuleInitRequiredFile) f, createErr := os.Create(initFile) if createErr != nil { return createErr @@ -132,7 +132,7 @@ func downloadTerraformSourceIfNecessary(ctx context.Context, terraformSource *te // Returns true if the specified TerraformSource, of the exact same version, has already been downloaded into the // DownloadFolder. This helps avoid downloading the same code multiple times. Note that if the TerraformSource points // to a local file path, a hash will be generated from the contents of the source dir. See the ProcessTerraformSource method for more info. -func alreadyHaveLatestCode(terraformSource *terraform.Source, terragruntOptions *options.TerragruntOptions) (bool, error) { +func AlreadyHaveLatestCode(terraformSource *terraform.Source, terragruntOptions *options.TerragruntOptions) (bool, error) { if !util.FileExists(terraformSource.DownloadDir) || !util.FileExists(terraformSource.WorkingDir) || !util.FileExists(terraformSource.VersionFile) { @@ -222,7 +222,7 @@ func downloadSource(terraformSource *terraform.Source, terragruntOptions *option } // Check if working terraformSource.WorkingDir exists and is directory -func validateWorkingDir(terraformSource *terraform.Source) error { +func ValidateWorkingDir(terraformSource *terraform.Source) error { workingLocalDir := strings.ReplaceAll(terraformSource.WorkingDir, terraformSource.DownloadDir+filepath.FromSlash("/"), "") if util.IsFile(terraformSource.WorkingDir) { return WorkingDirNotDir{Dir: workingLocalDir, Source: terraformSource.CanonicalSourceURL.String()} diff --git a/cli/commands/terraform/download_source_test.go b/cli/commands/terraform/download_source_test.go index 08fa57d05..e1b9faf9f 100644 --- a/cli/commands/terraform/download_source_test.go +++ b/cli/commands/terraform/download_source_test.go @@ -1,4 +1,4 @@ -package terraform +package terraform_test import ( "context" @@ -13,7 +13,8 @@ import ( "testing" "github.com/gruntwork-io/go-commons/env" - "github.com/gruntwork-io/terragrunt/terraform" + "github.com/gruntwork-io/terragrunt/cli/commands/terraform" + tgTerraform "github.com/gruntwork-io/terragrunt/terraform" "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" @@ -252,9 +253,9 @@ func TestDownloadTerraformSourceIfNecessaryInvalidTerraformSource(t *testing.T) require.NoError(t, err) - err = downloadTerraformSourceIfNecessary(context.Background(), terraformSource, terragruntOptions, terragruntConfig) + err = terraform.DownloadTerraformSourceIfNecessary(context.Background(), terraformSource, terragruntOptions, terragruntConfig) require.Error(t, err) - var downloadingTerraformSourceErr DownloadingTerraformSourceErr + var downloadingTerraformSourceErr terraform.DownloadingTerraformSourceErr ok := errors.As(err, &downloadingTerraformSourceErr) assert.True(t, ok) } @@ -272,9 +273,9 @@ func TestInvalidModulePath(t *testing.T) { require.NoError(t, err) terraformSource.WorkingDir += "/not-existing-path" - err = validateWorkingDir(terraformSource) + err = terraform.ValidateWorkingDir(terraformSource) require.Error(t, err) - var workingDirNotFound WorkingDirNotFound + var workingDirNotFound terraform.WorkingDirNotFound ok := errors.As(err, &workingDirNotFound) assert.True(t, ok) } @@ -292,9 +293,9 @@ func TestDownloadInvalidPathToFilePath(t *testing.T) { require.NoError(t, err) terraformSource.WorkingDir += "/main.tf" - err = validateWorkingDir(terraformSource) + err = terraform.ValidateWorkingDir(terraformSource) require.Error(t, err) - var workingDirNotDir WorkingDirNotDir + var workingDirNotDir terraform.WorkingDirNotDir ok := errors.As(err, &workingDirNotDir) assert.True(t, ok) } @@ -303,12 +304,16 @@ func TestDownloadTerraformSourceFromLocalFolderWithManifest(t *testing.T) { t.Parallel() downloadDir := tmpDir(t) - defer os.Remove(downloadDir) + t.Cleanup(func() { + os.RemoveAll(downloadDir) + }) // used to test if an empty folder gets copied testDir := tmpDir(t) require.NoError(t, os.Mkdir(path.Join(testDir, "sub2"), 0700)) - defer os.Remove(testDir) + t.Cleanup(func() { + os.Remove(testDir) + }) testCases := []struct { name string @@ -355,6 +360,8 @@ func TestDownloadTerraformSourceFromLocalFolderWithManifest(t *testing.T) { for _, testCase := range testCases { testCase := testCase t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + copyFolder(t, testCase.sourceURL, downloadDir) assert.Condition(t, testCase.comp) }) @@ -363,12 +370,12 @@ func TestDownloadTerraformSourceFromLocalFolderWithManifest(t *testing.T) { } -func testDownloadTerraformSourceIfNecessary(t *testing.T, canonicalUrl string, downloadDir string, sourceUpdate bool, expectedFileContents string, assertInitFile bool) { +func testDownloadTerraformSourceIfNecessary(t *testing.T, canonicalUrl string, downloadDir string, sourceUpdate bool, expectedFileContents string, requireInitFile bool) { terraformSource, terragruntOptions, terragruntConfig, err := createConfig(t, canonicalUrl, downloadDir, sourceUpdate) require.NoError(t, err) - err = downloadTerraformSourceIfNecessary(context.Background(), terraformSource, terragruntOptions, terragruntConfig) + err = terraform.DownloadTerraformSourceIfNecessary(context.Background(), terraformSource, terragruntOptions, terragruntConfig) require.NoError(t, err, "For terraform source %v: %v", terraformSource, err) expectedFilePath := util.JoinPath(downloadDir, "main.tf") @@ -377,16 +384,16 @@ func testDownloadTerraformSourceIfNecessary(t *testing.T, canonicalUrl string, d assert.Equal(t, expectedFileContents, actualFileContents, "For terraform source %v", terraformSource) } - if assertInitFile { - existsInitFile := util.FileExists(util.JoinPath(terraformSource.WorkingDir, moduleInitRequiredFile)) - assert.True(t, existsInitFile) + if requireInitFile { + existsInitFile := util.FileExists(util.JoinPath(terraformSource.WorkingDir, terraform.ModuleInitRequiredFile)) + require.True(t, existsInitFile) } } -func createConfig(t *testing.T, canonicalUrl string, downloadDir string, sourceUpdate bool) (*terraform.Source, *options.TerragruntOptions, *config.TerragruntConfig, error) { +func createConfig(t *testing.T, canonicalUrl string, downloadDir string, sourceUpdate bool) (*tgTerraform.Source, *options.TerragruntOptions, *config.TerragruntConfig, error) { logger := logrus.New() logger.Out = io.Discard - terraformSource := &terraform.Source{ + terraformSource := &tgTerraform.Source{ CanonicalSourceURL: parseUrl(t, canonicalUrl), DownloadDir: downloadDir, WorkingDir: downloadDir, @@ -407,7 +414,7 @@ func createConfig(t *testing.T, canonicalUrl string, downloadDir string, sourceU }, } - err = PopulateTerraformVersion(context.Background(), terragruntOptions) + err = terraform.PopulateTerraformVersion(context.Background(), terragruntOptions) require.NoError(t, err) return terraformSource, terragruntOptions, terragruntConfig, err } @@ -415,7 +422,7 @@ func createConfig(t *testing.T, canonicalUrl string, downloadDir string, sourceU func testAlreadyHaveLatestCode(t *testing.T, canonicalUrl string, downloadDir string, expected bool) { logger := logrus.New() logger.Out = io.Discard - terraformSource := &terraform.Source{ + terraformSource := &tgTerraform.Source{ CanonicalSourceURL: parseUrl(t, canonicalUrl), DownloadDir: downloadDir, WorkingDir: downloadDir, @@ -426,7 +433,7 @@ func testAlreadyHaveLatestCode(t *testing.T, canonicalUrl string, downloadDir st opts, err := options.NewTerragruntOptionsForTest("./should-not-be-used") require.NoError(t, err) - actual, err := alreadyHaveLatestCode(terraformSource, opts) + actual, err := terraform.AlreadyHaveLatestCode(terraformSource, opts) require.NoError(t, err) assert.Equal(t, expected, actual, "For terraform source %v", terraformSource) } diff --git a/cli/commands/terraform/version_check.go b/cli/commands/terraform/version_check.go index 738b7a449..10ede8cd6 100644 --- a/cli/commands/terraform/version_check.go +++ b/cli/commands/terraform/version_check.go @@ -93,7 +93,7 @@ func PopulateTerraformVersion(ctx context.Context, terragruntOptions *options.Te return err } - terraformVersion, err := parseTerraformVersion(output.Stdout) + terraformVersion, err := ParseTerraformVersion(output.Stdout) if err != nil { return err } @@ -118,17 +118,17 @@ func PopulateTerraformVersion(ctx context.Context, terragruntOptions *options.Te // Check that the currently installed Terraform version works meets the specified version constraint and return an error // if it doesn't func CheckTerraformVersion(constraint string, terragruntOptions *options.TerragruntOptions) error { - return checkTerraformVersionMeetsConstraint(terragruntOptions.TerraformVersion, constraint) + return CheckTerraformVersionMeetsConstraint(terragruntOptions.TerraformVersion, constraint) } // Check that the currently running Terragrunt version meets the specified version constraint and return an error // if it doesn't func CheckTerragruntVersion(constraint string, terragruntOptions *options.TerragruntOptions) error { - return checkTerragruntVersionMeetsConstraint(terragruntOptions.TerragruntVersion, constraint) + return CheckTerragruntVersionMeetsConstraint(terragruntOptions.TerragruntVersion, constraint) } // Check that the current version of Terragrunt meets the specified constraint and return an error if it doesn't -func checkTerragruntVersionMeetsConstraint(currentVersion *version.Version, constraint string) error { +func CheckTerragruntVersionMeetsConstraint(currentVersion *version.Version, constraint string) error { versionConstraint, err := version.NewConstraint(constraint) if err != nil { return err @@ -142,7 +142,7 @@ func checkTerragruntVersionMeetsConstraint(currentVersion *version.Version, cons } // Check that the current version of Terraform meets the specified constraint and return an error if it doesn't -func checkTerraformVersionMeetsConstraint(currentVersion *version.Version, constraint string) error { +func CheckTerraformVersionMeetsConstraint(currentVersion *version.Version, constraint string) error { versionConstraint, err := version.NewConstraint(constraint) if err != nil { return err @@ -156,7 +156,7 @@ func checkTerraformVersionMeetsConstraint(currentVersion *version.Version, const } // Parse the output of the terraform --version command -func parseTerraformVersion(versionCommandOutput string) (*version.Version, error) { +func ParseTerraformVersion(versionCommandOutput string) (*version.Version, error) { matches := TerraformVersionRegex.FindStringSubmatch(versionCommandOutput) if len(matches) != versionParts { diff --git a/cli/commands/terraform/version_check_test.go b/cli/commands/terraform/version_check_test.go index a08fad5d3..bf0e22424 100644 --- a/cli/commands/terraform/version_check_test.go +++ b/cli/commands/terraform/version_check_test.go @@ -1,10 +1,11 @@ //nolint:unparam -package terraform +package terraform_test import ( "testing" "github.com/gruntwork-io/go-commons/errors" + "github.com/gruntwork-io/terragrunt/cli/commands/terraform" "github.com/hashicorp/go-version" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -83,7 +84,7 @@ func TestParseTerraformVersionWithUnexpectedName(t *testing.T) { func TestParseTerraformVersionInvalidSyntax(t *testing.T) { t.Parallel() - testParseTerraformVersion(t, "invalid-syntax", "", InvalidTerraformVersionSyntax("invalid-syntax")) + testParseTerraformVersion(t, "invalid-syntax", "", terraform.InvalidTerraformVersionSyntax("invalid-syntax")) } func testCheckTerraformVersionMeetsConstraint(t *testing.T, currentVersion string, versionConstraint string, versionMeetsConstraint bool) { @@ -92,7 +93,7 @@ func testCheckTerraformVersionMeetsConstraint(t *testing.T, currentVersion strin t.Fatalf("Invalid current version specified in test: %v", err) } - err = checkTerraformVersionMeetsConstraint(current, versionConstraint) + err = terraform.CheckTerraformVersionMeetsConstraint(current, versionConstraint) if versionMeetsConstraint && err != nil { assert.NoError(t, err, "Expected Terraform version %s to meet constraint %s, but got error: %v", currentVersion, versionConstraint, err) } else if !versionMeetsConstraint && err == nil { @@ -101,7 +102,7 @@ func testCheckTerraformVersionMeetsConstraint(t *testing.T, currentVersion strin } func testParseTerraformVersion(t *testing.T, versionString string, expectedVersion string, expectedErr error) { - actualVersion, actualErr := parseTerraformVersion(versionString) + actualVersion, actualErr := terraform.ParseTerraformVersion(versionString) if expectedErr == nil { expected, err := version.NewVersion(expectedVersion) if err != nil { @@ -147,7 +148,7 @@ func testCheckTerragruntVersionMeetsConstraint(t *testing.T, currentVersion stri t.Fatalf("Invalid current version specified in test: %v", err) } - err = checkTerragruntVersionMeetsConstraint(current, versionConstraint) + err = terraform.CheckTerragruntVersionMeetsConstraint(current, versionConstraint) if versionMeetsConstraint && err != nil { t.Fatalf("Expected Terragrunt version %s to meet constraint %s, but got error: %v", currentVersion, versionConstraint, err) } else if !versionMeetsConstraint && err == nil { diff --git a/cli/commands/validate-inputs/action.go b/cli/commands/validate-inputs/action.go index a3bf96f4a..0ff9c87b6 100644 --- a/cli/commands/validate-inputs/action.go +++ b/cli/commands/validate-inputs/action.go @@ -201,7 +201,7 @@ func getTerraformInputNamesFromVarFiles(opts *options.TerragruntOptions, terragr // args that are passed in via the configured arguments attribute in the extra_arguments block of the given terragrunt // config and those that are directly passed in via the CLI. func getTerraformInputNamesFromCLIArgs(opts *options.TerragruntOptions, terragruntConfig *config.TerragruntConfig) ([]string, error) { - inputNames, varFiles, err := getVarFlagsFromArgList(opts.TerraformCliArgs) + inputNames, varFiles, err := GetVarFlagsFromArgList(opts.TerraformCliArgs) if err != nil { return inputNames, err } @@ -209,7 +209,7 @@ func getTerraformInputNamesFromCLIArgs(opts *options.TerragruntOptions, terragru if terragruntConfig.Terraform != nil { for _, arg := range terragruntConfig.Terraform.ExtraArgs { if arg.Arguments != nil { - vars, rawVarFiles, err := getVarFlagsFromArgList(*arg.Arguments) + vars, rawVarFiles, err := GetVarFlagsFromArgList(*arg.Arguments) if err != nil { return inputNames, err } @@ -298,7 +298,7 @@ func getVarNamesFromVarFile(varFile string) ([]string, error) { // Returns the CLI flags defined on the provided arguments list that correspond to -var and -var-file. Returns two // slices, one for `-var` args (the first one) and one for `-var-file` args (the second one). -func getVarFlagsFromArgList(argList []string) ([]string, []string, error) { +func GetVarFlagsFromArgList(argList []string) ([]string, []string, error) { vars := []string{} varFiles := []string{} diff --git a/cli/commands/validate-inputs/action_test.go b/cli/commands/validate-inputs/action_test.go index d2162b4ac..bc711553b 100644 --- a/cli/commands/validate-inputs/action_test.go +++ b/cli/commands/validate-inputs/action_test.go @@ -1,9 +1,10 @@ -package validateinputs +package validateinputs_test import ( "sort" "testing" + validateinputs "github.com/gruntwork-io/terragrunt/cli/commands/validate-inputs" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -57,7 +58,7 @@ func TestGetVarFlagsFromExtraArgs(t *testing.T) { t.Run(testCase.name, func(t *testing.T) { t.Parallel() - vars, varFiles, err := getVarFlagsFromArgList(testCase.args) + vars, varFiles, err := validateinputs.GetVarFlagsFromArgList(testCase.args) require.NoError(t, err) sort.Strings(vars) sort.Strings(varFiles) diff --git a/cli/deprecated_commands.go b/cli/deprecated_commands.go index f6f272069..66a698210 100644 --- a/cli/deprecated_commands.go +++ b/cli/deprecated_commands.go @@ -61,7 +61,7 @@ func replaceDeprecatedCommandFunc(terragruntCommandName, terraformCommandName st } } -func deprecatedCommands(opts *options.TerragruntOptions) cli.Commands { +func DeprecatedCommands(opts *options.TerragruntOptions) cli.Commands { var commands cli.Commands for commandName, runFunc := range replaceDeprecatedCommandsFuncs { diff --git a/cli/provider_cache.go b/cli/provider_cache.go index 73d125518..d17017ece 100644 --- a/cli/provider_cache.go +++ b/cli/provider_cache.go @@ -33,10 +33,10 @@ const ( // The status returned when making a request to the caching provider. // It is needed to prevent further loading of providers by terraform, and at the same time make sure that the request was processed successfully. - cacheProviderHTTPStatusCode = http.StatusLocked + CACHE_PROVIDER_HTTP_STATUS_CODE = http.StatusLocked // Authentication type on the Terragrunt Provider Cache server. - apiKeyAuth = "x-api-key" + API_KEY_AUTH = "x-api-key" ) var ( @@ -54,7 +54,7 @@ var ( // │ provider registry for registry.terraform.io/snowflake-labs/snowflake: 423 // │ Locked // ╵ - httpStatusCacheProviderReg = regexp.MustCompile(`(?smi)` + strconv.Itoa(cacheProviderHTTPStatusCode) + `.*` + http.StatusText(cacheProviderHTTPStatusCode)) + httpStatusCacheProviderReg = regexp.MustCompile(`(?smi)` + strconv.Itoa(CACHE_PROVIDER_HTTP_STATUS_CODE) + `.*` + http.StatusText(CACHE_PROVIDER_HTTP_STATUS_CODE)) ) type ProviderCache struct { @@ -83,8 +83,8 @@ func InitProviderCacheServer(opts *options.TerragruntOptions) (*ProviderCache, e opts.ProviderCacheToken = uuid.New().String() } // Currently, the cache server only supports the `x-api-key` token. - if !strings.HasPrefix(strings.ToLower(opts.ProviderCacheToken), apiKeyAuth+":") { - opts.ProviderCacheToken = fmt.Sprintf("%s:%s", apiKeyAuth, opts.ProviderCacheToken) + if !strings.HasPrefix(strings.ToLower(opts.ProviderCacheToken), API_KEY_AUTH+":") { + opts.ProviderCacheToken = fmt.Sprintf("%s:%s", API_KEY_AUTH, opts.ProviderCacheToken) } cliCfg, err := cliconfig.LoadUserConfig() @@ -111,15 +111,15 @@ func InitProviderCacheServer(opts *options.TerragruntOptions) (*ProviderCache, e for _, method := range cliCfg.ProviderInstallation.Methods { switch method := method.(type) { case *cliconfig.ProviderInstallationFilesystemMirror: - providerHandlers = append(providerHandlers, handlers.NewProviderFilesystemMirrorHandler(providerService, cacheProviderHTTPStatusCode, method)) + providerHandlers = append(providerHandlers, handlers.NewProviderFilesystemMirrorHandler(providerService, CACHE_PROVIDER_HTTP_STATUS_CODE, method)) case *cliconfig.ProviderInstallationNetworkMirror: - networkMirrorHandler, err := handlers.NewProviderNetworkMirrorHandler(providerService, cacheProviderHTTPStatusCode, method, cliCfg.CredentialsSource()) + networkMirrorHandler, err := handlers.NewProviderNetworkMirrorHandler(providerService, CACHE_PROVIDER_HTTP_STATUS_CODE, method, cliCfg.CredentialsSource()) if err != nil { return nil, err } providerHandlers = append(providerHandlers, networkMirrorHandler) case *cliconfig.ProviderInstallationDirect: - providerHandlers = append(providerHandlers, handlers.NewProviderDirectHandler(providerService, cacheProviderHTTPStatusCode, method, cliCfg.CredentialsSource())) + providerHandlers = append(providerHandlers, handlers.NewProviderDirectHandler(providerService, CACHE_PROVIDER_HTTP_STATUS_CODE, method, cliCfg.CredentialsSource())) directIsdefined = true } method.AppendExclude(excludeAddrs) @@ -127,7 +127,7 @@ func InitProviderCacheServer(opts *options.TerragruntOptions) (*ProviderCache, e if !directIsdefined { // In a case if none of direct provider installation methods `cliCfg.ProviderInstallation.Methods` are specified. - providerHandlers = append(providerHandlers, handlers.NewProviderDirectHandler(providerService, cacheProviderHTTPStatusCode, new(cliconfig.ProviderInstallationDirect), cliCfg.CredentialsSource())) + providerHandlers = append(providerHandlers, handlers.NewProviderDirectHandler(providerService, CACHE_PROVIDER_HTTP_STATUS_CODE, new(cliconfig.ProviderInstallationDirect), cliCfg.CredentialsSource())) } cache := cache.NewServer( diff --git a/cli/provider_cache_test.go b/cli/provider_cache_test.go index df1e86774..60a794683 100644 --- a/cli/provider_cache_test.go +++ b/cli/provider_cache_test.go @@ -1,4 +1,4 @@ -package cli +package cli_test import ( "context" @@ -13,6 +13,7 @@ import ( "testing" "github.com/google/uuid" + "github.com/gruntwork-io/terragrunt/cli" "github.com/gruntwork-io/terragrunt/terraform/cache" "github.com/gruntwork-io/terragrunt/terraform/cache/handlers" "github.com/gruntwork-io/terragrunt/terraform/cache/services" @@ -39,7 +40,7 @@ func createFakeProvider(t *testing.T, cacheDir, relativePath string) string { func TestProviderCache(t *testing.T) { t.Parallel() - token := fmt.Sprintf("%s:%s", apiKeyAuth, uuid.New().String()) + token := fmt.Sprintf("%s:%s", cli.API_KEY_AUTH, uuid.New().String()) providerCacheDir := t.TempDir() pluginCacheDir := t.TempDir() @@ -111,7 +112,7 @@ func TestProviderCache(t *testing.T) { errGroup, ctx := errgroup.WithContext(ctx) providerService := services.NewProviderService(providerCacheDir, pluginCacheDir, nil) - providerHandler := handlers.NewProviderDirectHandler(providerService, cacheProviderHTTPStatusCode, new(cliconfig.ProviderInstallationDirect), nil) + providerHandler := handlers.NewProviderDirectHandler(providerService, cli.CACHE_PROVIDER_HTTP_STATUS_CODE, new(cliconfig.ProviderInstallationDirect), nil) testCase.opts = append(testCase.opts, cache.WithServices(providerService), cache.WithProviderHandlers(providerHandler)) diff --git a/codegen/generate_test.go b/codegen/generate_test.go index 2ca2f0c02..95357d95e 100644 --- a/codegen/generate_test.go +++ b/codegen/generate_test.go @@ -1,10 +1,11 @@ -package codegen +package codegen_test import ( "bytes" "fmt" "testing" + "github.com/gruntwork-io/terragrunt/codegen" "github.com/gruntwork-io/terragrunt/options" "github.com/gruntwork-io/terragrunt/util" "github.com/stretchr/testify/assert" @@ -12,6 +13,8 @@ import ( ) func TestRemoteStateConfigToTerraformCode(t *testing.T) { + t.Parallel() + expectedOrdered := []byte(`terraform { backend "ordered" { a = 1 @@ -26,7 +29,7 @@ func TestRemoteStateConfigToTerraformCode(t *testing.T) { } `) - testCases := []struct { + tc := []struct { name string backend string config map[string]interface{} @@ -50,18 +53,22 @@ func TestRemoteStateConfigToTerraformCode(t *testing.T) { }, } - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - output, err := RemoteStateConfigToTerraformCode(testCase.backend, testCase.config) + for _, tt := range tc { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + output, err := codegen.RemoteStateConfigToTerraformCode(tt.backend, tt.config) // validates the first output. - assert.True(t, bytes.Contains(output, []byte(testCase.backend))) - assert.Equal(t, testCase.expected, output) + assert.True(t, bytes.Contains(output, []byte(tt.backend))) + assert.Equal(t, tt.expected, output) require.NoError(t, err) // runs the function a few of times again. All the outputs must be // equal to the first output. for i := 0; i < 20; i++ { - actual, _ := RemoteStateConfigToTerraformCode(testCase.backend, testCase.config) + actual, _ := codegen.RemoteStateConfigToTerraformCode(tt.backend, tt.config) assert.Equal(t, output, actual) } }) @@ -69,53 +76,59 @@ func TestRemoteStateConfigToTerraformCode(t *testing.T) { } func TestGenerateDisabling(t *testing.T) { + t.Parallel() + testDir := t.TempDir() - testCases := []struct { + tc := []struct { name string disabled bool path string contents string - ifExists GenerateConfigExists + ifExists codegen.GenerateConfigExists }{ { "generate-disabled-true", true, fmt.Sprintf("%s/%s", testDir, "disabled_true"), "this file should not be generated", - ExistsError, + codegen.ExistsError, }, { "generate-disabled-false", false, fmt.Sprintf("%s/%s", testDir, "disabled_false"), "this file should be generated", - ExistsError, + codegen.ExistsError, }, } - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - config := GenerateConfig{ - Path: testCase.path, - IfExists: testCase.ifExists, + for _, tt := range tc { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + config := codegen.GenerateConfig{ + Path: tt.path, + IfExists: tt.ifExists, CommentPrefix: "", DisableSignature: false, - Contents: testCase.contents, - Disable: testCase.disabled, + Contents: tt.contents, + Disable: tt.disabled, } opts, err := options.NewTerragruntOptionsForTest("mock-path-for-test.hcl") require.NoError(t, err) assert.NotNil(t, opts) - err = WriteToFile(opts, "", config) + err = codegen.WriteToFile(opts, "", config) require.NoError(t, err) - if testCase.disabled { - assert.True(t, util.FileNotExists(testCase.path)) + if tt.disabled { + assert.True(t, util.FileNotExists(tt.path)) } else { - assert.True(t, util.FileExists(testCase.path)) + assert.True(t, util.FileExists(tt.path)) } }) } diff --git a/config/cache_test.go b/config/cache_test.go index 86cbf1bb7..aa5fa6ce5 100644 --- a/config/cache_test.go +++ b/config/cache_test.go @@ -1,9 +1,10 @@ -package config +package config_test import ( "context" "testing" + "github.com/gruntwork-io/terragrunt/config" "github.com/gruntwork-io/terragrunt/internal/cache" "github.com/stretchr/testify/assert" ) @@ -13,7 +14,7 @@ const testCacheName = "TerragruntConfig" func TestTerragruntConfigCacheCreation(t *testing.T) { t.Parallel() - cache := cache.NewCache[TerragruntConfig](testCacheName) + cache := cache.NewCache[config.TerragruntConfig](testCacheName) assert.NotNil(t, cache.Mutex) assert.NotNil(t, cache.Cache) @@ -27,14 +28,14 @@ func TestTerragruntConfigCacheOperation(t *testing.T) { testCacheKey := "super-safe-cache-key" ctx := context.Background() - cache := cache.NewCache[TerragruntConfig](testCacheName) + cache := cache.NewCache[config.TerragruntConfig](testCacheName) actualResult, found := cache.Get(ctx, testCacheKey) assert.False(t, found) assert.Empty(t, actualResult) - stubTerragruntConfig := TerragruntConfig{ + stubTerragruntConfig := config.TerragruntConfig{ IsPartial: true, // Any random property will be sufficient } diff --git a/config/catalog.go b/config/catalog.go index de897aa58..dea566ad2 100644 --- a/config/catalog.go +++ b/config/catalog.go @@ -102,7 +102,7 @@ func findCatalogConfig(ctx context.Context, opts *options.TerragruntOptions) (st // continue } - newConfigPath, err := findInParentFolders(NewParsingContext(ctx, opts), []string{configName}) + newConfigPath, err := FindInParentFolders(NewParsingContext(ctx, opts), []string{configName}) if err != nil { var parentFileNotFoundError ParentFileNotFoundError if ok := errors.As(err, &parentFileNotFoundError); ok { @@ -162,7 +162,7 @@ func convertToTerragruntCatalogConfig(ctx *ParsingContext, configPath string, te // we should ignore any errors from `parseCtyValueToMap` as some `locals` values might have been incorrectly evaluated, that results to `json.Unmarshal` error. // for example if the locals block looks like `{"var1":, "var2":"value2"}`, `parseCtyValueToMap` returns the map with "var2" value and an syntax error, // but since we consciously understand that not all variables can be evaluated correctly due to the fact that parsing may not start from the real root file, we can safely ignore this error. - localsParsed, _ := parseCtyValueToMap(*ctx.Locals) + localsParsed, _ := ParseCtyValueToMap(*ctx.Locals) terragruntConfig.Locals = localsParsed terragruntConfig.SetFieldMetadataMap(MetadataLocals, localsParsed, defaultMetadata) } diff --git a/config/catalog_test.go b/config/catalog_test.go index 175d81523..0a4fee2a8 100644 --- a/config/catalog_test.go +++ b/config/catalog_test.go @@ -1,4 +1,4 @@ -package config +package config_test import ( "context" @@ -7,6 +7,7 @@ import ( "path/filepath" "testing" + "github.com/gruntwork-io/terragrunt/config" "github.com/gruntwork-io/terragrunt/options" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -22,12 +23,12 @@ func TestCatalogParseConfigFile(t *testing.T) { testCases := []struct { configPath string - expectedConfig *CatalogConfig + expectedConfig *config.CatalogConfig expectedErr error }{ { filepath.Join(basePath, "config1.hcl"), - &CatalogConfig{ + &config.CatalogConfig{ URLs: []string{ filepath.Join(basePath, "terraform-aws-eks"), // this path exists in the fixture directory and must be converted to the absolute path. "/repo-copier", @@ -45,12 +46,12 @@ func TestCatalogParseConfigFile(t *testing.T) { }, { filepath.Join(basePath, "config3.hcl"), - &CatalogConfig{}, + &config.CatalogConfig{}, nil, }, { filepath.Join(basePath, "complex/terragrunt.hcl"), - &CatalogConfig{ + &config.CatalogConfig{ URLs: []string{ filepath.Join(basePath, "complex/dev/us-west-1/modules/terraform-aws-eks"), "./terraform-aws-service-catalog", @@ -61,7 +62,7 @@ func TestCatalogParseConfigFile(t *testing.T) { }, { filepath.Join(basePath, "complex/dev/terragrunt.hcl"), - &CatalogConfig{ + &config.CatalogConfig{ URLs: []string{ filepath.Join(basePath, "complex/dev/us-west-1/modules/terraform-aws-eks"), "./terraform-aws-service-catalog", @@ -72,7 +73,7 @@ func TestCatalogParseConfigFile(t *testing.T) { }, { filepath.Join(basePath, "complex/dev/us-west-1/terragrunt.hcl"), - &CatalogConfig{ + &config.CatalogConfig{ URLs: []string{ filepath.Join(basePath, "complex/dev/us-west-1/modules/terraform-aws-eks"), "./terraform-aws-service-catalog", @@ -83,7 +84,7 @@ func TestCatalogParseConfigFile(t *testing.T) { }, { filepath.Join(basePath, "complex/dev/us-west-1/modules/terragrunt.hcl"), - &CatalogConfig{ + &config.CatalogConfig{ URLs: []string{ filepath.Join(basePath, "complex/dev/us-west-1/modules/terraform-aws-eks"), "./terraform-aws-service-catalog", @@ -94,7 +95,7 @@ func TestCatalogParseConfigFile(t *testing.T) { }, { filepath.Join(basePath, "complex/prod/terragrunt.hcl"), - &CatalogConfig{ + &config.CatalogConfig{ URLs: []string{ filepath.Join(basePath, "complex/dev/us-west-1/modules/terraform-aws-eks"), "./terraform-aws-service-catalog", @@ -114,7 +115,7 @@ func TestCatalogParseConfigFile(t *testing.T) { opts, err := options.NewTerragruntOptionsWithConfigPath(testCase.configPath) require.NoError(t, err) - config, err := ReadCatalogConfig(context.Background(), opts) + config, err := config.ReadCatalogConfig(context.Background(), opts) if testCase.expectedErr == nil { require.NoError(t, err) diff --git a/config/config.go b/config/config.go index e7d248d93..96a1ab95e 100644 --- a/config/config.go +++ b/config/config.go @@ -239,7 +239,7 @@ func (remoteState *remoteStateConfigFile) String() string { // Convert the parsed config file remote state struct to the internal representation struct of remote state // configurations. func (remoteState *remoteStateConfigFile) toConfig() (*remote.RemoteState, error) { - remoteStateConfig, err := parseCtyValueToMap(remoteState.Config) + remoteStateConfig, err := ParseCtyValueToMap(remoteState.Config) if err != nil { return nil, err } @@ -906,7 +906,7 @@ func decodeAsTerragruntConfigFile(ctx *ParsingContext, file *hclparse.File, eval } if terragruntConfig.Inputs != nil { - inputs, err := updateUnknownCtyValValues(*terragruntConfig.Inputs) + inputs, err := UpdateUnknownCtyValValues(*terragruntConfig.Inputs) if err != nil { return nil, err } @@ -983,7 +983,7 @@ func convertToTerragruntConfig(ctx *ParsingContext, configPath string, terragrun } if terragruntConfigFromFile.RemoteStateAttr != nil { - remoteStateMap, err := parseCtyValueToMap(*terragruntConfigFromFile.RemoteStateAttr) + remoteStateMap, err := ParseCtyValueToMap(*terragruntConfigFromFile.RemoteStateAttr) if err != nil { return nil, err } @@ -1095,7 +1095,7 @@ func convertToTerragruntConfig(ctx *ParsingContext, configPath string, terragrun generateBlocks = append(generateBlocks, terragruntConfigFromFile.GenerateBlocks...) if terragruntConfigFromFile.GenerateAttrs != nil { - generateMap, err := parseCtyValueToMap(*terragruntConfigFromFile.GenerateAttrs) + generateMap, err := ParseCtyValueToMap(*terragruntConfigFromFile.GenerateAttrs) if err != nil { return nil, err } @@ -1155,7 +1155,7 @@ func convertToTerragruntConfig(ctx *ParsingContext, configPath string, terragrun } if terragruntConfigFromFile.Inputs != nil { - inputs, err := parseCtyValueToMap(*terragruntConfigFromFile.Inputs) + inputs, err := ParseCtyValueToMap(*terragruntConfigFromFile.Inputs) if err != nil { return nil, err } @@ -1165,7 +1165,7 @@ func convertToTerragruntConfig(ctx *ParsingContext, configPath string, terragrun } if ctx.Locals != nil && *ctx.Locals != cty.NilVal { - localsParsed, err := parseCtyValueToMap(*ctx.Locals) + localsParsed, err := ParseCtyValueToMap(*ctx.Locals) if err != nil { return nil, err } @@ -1305,7 +1305,7 @@ func (conf *TerragruntConfig) EngineOptions() (*options.EngineOptions, error) { // in case of Meta is null, set empty meta var meta = map[string]interface{}{} if conf.Engine.Meta != nil { - parsedMeta, err := parseCtyValueToMap(*conf.Engine.Meta) + parsedMeta, err := ParseCtyValueToMap(*conf.Engine.Meta) if err != nil { return nil, err } diff --git a/config/config_as_cty.go b/config/config_as_cty.go index eb2cc60d0..62c2b1e33 100644 --- a/config/config_as_cty.go +++ b/config/config_as_cty.go @@ -53,7 +53,7 @@ func TerragruntConfigAsCty(config *TerragruntConfig) (cty.Value, error) { output[MetadataTerraform] = terraformConfigCty } - remoteStateCty, err := remoteStateAsCty(config.RemoteState) + remoteStateCty, err := RemoteStateAsCty(config.RemoteState) if err != nil { return cty.NilVal, err } @@ -220,7 +220,7 @@ func TerragruntConfigAsCtyWithMetadata(config *TerragruntConfig) (cty.Value, err } // Remote state - remoteStateCty, err := remoteStateAsCty(config.RemoteState) + remoteStateCty, err := RemoteStateAsCty(config.RemoteState) if err != nil { return cty.NilVal, err } @@ -440,9 +440,9 @@ func engineConfigAsCty(config *EngineConfig) (cty.Value, error) { return goTypeToCty(configCty) } -// ctyTerraformConfig is an alternate representation of TerraformConfig that converts internal blocks into a map that +// CtyTerraformConfig is an alternate representation of TerraformConfig that converts internal blocks into a map that // maps the name to the underlying struct, as opposed to a list representation. -type ctyTerraformConfig struct { +type CtyTerraformConfig struct { ExtraArgs map[string]TerraformExtraArguments `cty:"extra_arguments"` Source *string `cty:"source"` IncludeInCopy *[]string `cty:"include_in_copy"` @@ -457,7 +457,7 @@ func terraformConfigAsCty(config *TerraformConfig) (cty.Value, error) { return cty.NilVal, nil } - configCty := ctyTerraformConfig{ + configCty := CtyTerraformConfig{ Source: config.Source, IncludeInCopy: config.IncludeInCopy, ExtraArgs: map[string]TerraformExtraArguments{}, @@ -484,7 +484,7 @@ func terraformConfigAsCty(config *TerraformConfig) (cty.Value, error) { // Serialize RemoteState to a cty Value. We can't directly serialize the struct because `config` is an arbitrary // interface whose type we do not know, so we have to do a hack to go through json. -func remoteStateAsCty(remoteState *remote.RemoteState) (cty.Value, error) { +func RemoteStateAsCty(remoteState *remote.RemoteState) (cty.Value, error) { if remoteState == nil { return cty.NilVal, nil } diff --git a/config/config_as_cty_test.go b/config/config_as_cty_test.go index dd70cc149..4c79ad91d 100644 --- a/config/config_as_cty_test.go +++ b/config/config_as_cty_test.go @@ -1,4 +1,4 @@ -package config +package config_test import ( "sort" @@ -10,52 +10,55 @@ import ( "github.com/zclconf/go-cty/cty" "github.com/gruntwork-io/terragrunt/codegen" + "github.com/gruntwork-io/terragrunt/config" "github.com/gruntwork-io/terragrunt/remote" ) // This test makes sure that all the fields from the TerragruntConfig struct are accounted for in the conversion to // cty.Value. func TestTerragruntConfigAsCtyDrift(t *testing.T) { + t.Parallel() + testSource := "./foo" testTrue := true testFalse := false mockOutputs := cty.Zero mockOutputsAllowedTerraformCommands := []string{"init"} dependentModulesPath := []*string{&testSource} - testConfig := TerragruntConfig{ - Engine: &EngineConfig{ + testConfig := config.TerragruntConfig{ + Engine: &config.EngineConfig{ Source: "github.com/acme/terragrunt-plugin-custom-opentofu", Meta: &cty.Value{}, }, - Catalog: &CatalogConfig{ + Catalog: &config.CatalogConfig{ URLs: []string{ "repo/path", }, }, - Terraform: &TerraformConfig{ + Terraform: &config.TerraformConfig{ Source: &testSource, - ExtraArgs: []TerraformExtraArguments{ - TerraformExtraArguments{ + ExtraArgs: []config.TerraformExtraArguments{ + { Name: "init", Commands: []string{"init"}, }, }, - BeforeHooks: []Hook{ - Hook{ + BeforeHooks: []config.Hook{ + { Name: "init", Commands: []string{"init"}, Execute: []string{"true"}, }, }, - AfterHooks: []Hook{ - Hook{ + AfterHooks: []config.Hook{ + { Name: "init", Commands: []string{"init"}, Execute: []string{"true"}, }, }, - ErrorHooks: []ErrorHook{ - ErrorHook{ + ErrorHooks: []config.ErrorHook{ + { Name: "init", Commands: []string{"init"}, Execute: []string{"true"}, @@ -74,7 +77,7 @@ func TestTerragruntConfigAsCtyDrift(t *testing.T) { "bar": "baz", }, }, - Dependencies: &ModuleDependencies{ + Dependencies: &config.ModuleDependencies{ Paths: []string{"foo"}, }, DownloadDir: ".terragrunt-cache", @@ -88,8 +91,8 @@ func TestTerragruntConfigAsCtyDrift(t *testing.T) { "quote": "the answer is 42", }, DependentModulesPath: dependentModulesPath, - TerragruntDependencies: Dependencies{ - { + TerragruntDependencies: config.Dependencies{ + config.Dependency{ Name: "foo", ConfigPath: cty.StringVal("foo"), SkipOutputs: &testTrue, @@ -100,7 +103,7 @@ func TestTerragruntConfigAsCtyDrift(t *testing.T) { }, }, GenerateConfigs: map[string]codegen.GenerateConfig{ - "provider": codegen.GenerateConfig{ + "provider": { Path: "foo", IfExists: codegen.ExistsOverwriteTerragrunt, IfExistsStr: "overwrite_terragrunt", @@ -111,10 +114,10 @@ func TestTerragruntConfigAsCtyDrift(t *testing.T) { }, }, } - ctyVal, err := TerragruntConfigAsCty(&testConfig) + ctyVal, err := config.TerragruntConfigAsCty(&testConfig) require.NoError(t, err) - ctyMap, err := parseCtyValueToMap(ctyVal) + ctyMap, err := config.ParseCtyValueToMap(ctyVal) require.NoError(t, err) // Test the root properties @@ -137,6 +140,8 @@ func TestTerragruntConfigAsCtyDrift(t *testing.T) { // This test makes sure that all the fields in RemoteState are converted to cty func TestRemoteStateAsCtyDrift(t *testing.T) { + t.Parallel() + testConfig := remote.RemoteState{ Backend: "foo", DisableInit: true, @@ -150,10 +155,10 @@ func TestRemoteStateAsCtyDrift(t *testing.T) { }, } - ctyVal, err := remoteStateAsCty(&testConfig) + ctyVal, err := config.RemoteStateAsCty(&testConfig) require.NoError(t, err) - ctyMap, err := parseCtyValueToMap(ctyVal) + ctyMap, err := config.ParseCtyValueToMap(ctyVal) require.NoError(t, err) // Test the root properties @@ -177,10 +182,12 @@ func TestRemoteStateAsCtyDrift(t *testing.T) { // This test makes sure that all the fields in TerraformConfig exist in ctyTerraformConfig. func TestTerraformConfigAsCtyDrift(t *testing.T) { - terraformConfigStructInfo := structs.New(TerraformConfig{}) + t.Parallel() + + terraformConfigStructInfo := structs.New(config.TerraformConfig{}) terraformConfigFields := terraformConfigStructInfo.Names() sort.Strings(terraformConfigFields) - ctyTerraformConfigStructInfo := structs.New(ctyTerraformConfig{}) + ctyTerraformConfigStructInfo := structs.New(config.CtyTerraformConfig{}) ctyTerraformConfigFields := ctyTerraformConfigStructInfo.Names() sort.Strings(ctyTerraformConfigFields) assert.Equal(t, terraformConfigFields, ctyTerraformConfigFields) diff --git a/config/config_helpers.go b/config/config_helpers.go index 7fbfaec69..928433dcd 100644 --- a/config/config_helpers.go +++ b/config/config_helpers.go @@ -142,21 +142,21 @@ func createTerragruntEvalContext(ctx *ParsingContext, configPath string) (*hcl.E } terragruntFunctions := map[string]function.Function{ - FuncNameFindInParentFolders: wrapStringSliceToStringAsFuncImpl(ctx, findInParentFolders), - FuncNamePathRelativeToInclude: wrapStringSliceToStringAsFuncImpl(ctx, pathRelativeToInclude), - FuncNamePathRelativeFromInclude: wrapStringSliceToStringAsFuncImpl(ctx, pathRelativeFromInclude), + FuncNameFindInParentFolders: wrapStringSliceToStringAsFuncImpl(ctx, FindInParentFolders), + FuncNamePathRelativeToInclude: wrapStringSliceToStringAsFuncImpl(ctx, PathRelativeToInclude), + FuncNamePathRelativeFromInclude: wrapStringSliceToStringAsFuncImpl(ctx, PathRelativeFromInclude), FuncNameGetEnv: wrapStringSliceToStringAsFuncImpl(ctx, getEnvironmentVariable), - FuncNameRunCmd: wrapStringSliceToStringAsFuncImpl(ctx, runCommand), + FuncNameRunCmd: wrapStringSliceToStringAsFuncImpl(ctx, RunCommand), FuncNameReadTerragruntConfig: readTerragruntConfigAsFuncImpl(ctx), FuncNameGetPlatform: wrapVoidToStringAsFuncImpl(ctx, getPlatform), FuncNameGetRepoRoot: wrapVoidToStringAsFuncImpl(ctx, getRepoRoot), FuncNameGetPathFromRepoRoot: wrapVoidToStringAsFuncImpl(ctx, getPathFromRepoRoot), FuncNameGetPathToRepoRoot: wrapVoidToStringAsFuncImpl(ctx, getPathToRepoRoot), - FuncNameGetTerragruntDir: wrapVoidToStringAsFuncImpl(ctx, getTerragruntDir), + FuncNameGetTerragruntDir: wrapVoidToStringAsFuncImpl(ctx, GetTerragruntDir), FuncNameGetOriginalTerragruntDir: wrapVoidToStringAsFuncImpl(ctx, getOriginalTerragruntDir), FuncNameGetTerraformCommand: wrapVoidToStringAsFuncImpl(ctx, getTerraformCommand), FuncNameGetTerraformCLIArgs: wrapVoidToStringSliceAsFuncImpl(ctx, getTerraformCliArgs), - FuncNameGetParentTerragruntDir: wrapStringSliceToStringAsFuncImpl(ctx, getParentTerragruntDir), + FuncNameGetParentTerragruntDir: wrapStringSliceToStringAsFuncImpl(ctx, GetParentTerragruntDir), FuncNameGetAWSAccountID: wrapVoidToStringAsFuncImpl(ctx, getAWSAccountID), FuncNameGetAWSCallerIdentityArn: wrapVoidToStringAsFuncImpl(ctx, getAWSCallerIdentityARN), FuncNameGetAWSCallerIdentityUserID: wrapVoidToStringAsFuncImpl(ctx, getAWSCallerIdentityUserID), @@ -172,10 +172,10 @@ func createTerragruntEvalContext(ctx *ParsingContext, configPath string) (*hcl.E // Map with HCL functions introduced in Terraform after v0.15.3, since upgrade to a later version is not supported // https://github.com/gruntwork-io/terragrunt/blob/master/go.mod#L22 - FuncNameStartsWith: wrapStringSliceToBoolAsFuncImpl(ctx, startsWith), - FuncNameEndsWith: wrapStringSliceToBoolAsFuncImpl(ctx, endsWith), - FuncNameStrContains: wrapStringSliceToBoolAsFuncImpl(ctx, strContains), - FuncNameTimeCmp: wrapStringSliceToNumberAsFuncImpl(ctx, timeCmp), + FuncNameStartsWith: wrapStringSliceToBoolAsFuncImpl(ctx, StartsWith), + FuncNameEndsWith: wrapStringSliceToBoolAsFuncImpl(ctx, EndsWith), + FuncNameStrContains: wrapStringSliceToBoolAsFuncImpl(ctx, StrContains), + FuncNameTimeCmp: wrapStringSliceToNumberAsFuncImpl(ctx, TimeCmp), } functions := map[string]function.Function{} @@ -253,7 +253,7 @@ func getPathToRepoRoot(ctx *ParsingContext) (string, error) { } // Return the directory where the Terragrunt configuration file lives -func getTerragruntDir(ctx *ParsingContext) (string, error) { +func GetTerragruntDir(ctx *ParsingContext) (string, error) { terragruntConfigFileAbsPath, err := filepath.Abs(ctx.TerragruntOptions.TerragruntConfigPath) if err != nil { return "", errors.WithStackTrace(err) @@ -276,8 +276,8 @@ func getOriginalTerragruntDir(ctx *ParsingContext) (string, error) { } // Return the parent directory where the Terragrunt configuration file lives -func getParentTerragruntDir(ctx *ParsingContext, params []string) (string, error) { - parentPath, err := pathRelativeFromInclude(ctx, params) +func GetParentTerragruntDir(ctx *ParsingContext, params []string) (string, error) { + parentPath, err := PathRelativeFromInclude(ctx, params) if err != nil { return "", errors.WithStackTrace(err) } @@ -311,10 +311,10 @@ func parseGetEnvParameters(parameters []string) (EnvVar, error) { return envVariable, nil } -// runCommand is a helper function that runs a command and returns the stdout as the interporation +// RunCommand is a helper function that runs a command and returns the stdout as the interporation // for each `run_cmd` in locals section, function is called twice // result -func runCommand(ctx *ParsingContext, args []string) (string, error) { +func RunCommand(ctx *ParsingContext, args []string) (string, error) { // runCommandCache - cache of evaluated `run_cmd` invocations // see: https://github.com/gruntwork-io/terragrunt/issues/1427 runCommandCache := cache.ContextCache[string](ctx, RunCmdCacheContextKey) @@ -393,7 +393,7 @@ func getEnvironmentVariable(ctx *ParsingContext, parameters []string) (string, e // Find a parent Terragrunt configuration file in the parent folders above the current Terragrunt configuration file // and return its path -func findInParentFolders( +func FindInParentFolders( ctx *ParsingContext, params []string, ) (string, error) { @@ -453,7 +453,7 @@ func findInParentFolders( // Return the relative path between the included Terragrunt configuration file and the current Terragrunt configuration // file. Name param is required and used to lookup the relevant import block when called in a child config with multiple // import blocks. -func pathRelativeToInclude(ctx *ParsingContext, params []string) (string, error) { +func PathRelativeToInclude(ctx *ParsingContext, params []string) (string, error) { if ctx.TrackInclude == nil { return ".", nil } @@ -485,7 +485,7 @@ func pathRelativeToInclude(ctx *ParsingContext, params []string) (string, error) } // Return the relative path from the current Terragrunt configuration to the included Terragrunt configuration file -func pathRelativeFromInclude(ctx *ParsingContext, params []string) (string, error) { +func PathRelativeFromInclude(ctx *ParsingContext, params []string) (string, error) { if ctx.TrackInclude == nil { return ".", nil } @@ -583,7 +583,7 @@ func getAWSCallerIdentityUserID(ctx *ParsingContext) (string, error) { // Parse the terragrunt config and return a representation that can be used as a reference. If given a default value, // this will return the default if the terragrunt config file does not exist. -func readTerragruntConfig(ctx *ParsingContext, configPath string, defaultVal *cty.Value) (cty.Value, error) { +func ParseTerragruntConfig(ctx *ParsingContext, configPath string, defaultVal *cty.Value) (cty.Value, error) { // target config check: make sure the target config exists. If the file does not exist, and there is no default val, // return an error. If the file does not exist but there is a default val, return the default val. Otherwise, // proceed to parse the file as a terragrunt config file. @@ -643,7 +643,7 @@ func readTerragruntConfigAsFuncImpl(ctx *ParsingContext) function.Function { } targetConfigPath := strArgs[0] - return readTerragruntConfig(ctx, targetConfigPath, defaultVal) + return ParseTerragruntConfig(ctx, targetConfigPath, defaultVal) }, }) } @@ -832,8 +832,8 @@ func getSelectedIncludeBlock(trackInclude TrackInclude, params []string) (*Inclu return &imported, nil } -// startsWith Implementation of Terraform's startsWith function -func startsWith(ctx *ParsingContext, args []string) (bool, error) { +// StartsWith Implementation of Terraform's StartsWith function +func StartsWith(ctx *ParsingContext, args []string) (bool, error) { if len(args) == 0 { return false, errors.WithStackTrace(EmptyStringNotAllowedError("parameter to the startswith function")) } @@ -847,8 +847,8 @@ func startsWith(ctx *ParsingContext, args []string) (bool, error) { return false, nil } -// endsWith Implementation of Terraform's endsWith function -func endsWith(ctx *ParsingContext, args []string) (bool, error) { +// EndsWith Implementation of Terraform's EndsWith function +func EndsWith(ctx *ParsingContext, args []string) (bool, error) { if len(args) == 0 { return false, errors.WithStackTrace(EmptyStringNotAllowedError("parameter to the endswith function")) } @@ -862,8 +862,8 @@ func endsWith(ctx *ParsingContext, args []string) (bool, error) { return false, nil } -// timeCmp implements Terraform's `timecmp` function that compares two timestamps. -func timeCmp(ctx *ParsingContext, args []string) (int64, error) { +// TimeCmp implements Terraform's `timecmp` function that compares two timestamps. +func TimeCmp(ctx *ParsingContext, args []string) (int64, error) { if len(args) != matchedPats { return 0, errors.WithStackTrace(goErrors.New("function can take only two parameters: timestamp_a and timestamp_b")) } @@ -888,8 +888,8 @@ func timeCmp(ctx *ParsingContext, args []string) (int64, error) { } } -// strContains Implementation of Terraform's strContains function -func strContains(ctx *ParsingContext, args []string) (bool, error) { +// StrContains Implementation of Terraform's StrContains function +func StrContains(ctx *ParsingContext, args []string) (bool, error) { if len(args) == 0 { return false, errors.WithStackTrace(EmptyStringNotAllowedError("parameter to the strcontains function")) } @@ -982,7 +982,7 @@ func ParseAndDecodeVarFile(varFile string, fileContents []byte, out interface{}) typedOut, hasType := out.(*map[string]interface{}) if hasType { - genericMap, err := parseCtyValueToMap(ctyVal) + genericMap, err := ParseCtyValueToMap(ctyVal) if err != nil { return err } diff --git a/config/config_helpers_test.go b/config/config_helpers_test.go index 3f3bae763..946354449 100644 --- a/config/config_helpers_test.go +++ b/config/config_helpers_test.go @@ -1,4 +1,4 @@ -package config +package config_test import ( "context" @@ -8,6 +8,7 @@ import ( "testing" "github.com/gruntwork-io/go-commons/errors" + "github.com/gruntwork-io/terragrunt/config" "github.com/gruntwork-io/terragrunt/options" "github.com/gruntwork-io/terragrunt/test/helpers" "github.com/stretchr/testify/assert" @@ -18,8 +19,8 @@ import ( func TestPathRelativeToInclude(t *testing.T) { t.Parallel() - testCases := []struct { - include map[string]IncludeConfig + tc := []struct { + include map[string]config.IncludeConfig params []string terragruntOptions *options.TerragruntOptions expectedPath string @@ -27,70 +28,70 @@ func TestPathRelativeToInclude(t *testing.T) { { nil, nil, - terragruntOptionsForTest(t, helpers.RootFolder+"child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, helpers.RootFolder+"child/"+config.DefaultTerragruntConfigPath), ".", }, { - map[string]IncludeConfig{"": {Path: "../" + DefaultTerragruntConfigPath}}, + map[string]config.IncludeConfig{"": {Path: "../" + config.DefaultTerragruntConfigPath}}, nil, - terragruntOptionsForTest(t, helpers.RootFolder+"child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, helpers.RootFolder+"child/"+config.DefaultTerragruntConfigPath), "child", }, { - map[string]IncludeConfig{"": {Path: helpers.RootFolder + DefaultTerragruntConfigPath}}, + map[string]config.IncludeConfig{"": {Path: helpers.RootFolder + config.DefaultTerragruntConfigPath}}, nil, - terragruntOptionsForTest(t, helpers.RootFolder+"child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, helpers.RootFolder+"child/"+config.DefaultTerragruntConfigPath), "child", }, { - map[string]IncludeConfig{"": {Path: "../../../" + DefaultTerragruntConfigPath}}, + map[string]config.IncludeConfig{"": {Path: "../../../" + config.DefaultTerragruntConfigPath}}, nil, - terragruntOptionsForTest(t, helpers.RootFolder+"child/sub-child/sub-sub-child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, helpers.RootFolder+"child/sub-child/sub-sub-child/"+config.DefaultTerragruntConfigPath), "child/sub-child/sub-sub-child", }, { - map[string]IncludeConfig{"": {Path: helpers.RootFolder + DefaultTerragruntConfigPath}}, + map[string]config.IncludeConfig{"": {Path: helpers.RootFolder + config.DefaultTerragruntConfigPath}}, nil, - terragruntOptionsForTest(t, helpers.RootFolder+"child/sub-child/sub-sub-child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, helpers.RootFolder+"child/sub-child/sub-sub-child/"+config.DefaultTerragruntConfigPath), "child/sub-child/sub-sub-child", }, { - map[string]IncludeConfig{"": {Path: "../../other-child/" + DefaultTerragruntConfigPath}}, + map[string]config.IncludeConfig{"": {Path: "../../other-child/" + config.DefaultTerragruntConfigPath}}, nil, - terragruntOptionsForTest(t, helpers.RootFolder+"child/sub-child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, helpers.RootFolder+"child/sub-child/"+config.DefaultTerragruntConfigPath), "../child/sub-child", }, { - map[string]IncludeConfig{"": {Path: "../../" + DefaultTerragruntConfigPath}}, + map[string]config.IncludeConfig{"": {Path: "../../" + config.DefaultTerragruntConfigPath}}, nil, - terragruntOptionsForTest(t, "../child/sub-child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, "../child/sub-child/"+config.DefaultTerragruntConfigPath), "child/sub-child", }, { - map[string]IncludeConfig{ - "root": {Path: "../../" + DefaultTerragruntConfigPath}, - "child": {Path: "../../other-child/" + DefaultTerragruntConfigPath}, + map[string]config.IncludeConfig{ + "root": {Path: "../../" + config.DefaultTerragruntConfigPath}, + "child": {Path: "../../other-child/" + config.DefaultTerragruntConfigPath}, }, []string{"child"}, - terragruntOptionsForTest(t, "../child/sub-child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, "../child/sub-child/"+config.DefaultTerragruntConfigPath), "../child/sub-child", }, } - for _, testCase := range testCases { - trackInclude := getTrackIncludeFromTestData(testCase.include, testCase.params) - ctx := NewParsingContext(context.Background(), testCase.terragruntOptions).WithTrackInclude(trackInclude) - actualPath, actualErr := pathRelativeToInclude(ctx, testCase.params) - require.NoError(t, actualErr, "For include %v and options %v, unexpected error: %v", testCase.include, testCase.terragruntOptions, actualErr) - assert.Equal(t, testCase.expectedPath, actualPath, "For include %v and options %v", testCase.include, testCase.terragruntOptions) + for _, tt := range tc { + trackInclude := getTrackIncludeFromTestData(tt.include, tt.params) + ctx := config.NewParsingContext(context.Background(), tt.terragruntOptions).WithTrackInclude(trackInclude) + actualPath, actualErr := config.PathRelativeToInclude(ctx, tt.params) + require.NoError(t, actualErr, "For include %v and options %v, unexpected error: %v", tt.include, tt.terragruntOptions, actualErr) + assert.Equal(t, tt.expectedPath, actualPath, "For include %v and options %v", tt.include, tt.terragruntOptions) } } func TestPathRelativeFromInclude(t *testing.T) { t.Parallel() - testCases := []struct { - include map[string]IncludeConfig + tc := []struct { + include map[string]config.IncludeConfig params []string terragruntOptions *options.TerragruntOptions expectedPath string @@ -98,62 +99,62 @@ func TestPathRelativeFromInclude(t *testing.T) { { nil, nil, - terragruntOptionsForTest(t, helpers.RootFolder+"child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, helpers.RootFolder+"child/"+config.DefaultTerragruntConfigPath), ".", }, { - map[string]IncludeConfig{"": {Path: "../" + DefaultTerragruntConfigPath}}, + map[string]config.IncludeConfig{"": {Path: "../" + config.DefaultTerragruntConfigPath}}, nil, - terragruntOptionsForTest(t, helpers.RootFolder+"child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, helpers.RootFolder+"child/"+config.DefaultTerragruntConfigPath), "..", }, { - map[string]IncludeConfig{"": {Path: helpers.RootFolder + DefaultTerragruntConfigPath}}, + map[string]config.IncludeConfig{"": {Path: helpers.RootFolder + config.DefaultTerragruntConfigPath}}, nil, - terragruntOptionsForTest(t, helpers.RootFolder+"child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, helpers.RootFolder+"child/"+config.DefaultTerragruntConfigPath), "..", }, { - map[string]IncludeConfig{"": {Path: "../../../" + DefaultTerragruntConfigPath}}, + map[string]config.IncludeConfig{"": {Path: "../../../" + config.DefaultTerragruntConfigPath}}, nil, - terragruntOptionsForTest(t, helpers.RootFolder+"child/sub-child/sub-sub-child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, helpers.RootFolder+"child/sub-child/sub-sub-child/"+config.DefaultTerragruntConfigPath), "../../..", }, { - map[string]IncludeConfig{"": {Path: helpers.RootFolder + DefaultTerragruntConfigPath}}, + map[string]config.IncludeConfig{"": {Path: helpers.RootFolder + config.DefaultTerragruntConfigPath}}, nil, - terragruntOptionsForTest(t, helpers.RootFolder+"child/sub-child/sub-sub-child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, helpers.RootFolder+"child/sub-child/sub-sub-child/"+config.DefaultTerragruntConfigPath), "../../..", }, { - map[string]IncludeConfig{"": {Path: "../../other-child/" + DefaultTerragruntConfigPath}}, + map[string]config.IncludeConfig{"": {Path: "../../other-child/" + config.DefaultTerragruntConfigPath}}, nil, - terragruntOptionsForTest(t, helpers.RootFolder+"child/sub-child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, helpers.RootFolder+"child/sub-child/"+config.DefaultTerragruntConfigPath), "../../other-child", }, { - map[string]IncludeConfig{"": {Path: "../../" + DefaultTerragruntConfigPath}}, + map[string]config.IncludeConfig{"": {Path: "../../" + config.DefaultTerragruntConfigPath}}, nil, - terragruntOptionsForTest(t, "../child/sub-child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, "../child/sub-child/"+config.DefaultTerragruntConfigPath), "../..", }, { - map[string]IncludeConfig{ - "root": {Path: "../../" + DefaultTerragruntConfigPath}, - "child": {Path: "../../other-child/" + DefaultTerragruntConfigPath}, + map[string]config.IncludeConfig{ + "root": {Path: "../../" + config.DefaultTerragruntConfigPath}, + "child": {Path: "../../other-child/" + config.DefaultTerragruntConfigPath}, }, []string{"child"}, - terragruntOptionsForTest(t, "../child/sub-child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, "../child/sub-child/"+config.DefaultTerragruntConfigPath), "../../other-child", }, } - for _, testCase := range testCases { - trackInclude := getTrackIncludeFromTestData(testCase.include, testCase.params) - ctx := NewParsingContext(context.Background(), testCase.terragruntOptions).WithTrackInclude(trackInclude) - actualPath, actualErr := pathRelativeFromInclude(ctx, testCase.params) - require.NoError(t, actualErr, "For include %v and options %v, unexpected error: %v", testCase.include, testCase.terragruntOptions, actualErr) - assert.Equal(t, testCase.expectedPath, actualPath, "For include %v and options %v", testCase.include, testCase.terragruntOptions) + for _, tt := range tc { + trackInclude := getTrackIncludeFromTestData(tt.include, tt.params) + ctx := config.NewParsingContext(context.Background(), tt.terragruntOptions).WithTrackInclude(trackInclude) + actualPath, actualErr := config.PathRelativeFromInclude(ctx, tt.params) + require.NoError(t, actualErr, "For include %v and options %v, unexpected error: %v", tt.include, tt.terragruntOptions, actualErr) + assert.Equal(t, tt.expectedPath, actualPath, "For include %v and options %v", tt.include, tt.terragruntOptions) } } @@ -161,7 +162,7 @@ func TestRunCommand(t *testing.T) { t.Parallel() homeDir := os.Getenv("HOME") - testCases := []struct { + tc := []struct { params []string terragruntOptions *options.TerragruntOptions expectedOutput string @@ -213,20 +214,24 @@ func TestRunCommand(t *testing.T) { nil, terragruntOptionsForTest(t, homeDir), "", - EmptyStringNotAllowedError("{run_cmd()}"), + config.EmptyStringNotAllowedError("{run_cmd()}"), }, } - for _, testCase := range testCases { - t.Run(testCase.terragruntOptions.TerragruntConfigPath, func(t *testing.T) { - ctx := NewParsingContext(context.Background(), testCase.terragruntOptions) - actualOutput, actualErr := runCommand(ctx, testCase.params) - if testCase.expectedErr != nil { + for _, tt := range tc { + tt := tt + + t.Run(tt.terragruntOptions.TerragruntConfigPath, func(t *testing.T) { + t.Parallel() + + ctx := config.NewParsingContext(context.Background(), tt.terragruntOptions) + actualOutput, actualErr := config.RunCommand(ctx, tt.params) + if tt.expectedErr != nil { if assert.Error(t, actualErr) { - assert.IsType(t, testCase.expectedErr, errors.Unwrap(actualErr)) + assert.IsType(t, tt.expectedErr, errors.Unwrap(actualErr)) } } else { require.NoError(t, actualErr) - assert.Equal(t, testCase.expectedOutput, actualOutput) + assert.Equal(t, tt.expectedOutput, actualOutput) } }) } @@ -241,7 +246,7 @@ func absPath(t *testing.T, path string) string { func TestFindInParentFolders(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { params []string terragruntOptions *options.TerragruntOptions expectedPath string @@ -249,55 +254,55 @@ func TestFindInParentFolders(t *testing.T) { }{ { nil, - terragruntOptionsForTest(t, "../test/fixture-parent-folders/terragrunt-in-root/child/"+DefaultTerragruntConfigPath), - absPath(t, "../test/fixture-parent-folders/terragrunt-in-root/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, "../test/fixture-parent-folders/terragrunt-in-root/child/"+config.DefaultTerragruntConfigPath), + absPath(t, "../test/fixture-parent-folders/terragrunt-in-root/"+config.DefaultTerragruntConfigPath), nil, }, { nil, - terragruntOptionsForTest(t, "../test/fixture-parent-folders/terragrunt-in-root/child/sub-child/sub-sub-child/"+DefaultTerragruntConfigPath), - absPath(t, "../test/fixture-parent-folders/terragrunt-in-root/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, "../test/fixture-parent-folders/terragrunt-in-root/child/sub-child/sub-sub-child/"+config.DefaultTerragruntConfigPath), + absPath(t, "../test/fixture-parent-folders/terragrunt-in-root/"+config.DefaultTerragruntConfigPath), nil, }, { nil, - terragruntOptionsForTestWithMaxFolders(t, "../test/fixture-parent-folders/no-terragrunt-in-root/child/sub-child/"+DefaultTerragruntConfigPath, 3), + terragruntOptionsForTestWithMaxFolders(t, "../test/fixture-parent-folders/no-terragrunt-in-root/child/sub-child/"+config.DefaultTerragruntConfigPath, 3), "", - ParentFileNotFoundError{}, + config.ParentFileNotFoundError{}, }, { nil, - terragruntOptionsForTest(t, "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/"+DefaultTerragruntConfigPath), - absPath(t, "../test/fixture-parent-folders/multiple-terragrunt-in-parents/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/"+config.DefaultTerragruntConfigPath), + absPath(t, "../test/fixture-parent-folders/multiple-terragrunt-in-parents/"+config.DefaultTerragruntConfigPath), nil, }, { nil, - terragruntOptionsForTest(t, "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/sub-child/"+DefaultTerragruntConfigPath), - absPath(t, "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/sub-child/"+config.DefaultTerragruntConfigPath), + absPath(t, "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/"+config.DefaultTerragruntConfigPath), nil, }, { nil, - terragruntOptionsForTest(t, "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/sub-child/sub-sub-child/"+DefaultTerragruntConfigPath), - absPath(t, "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/sub-child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/sub-child/sub-sub-child/"+config.DefaultTerragruntConfigPath), + absPath(t, "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/sub-child/"+config.DefaultTerragruntConfigPath), nil, }, { []string{"foo.txt"}, - terragruntOptionsForTest(t, "../test/fixture-parent-folders/other-file-names/child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, "../test/fixture-parent-folders/other-file-names/child/"+config.DefaultTerragruntConfigPath), absPath(t, "../test/fixture-parent-folders/other-file-names/foo.txt"), nil, }, { []string{"common/foo.txt"}, - terragruntOptionsForTest(t, "../test/fixture-parent-folders/in-another-subfolder/live/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, "../test/fixture-parent-folders/in-another-subfolder/live/"+config.DefaultTerragruntConfigPath), absPath(t, "../test/fixture-parent-folders/in-another-subfolder/common/foo.txt"), nil, }, { []string{"tfwork"}, - terragruntOptionsForTest(t, "../test/fixture-parent-folders/with-params/tfwork/tg/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, "../test/fixture-parent-folders/with-params/tfwork/tg/"+config.DefaultTerragruntConfigPath), absPath(t, "../test/fixture-parent-folders/with-params/tfwork"), nil, }, @@ -305,13 +310,13 @@ func TestFindInParentFolders(t *testing.T) { nil, terragruntOptionsForTest(t, "/"), "", - ParentFileNotFoundError{}, + config.ParentFileNotFoundError{}, }, { nil, terragruntOptionsForTest(t, "/fake/path"), "", - ParentFileNotFoundError{}, + config.ParentFileNotFoundError{}, }, { []string{"foo.txt", "fallback.txt"}, @@ -321,17 +326,21 @@ func TestFindInParentFolders(t *testing.T) { }, } - for _, testCase := range testCases { - t.Run(testCase.terragruntOptions.TerragruntConfigPath, func(t *testing.T) { - ctx := NewParsingContext(context.Background(), testCase.terragruntOptions) - actualPath, actualErr := findInParentFolders(ctx, testCase.params) - if testCase.expectedErr != nil { + for _, tt := range tc { + tt := tt + + t.Run(tt.terragruntOptions.TerragruntConfigPath, func(t *testing.T) { + t.Parallel() + + ctx := config.NewParsingContext(context.Background(), tt.terragruntOptions) + actualPath, actualErr := config.FindInParentFolders(ctx, tt.params) + if tt.expectedErr != nil { if assert.Error(t, actualErr) { - assert.IsType(t, testCase.expectedErr, errors.Unwrap(actualErr)) + assert.IsType(t, tt.expectedErr, errors.Unwrap(actualErr)) } } else { require.NoError(t, actualErr) - assert.Equal(t, testCase.expectedPath, actualPath) + assert.Equal(t, tt.expectedPath, actualPath) } }) } @@ -340,9 +349,9 @@ func TestFindInParentFolders(t *testing.T) { func TestResolveTerragruntInterpolation(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { str string - include *IncludeConfig + include *config.IncludeConfig terragruntOptions *options.TerragruntOptions expectedOut string expectedErr string @@ -350,56 +359,59 @@ func TestResolveTerragruntInterpolation(t *testing.T) { { "terraform { source = path_relative_to_include() }", nil, - terragruntOptionsForTest(t, "/root/child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, "/root/child/"+config.DefaultTerragruntConfigPath), ".", "", }, { "terraform { source = path_relative_to_include() }", - &IncludeConfig{Path: "../" + DefaultTerragruntConfigPath}, - terragruntOptionsForTest(t, "/root/child/"+DefaultTerragruntConfigPath), + &config.IncludeConfig{Path: "../" + config.DefaultTerragruntConfigPath}, + terragruntOptionsForTest(t, "/root/child/"+config.DefaultTerragruntConfigPath), "child", "", }, { "terraform { source = find_in_parent_folders() }", nil, - terragruntOptionsForTest(t, "../test/fixture-parent-folders/terragrunt-in-root/child/sub-child/"+DefaultTerragruntConfigPath), - absPath(t, "../test/fixture-parent-folders/terragrunt-in-root/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, "../test/fixture-parent-folders/terragrunt-in-root/child/sub-child/"+config.DefaultTerragruntConfigPath), + absPath(t, "../test/fixture-parent-folders/terragrunt-in-root/"+config.DefaultTerragruntConfigPath), "", }, { "terraform { source = find_in_parent_folders() }", nil, - terragruntOptionsForTestWithMaxFolders(t, "../test/fixture-parent-folders/terragrunt-in-root/child/sub-child/"+DefaultTerragruntConfigPath, 1), + terragruntOptionsForTestWithMaxFolders(t, "../test/fixture-parent-folders/terragrunt-in-root/child/sub-child/"+config.DefaultTerragruntConfigPath, 1), "", "ParentFileNotFoundError", }, { "terraform { source = find_in_parent_folders() }", nil, - terragruntOptionsForTestWithMaxFolders(t, "../test/fixture-parent-folders/no-terragrunt-in-root/child/sub-child/"+DefaultTerragruntConfigPath, 3), + terragruntOptionsForTestWithMaxFolders(t, "../test/fixture-parent-folders/no-terragrunt-in-root/child/sub-child/"+config.DefaultTerragruntConfigPath, 3), "", "ParentFileNotFoundError", }, } - for _, testCase := range testCases { - // The following is necessary to make sure testCase's values don't + for _, tt := range tc { + // The following is necessary to make sure tt's values don't // get updated due to concurrency within the scope of t.Run(..) below - testCase := testCase - t.Run(fmt.Sprintf("%s--%s", testCase.str, testCase.terragruntOptions.TerragruntConfigPath), func(t *testing.T) { - ctx := NewParsingContext(context.Background(), testCase.terragruntOptions) - actualOut, actualErr := ParseConfigString(ctx, "mock-path-for-test.hcl", testCase.str, testCase.include) - if testCase.expectedErr != "" { + tt := tt + + t.Run(fmt.Sprintf("%s--%s", tt.str, tt.terragruntOptions.TerragruntConfigPath), func(t *testing.T) { + t.Parallel() + + ctx := config.NewParsingContext(context.Background(), tt.terragruntOptions) + actualOut, actualErr := config.ParseConfigString(ctx, "mock-path-for-test.hcl", tt.str, tt.include) + if tt.expectedErr != "" { require.Error(t, actualErr) - assert.Contains(t, actualErr.Error(), testCase.expectedErr) + assert.Contains(t, actualErr.Error(), tt.expectedErr) } else { require.NoError(t, actualErr) assert.NotNil(t, actualOut) assert.NotNil(t, actualOut.Terraform) assert.NotNil(t, actualOut.Terraform.Source) - assert.Equal(t, testCase.expectedOut, *actualOut.Terraform.Source) + assert.Equal(t, tt.expectedOut, *actualOut.Terraform.Source) } }) } @@ -408,9 +420,9 @@ func TestResolveTerragruntInterpolation(t *testing.T) { func TestResolveEnvInterpolationConfigString(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { str string - include *IncludeConfig + include *config.IncludeConfig terragruntOptions *options.TerragruntOptions expectedOut string expectedErr string @@ -418,81 +430,83 @@ func TestResolveEnvInterpolationConfigString(t *testing.T) { { `iam_role = "foo/${get_env()}/bar"`, nil, - terragruntOptionsForTest(t, "/root/child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, "/root/child/"+config.DefaultTerragruntConfigPath), "", "InvalidGetEnvParamsError", }, { `iam_role = "foo/${get_env("","")}/bar"`, nil, - terragruntOptionsForTest(t, "/root/child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, "/root/child/"+config.DefaultTerragruntConfigPath), "", "InvalidEnvParamNameError", }, { `iam_role = get_env()`, nil, - terragruntOptionsForTest(t, "/root/child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, "/root/child/"+config.DefaultTerragruntConfigPath), "", "InvalidGetEnvParamsError", }, { `iam_role = get_env("TEST_VAR_1", "TEST_VAR_2", "TEST_VAR_3")`, nil, - terragruntOptionsForTest(t, "/root/child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, "/root/child/"+config.DefaultTerragruntConfigPath), "", "InvalidGetEnvParamsError", }, { `iam_role = get_env("TEST_ENV_TERRAGRUNT_VAR")`, nil, - terragruntOptionsForTestWithEnv(t, "/root/child/"+DefaultTerragruntConfigPath, map[string]string{"TEST_ENV_TERRAGRUNT_VAR": "SOMETHING"}), + terragruntOptionsForTestWithEnv(t, "/root/child/"+config.DefaultTerragruntConfigPath, map[string]string{"TEST_ENV_TERRAGRUNT_VAR": "SOMETHING"}), "SOMETHING", "", }, { `iam_role = get_env("SOME_VAR", "SOME_VALUE")`, nil, - terragruntOptionsForTest(t, "/root/child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, "/root/child/"+config.DefaultTerragruntConfigPath), "SOME_VALUE", "", }, { `iam_role = "foo/${get_env("TEST_ENV_TERRAGRUNT_HIT","")}/bar"`, nil, - terragruntOptionsForTestWithEnv(t, "/root/child/"+DefaultTerragruntConfigPath, map[string]string{"TEST_ENV_TERRAGRUNT_OTHER": "SOMETHING"}), + terragruntOptionsForTestWithEnv(t, "/root/child/"+config.DefaultTerragruntConfigPath, map[string]string{"TEST_ENV_TERRAGRUNT_OTHER": "SOMETHING"}), "foo//bar", "", }, { `iam_role = "foo/${get_env("TEST_ENV_TERRAGRUNT_HIT","DEFAULT")}/bar"`, nil, - terragruntOptionsForTestWithEnv(t, "/root/child/"+DefaultTerragruntConfigPath, map[string]string{"TEST_ENV_TERRAGRUNT_OTHER": "SOMETHING"}), + terragruntOptionsForTestWithEnv(t, "/root/child/"+config.DefaultTerragruntConfigPath, map[string]string{"TEST_ENV_TERRAGRUNT_OTHER": "SOMETHING"}), "foo/DEFAULT/bar", "", }, { `iam_role = "foo/${get_env("TEST_ENV_TERRAGRUNT_VAR")}/bar"`, nil, - terragruntOptionsForTestWithEnv(t, "/root/child/"+DefaultTerragruntConfigPath, map[string]string{"TEST_ENV_TERRAGRUNT_VAR": "SOMETHING"}), + terragruntOptionsForTestWithEnv(t, "/root/child/"+config.DefaultTerragruntConfigPath, map[string]string{"TEST_ENV_TERRAGRUNT_VAR": "SOMETHING"}), "foo/SOMETHING/bar", "", }, } - for _, testCase := range testCases { - // The following is necessary to make sure testCase's values don't + for _, tt := range tc { + // The following is necessary to make sure tt's values don't // get updated due to concurrency within the scope of t.Run(..) below - testCase := testCase - t.Run(testCase.str, func(t *testing.T) { - ctx := NewParsingContext(context.Background(), testCase.terragruntOptions) - actualOut, actualErr := ParseConfigString(ctx, "mock-path-for-test.hcl", testCase.str, testCase.include) - if testCase.expectedErr != "" { + tt := tt + t.Run(tt.str, func(t *testing.T) { + t.Parallel() + + ctx := config.NewParsingContext(context.Background(), tt.terragruntOptions) + actualOut, actualErr := config.ParseConfigString(ctx, "mock-path-for-test.hcl", tt.str, tt.include) + if tt.expectedErr != "" { require.Error(t, actualErr) - assert.Contains(t, actualErr.Error(), testCase.expectedErr) + assert.Contains(t, actualErr.Error(), tt.expectedErr) } else { require.NoError(t, actualErr) - assert.Equal(t, testCase.expectedOut, actualOut.IamRole) + assert.Equal(t, tt.expectedOut, actualOut.IamRole) } }) } @@ -501,41 +515,43 @@ func TestResolveEnvInterpolationConfigString(t *testing.T) { func TestResolveCommandsInterpolationConfigString(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { str string - include *IncludeConfig + include *config.IncludeConfig terragruntOptions *options.TerragruntOptions expectedFooInput []string }{ { "inputs = { foo = get_terraform_commands_that_need_locking() }", nil, - terragruntOptionsForTest(t, DefaultTerragruntConfigPath), - TERRAFORM_COMMANDS_NEED_LOCKING, + terragruntOptionsForTest(t, config.DefaultTerragruntConfigPath), + config.TERRAFORM_COMMANDS_NEED_LOCKING, }, { `inputs = { foo = get_terraform_commands_that_need_vars() }`, nil, - terragruntOptionsForTest(t, DefaultTerragruntConfigPath), - TERRAFORM_COMMANDS_NEED_VARS, + terragruntOptionsForTest(t, config.DefaultTerragruntConfigPath), + config.TERRAFORM_COMMANDS_NEED_VARS, }, { "inputs = { foo = get_terraform_commands_that_need_parallelism() }", nil, - terragruntOptionsForTest(t, DefaultTerragruntConfigPath), - TERRAFORM_COMMANDS_NEED_PARALLELISM, + terragruntOptionsForTest(t, config.DefaultTerragruntConfigPath), + config.TERRAFORM_COMMANDS_NEED_PARALLELISM, }, } - for _, testCase := range testCases { - // The following is necessary to make sure testCase's values don't + for _, tt := range tc { + // The following is necessary to make sure tt's values don't // get updated due to concurrency within the scope of t.Run(..) below - testCase := testCase + tt := tt + + t.Run(tt.str, func(t *testing.T) { + t.Parallel() - t.Run(testCase.str, func(t *testing.T) { - ctx := NewParsingContext(context.Background(), testCase.terragruntOptions) - actualOut, actualErr := ParseConfigString(ctx, "mock-path-for-test.hcl", testCase.str, testCase.include) - require.NoError(t, actualErr, "For string '%s' include %v and options %v, unexpected error: %v", testCase.str, testCase.include, testCase.terragruntOptions, actualErr) + ctx := config.NewParsingContext(context.Background(), tt.terragruntOptions) + actualOut, actualErr := config.ParseConfigString(ctx, "mock-path-for-test.hcl", tt.str, tt.include) + require.NoError(t, actualErr, "For string '%s' include %v and options %v, unexpected error: %v", tt.str, tt.include, tt.terragruntOptions, actualErr) assert.NotNil(t, actualOut) @@ -547,7 +563,7 @@ func TestResolveCommandsInterpolationConfigString(t *testing.T) { fooSlice := toStringSlice(t, foo) - assert.EqualValues(t, testCase.expectedFooInput, fooSlice, "For string '%s' include %v and options %v", testCase.str, testCase.include, testCase.terragruntOptions) + assert.EqualValues(t, tt.expectedFooInput, fooSlice, "For string '%s' include %v and options %v", tt.str, tt.include, tt.terragruntOptions) }) } } @@ -556,7 +572,7 @@ func TestResolveCliArgsInterpolationConfigString(t *testing.T) { t.Parallel() for _, cliArgs := range [][]string{nil, {}, {"apply"}, {"plan", "-out=planfile"}} { - opts := terragruntOptionsForTest(t, DefaultTerragruntConfigPath) + opts := terragruntOptionsForTest(t, config.DefaultTerragruntConfigPath) opts.TerraformCliArgs = cliArgs expectedFooInput := cliArgs // Expecting nil to be returned for get_terraform_cli_args() call for @@ -564,9 +580,9 @@ func TestResolveCliArgsInterpolationConfigString(t *testing.T) { if len(cliArgs) == 0 { expectedFooInput = nil } - testCase := struct { + tt := struct { str string - include *IncludeConfig + include *config.IncludeConfig terragruntOptions *options.TerragruntOptions expectedFooInput []string }{ @@ -575,10 +591,12 @@ func TestResolveCliArgsInterpolationConfigString(t *testing.T) { opts, expectedFooInput, } - t.Run(testCase.str, func(t *testing.T) { - ctx := NewParsingContext(context.Background(), testCase.terragruntOptions) - actualOut, actualErr := ParseConfigString(ctx, "mock-path-for-test.hcl", testCase.str, testCase.include) - require.NoError(t, actualErr, "For string '%s' include %v and options %v, unexpected error: %v", testCase.str, testCase.include, testCase.terragruntOptions, actualErr) + t.Run(tt.str, func(t *testing.T) { + t.Parallel() + + ctx := config.NewParsingContext(context.Background(), tt.terragruntOptions) + actualOut, actualErr := config.ParseConfigString(ctx, "mock-path-for-test.hcl", tt.str, tt.include) + require.NoError(t, actualErr, "For string '%s' include %v and options %v, unexpected error: %v", tt.str, tt.include, tt.terragruntOptions, actualErr) assert.NotNil(t, actualOut) @@ -589,7 +607,7 @@ func TestResolveCliArgsInterpolationConfigString(t *testing.T) { assert.True(t, containsFoo) fooSlice := toStringSlice(t, foo) - assert.EqualValues(t, testCase.expectedFooInput, fooSlice, "For string '%s' include %v and options %v", testCase.str, testCase.include, testCase.terragruntOptions) + assert.EqualValues(t, tt.expectedFooInput, fooSlice, "For string '%s' include %v and options %v", tt.str, tt.include, tt.terragruntOptions) }) } } @@ -637,8 +655,8 @@ func testGetTerragruntDir(t *testing.T, configPath string, expectedPath string) terragruntOptions, err := options.NewTerragruntOptionsForTest(configPath) require.NoError(t, err, "Unexpected error creating NewTerragruntOptionsForTest: %v", err) - ctx := NewParsingContext(context.Background(), terragruntOptions) - actualPath, err := getTerragruntDir(ctx) + ctx := config.NewParsingContext(context.Background(), terragruntOptions) + actualPath, err := config.GetTerragruntDir(ctx) require.NoError(t, err, "Unexpected error: %v", err) assert.Equal(t, expectedPath, actualPath) @@ -671,8 +689,8 @@ func TestGetParentTerragruntDir(t *testing.T) { require.NoError(t, err, "Could not get current working dir: %v", err) parentDir := filepath.ToSlash(filepath.Dir(currentDir)) - testCases := []struct { - include map[string]IncludeConfig + tc := []struct { + include map[string]config.IncludeConfig params []string terragruntOptions *options.TerragruntOptions expectedPath string @@ -680,69 +698,69 @@ func TestGetParentTerragruntDir(t *testing.T) { { nil, nil, - terragruntOptionsForTest(t, helpers.RootFolder+"child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, helpers.RootFolder+"child/"+config.DefaultTerragruntConfigPath), helpers.RootFolder + "child", }, { - map[string]IncludeConfig{"": {Path: "../" + DefaultTerragruntConfigPath}}, + map[string]config.IncludeConfig{"": {Path: "../" + config.DefaultTerragruntConfigPath}}, nil, - terragruntOptionsForTest(t, helpers.RootFolder+"child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, helpers.RootFolder+"child/"+config.DefaultTerragruntConfigPath), helpers.RootFolder, }, { - map[string]IncludeConfig{"": {Path: helpers.RootFolder + DefaultTerragruntConfigPath}}, + map[string]config.IncludeConfig{"": {Path: helpers.RootFolder + config.DefaultTerragruntConfigPath}}, nil, - terragruntOptionsForTest(t, helpers.RootFolder+"child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, helpers.RootFolder+"child/"+config.DefaultTerragruntConfigPath), helpers.RootFolder, }, { - map[string]IncludeConfig{"": {Path: "../../../" + DefaultTerragruntConfigPath}}, + map[string]config.IncludeConfig{"": {Path: "../../../" + config.DefaultTerragruntConfigPath}}, nil, - terragruntOptionsForTest(t, helpers.RootFolder+"child/sub-child/sub-sub-child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, helpers.RootFolder+"child/sub-child/sub-sub-child/"+config.DefaultTerragruntConfigPath), helpers.RootFolder, }, { - map[string]IncludeConfig{"": {Path: helpers.RootFolder + DefaultTerragruntConfigPath}}, + map[string]config.IncludeConfig{"": {Path: helpers.RootFolder + config.DefaultTerragruntConfigPath}}, nil, - terragruntOptionsForTest(t, helpers.RootFolder+"child/sub-child/sub-sub-child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, helpers.RootFolder+"child/sub-child/sub-sub-child/"+config.DefaultTerragruntConfigPath), helpers.RootFolder, }, { - map[string]IncludeConfig{"": {Path: "../../other-child/" + DefaultTerragruntConfigPath}}, + map[string]config.IncludeConfig{"": {Path: "../../other-child/" + config.DefaultTerragruntConfigPath}}, nil, - terragruntOptionsForTest(t, helpers.RootFolder+"child/sub-child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, helpers.RootFolder+"child/sub-child/"+config.DefaultTerragruntConfigPath), filepath.VolumeName(parentDir) + "/other-child", }, { - map[string]IncludeConfig{"": {Path: "../../" + DefaultTerragruntConfigPath}}, + map[string]config.IncludeConfig{"": {Path: "../../" + config.DefaultTerragruntConfigPath}}, nil, - terragruntOptionsForTest(t, "../child/sub-child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, "../child/sub-child/"+config.DefaultTerragruntConfigPath), parentDir, }, { - map[string]IncludeConfig{ - "root": {Path: "../../" + DefaultTerragruntConfigPath}, - "child": {Path: "../../other-child/" + DefaultTerragruntConfigPath}, + map[string]config.IncludeConfig{ + "root": {Path: "../../" + config.DefaultTerragruntConfigPath}, + "child": {Path: "../../other-child/" + config.DefaultTerragruntConfigPath}, }, []string{"child"}, - terragruntOptionsForTest(t, helpers.RootFolder+"child/sub-child/"+DefaultTerragruntConfigPath), + terragruntOptionsForTest(t, helpers.RootFolder+"child/sub-child/"+config.DefaultTerragruntConfigPath), filepath.VolumeName(parentDir) + "/other-child", }, } - for _, testCase := range testCases { - trackInclude := getTrackIncludeFromTestData(testCase.include, testCase.params) - ctx := NewParsingContext(context.Background(), testCase.terragruntOptions).WithTrackInclude(trackInclude) - actualPath, actualErr := getParentTerragruntDir(ctx, testCase.params) - require.NoError(t, actualErr, "For include %v and options %v, unexpected error: %v", testCase.include, testCase.terragruntOptions, actualErr) - assert.Equal(t, testCase.expectedPath, actualPath, "For include %v and options %v", testCase.include, testCase.terragruntOptions) + for _, tt := range tc { + trackInclude := getTrackIncludeFromTestData(tt.include, tt.params) + ctx := config.NewParsingContext(context.Background(), tt.terragruntOptions).WithTrackInclude(trackInclude) + actualPath, actualErr := config.GetParentTerragruntDir(ctx, tt.params) + require.NoError(t, actualErr, "For include %v and options %v, unexpected error: %v", tt.include, tt.terragruntOptions, actualErr) + assert.Equal(t, tt.expectedPath, actualPath, "For include %v and options %v", tt.include, tt.terragruntOptions) } } func TestTerraformBuiltInFunctions(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { input string expected interface{} }{ @@ -780,14 +798,17 @@ func TestTerraformBuiltInFunctions(t *testing.T) { }, } - for _, testCase := range testCases { - t.Run(testCase.input, func(t *testing.T) { + for _, tt := range tc { + tt := tt - terragruntOptions := terragruntOptionsForTest(t, "../test/fixture-config-terraform-functions/"+DefaultTerragruntConfigPath) - configString := fmt.Sprintf("inputs = { test = %s }", testCase.input) - ctx := NewParsingContext(context.Background(), terragruntOptions) - actual, err := ParseConfigString(ctx, terragruntOptions.TerragruntConfigPath, configString, nil) - require.NoError(t, err, "For hcl '%s' include %v and options %v, unexpected error: %v", testCase.input, nil, terragruntOptions, err) + t.Run(tt.input, func(t *testing.T) { + t.Parallel() + + terragruntOptions := terragruntOptionsForTest(t, "../test/fixture-config-terraform-functions/"+config.DefaultTerragruntConfigPath) + configString := fmt.Sprintf("inputs = { test = %s }", tt.input) + ctx := config.NewParsingContext(context.Background(), terragruntOptions) + actual, err := config.ParseConfigString(ctx, terragruntOptions.TerragruntConfigPath, configString, nil) + require.NoError(t, err, "For hcl '%s' include %v and options %v, unexpected error: %v", tt.input, nil, terragruntOptions, err) assert.NotNil(t, actual) @@ -797,7 +818,7 @@ func TestTerraformBuiltInFunctions(t *testing.T) { test, containsTest := inputs["test"] assert.True(t, containsTest) - assert.EqualValues(t, testCase.expected, test, "For hcl '%s' include %v and options %v", testCase.input, nil, terragruntOptions) + assert.EqualValues(t, tt.expected, test, "For hcl '%s' include %v and options %v", tt.input, nil, terragruntOptions) }) } } @@ -805,7 +826,7 @@ func TestTerraformBuiltInFunctions(t *testing.T) { func TestTerraformOutputJsonToCtyValueMap(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { input string expected map[string]cty.Value }{ @@ -856,13 +877,13 @@ func TestTerraformOutputJsonToCtyValueMap(t *testing.T) { }, } - mockTargetConfig := DefaultTerragruntConfigPath - for _, testCase := range testCases { - converted, err := terraformOutputJsonToCtyValueMap(mockTargetConfig, []byte(testCase.input)) + mockTargetConfig := config.DefaultTerragruntConfigPath + for _, tt := range tc { + converted, err := config.TerraformOutputJsonToCtyValueMap(mockTargetConfig, []byte(tt.input)) require.NoError(t, err) - assert.Equal(t, getKeys(converted), getKeys(testCase.expected)) + assert.Equal(t, getKeys(converted), getKeys(tt.expected)) for k, v := range converted { - assert.True(t, v.Equals(testCase.expected[k]).True()) + assert.True(t, v.Equals(tt.expected[k]).True()) } } } @@ -870,13 +891,13 @@ func TestTerraformOutputJsonToCtyValueMap(t *testing.T) { func TestReadTerragruntConfigInputs(t *testing.T) { t.Parallel() - options := terragruntOptionsForTest(t, DefaultTerragruntConfigPath) + options := terragruntOptionsForTest(t, config.DefaultTerragruntConfigPath) - ctx := NewParsingContext(context.Background(), options) - tgConfigCty, err := readTerragruntConfig(ctx, "../test/fixture-inputs/terragrunt.hcl", nil) + ctx := config.NewParsingContext(context.Background(), options) + tgConfigCty, err := config.ParseTerragruntConfig(ctx, "../test/fixture-inputs/terragrunt.hcl", nil) require.NoError(t, err) - tgConfigMap, err := parseCtyValueToMap(tgConfigCty) + tgConfigMap, err := config.ParseCtyValueToMap(tgConfigCty) require.NoError(t, err) inputsMap := tgConfigMap["inputs"].(map[string]interface{}) @@ -908,12 +929,12 @@ func TestReadTerragruntConfigInputs(t *testing.T) { func TestReadTerragruntConfigRemoteState(t *testing.T) { t.Parallel() - options := terragruntOptionsForTest(t, DefaultTerragruntConfigPath) - ctx := NewParsingContext(context.Background(), options) - tgConfigCty, err := readTerragruntConfig(ctx, "../test/fixture/terragrunt.hcl", nil) + options := terragruntOptionsForTest(t, config.DefaultTerragruntConfigPath) + ctx := config.NewParsingContext(context.Background(), options) + tgConfigCty, err := config.ParseTerragruntConfig(ctx, "../test/fixture/terragrunt.hcl", nil) require.NoError(t, err) - tgConfigMap, err := parseCtyValueToMap(tgConfigCty) + tgConfigMap, err := config.ParseCtyValueToMap(tgConfigCty) require.NoError(t, err) remoteStateMap := tgConfigMap["remote_state"].(map[string]interface{}) @@ -941,12 +962,12 @@ func TestReadTerragruntConfigRemoteState(t *testing.T) { func TestReadTerragruntConfigHooks(t *testing.T) { t.Parallel() - options := terragruntOptionsForTest(t, DefaultTerragruntConfigPath) - ctx := NewParsingContext(context.Background(), options) - tgConfigCty, err := readTerragruntConfig(ctx, "../test/fixture-hooks/before-after-and-on-error/terragrunt.hcl", nil) + options := terragruntOptionsForTest(t, config.DefaultTerragruntConfigPath) + ctx := config.NewParsingContext(context.Background(), options) + tgConfigCty, err := config.ParseTerragruntConfig(ctx, "../test/fixture-hooks/before-after-and-on-error/terragrunt.hcl", nil) require.NoError(t, err) - tgConfigMap, err := parseCtyValueToMap(tgConfigCty) + tgConfigMap, err := config.ParseCtyValueToMap(tgConfigCty) require.NoError(t, err) terraformMap := tgConfigMap["terraform"].(map[string]interface{}) @@ -984,12 +1005,12 @@ func TestReadTerragruntConfigHooks(t *testing.T) { func TestReadTerragruntConfigLocals(t *testing.T) { t.Parallel() - options := terragruntOptionsForTest(t, DefaultTerragruntConfigPath) - ctx := NewParsingContext(context.Background(), options) - tgConfigCty, err := readTerragruntConfig(ctx, "../test/fixture-locals/canonical/terragrunt.hcl", nil) + options := terragruntOptionsForTest(t, config.DefaultTerragruntConfigPath) + ctx := config.NewParsingContext(context.Background(), options) + tgConfigCty, err := config.ParseTerragruntConfig(ctx, "../test/fixture-locals/canonical/terragrunt.hcl", nil) require.NoError(t, err) - tgConfigMap, err := parseCtyValueToMap(tgConfigCty) + tgConfigMap, err := config.ParseCtyValueToMap(tgConfigCty) require.NoError(t, err) localsMap := tgConfigMap["locals"].(map[string]interface{}) @@ -1001,8 +1022,8 @@ func TestReadTerragruntConfigLocals(t *testing.T) { func TestGetTerragruntSourceForModuleHappyPath(t *testing.T) { t.Parallel() - testCases := []struct { - config *TerragruntConfig + tc := []struct { + config *config.TerragruntConfig source string expected string }{ @@ -1018,14 +1039,16 @@ func TestGetTerragruntSourceForModuleHappyPath(t *testing.T) { {mockConfigWithSource("./some/path//to/modulename"), "/source/modules", "/source/modules//to/modulename"}, } - for _, testCase := range testCases { - // The following is necessary to make sure testCase's values don't + for _, tt := range tc { + // The following is necessary to make sure tt's values don't // get updated due to concurrency within the scope of t.Run(..) below - testCase := testCase - t.Run(fmt.Sprintf("%v-%s", *testCase.config.Terraform.Source, testCase.source), func(t *testing.T) { - actual, err := GetTerragruntSourceForModule(testCase.source, "mock-for-test", testCase.config) + tt := tt + t.Run(fmt.Sprintf("%v-%s", *tt.config.Terraform.Source, tt.source), func(t *testing.T) { + t.Parallel() + + actual, err := config.GetTerragruntSourceForModule(tt.source, "mock-for-test", tt.config) require.NoError(t, err) - assert.Equal(t, testCase.expected, actual) + assert.Equal(t, tt.expected, actual) }) } } @@ -1033,7 +1056,7 @@ func TestGetTerragruntSourceForModuleHappyPath(t *testing.T) { func TestStartsWith(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { config *options.TerragruntOptions args []string value bool @@ -1049,13 +1072,15 @@ func TestStartsWith(t *testing.T) { {terragruntOptionsForTest(t, ""), []string{" ", "hello"}, false}, } - for id, testCase := range testCases { - testCase := testCase - t.Run(fmt.Sprintf("%v %v", id, testCase.args), func(t *testing.T) { - ctx := NewParsingContext(context.Background(), testCase.config) - actual, err := startsWith(ctx, testCase.args) + for id, tt := range tc { + tt := tt + t.Run(fmt.Sprintf("%v %v", id, tt.args), func(t *testing.T) { + t.Parallel() + + ctx := config.NewParsingContext(context.Background(), tt.config) + actual, err := config.StartsWith(ctx, tt.args) require.NoError(t, err) - assert.Equal(t, testCase.value, actual) + assert.Equal(t, tt.value, actual) }) } } @@ -1063,7 +1088,7 @@ func TestStartsWith(t *testing.T) { func TestEndsWith(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { config *options.TerragruntOptions args []string value bool @@ -1079,13 +1104,16 @@ func TestEndsWith(t *testing.T) { {terragruntOptionsForTest(t, ""), []string{" ", "hello"}, false}, } - for id, testCase := range testCases { - testCase := testCase - t.Run(fmt.Sprintf("%v %v", id, testCase.args), func(t *testing.T) { - ctx := NewParsingContext(context.Background(), testCase.config) - actual, err := endsWith(ctx, testCase.args) + for id, tt := range tc { + tt := tt + + t.Run(fmt.Sprintf("%v %v", id, tt.args), func(t *testing.T) { + t.Parallel() + + ctx := config.NewParsingContext(context.Background(), tt.config) + actual, err := config.EndsWith(ctx, tt.args) require.NoError(t, err) - assert.Equal(t, testCase.value, actual) + assert.Equal(t, tt.value, actual) }) } } @@ -1093,7 +1121,7 @@ func TestEndsWith(t *testing.T) { func TestTimeCmp(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { config *options.TerragruntOptions args []string value int64 @@ -1109,21 +1137,21 @@ func TestTimeCmp(t *testing.T) { {terragruntOptionsForTest(t, ""), []string{"2017-11-22 00:00:00Z", "2017-11-22T00:00:00Z"}, 0, `could not parse first parameter "2017-11-22 00:00:00Z": not a valid RFC3339 timestamp: missing required time introducer 'T'`}, } - for _, testCase := range testCases { - testCase := testCase + for _, tt := range tc { + tt := tt - t.Run(fmt.Sprintf("TimeCmp(%#v, %#v)", testCase.args[0], testCase.args[1]), func(t *testing.T) { + t.Run(fmt.Sprintf("TimeCmp(%#v, %#v)", tt.args[0], tt.args[1]), func(t *testing.T) { t.Parallel() - ctx := NewParsingContext(context.Background(), testCase.config) - actual, err := timeCmp(ctx, testCase.args) - if testCase.err != "" { - require.EqualError(t, err, testCase.err) + ctx := config.NewParsingContext(context.Background(), tt.config) + actual, err := config.TimeCmp(ctx, tt.args) + if tt.err != "" { + require.EqualError(t, err, tt.err) } else { require.NoError(t, err) } - assert.Equal(t, testCase.value, actual) + assert.Equal(t, tt.value, actual) }) } } @@ -1131,7 +1159,7 @@ func TestTimeCmp(t *testing.T) { func TestStrContains(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { config *options.TerragruntOptions args []string value bool @@ -1146,21 +1174,21 @@ func TestStrContains(t *testing.T) { {terragruntOptionsForTest(t, ""), []string{}, false, "Empty string value is not allowed for parameter to the strcontains function"}, } - for _, testCase := range testCases { - testCase := testCase + for _, tt := range tc { + tt := tt - t.Run(fmt.Sprintf("StrContains %v", testCase.args), func(t *testing.T) { + t.Run(fmt.Sprintf("StrContains %v", tt.args), func(t *testing.T) { t.Parallel() - ctx := NewParsingContext(context.Background(), testCase.config) - actual, err := strContains(ctx, testCase.args) - if testCase.err != "" { - require.EqualError(t, err, testCase.err) + ctx := config.NewParsingContext(context.Background(), tt.config) + actual, err := config.StrContains(ctx, tt.args) + if tt.err != "" { + require.EqualError(t, err, tt.err) } else { require.NoError(t, err) } - assert.Equal(t, testCase.value, actual) + assert.Equal(t, tt.value, actual) }) } } @@ -1168,12 +1196,12 @@ func TestStrContains(t *testing.T) { func TestReadTFVarsFiles(t *testing.T) { t.Parallel() - options := terragruntOptionsForTest(t, DefaultTerragruntConfigPath) - ctx := NewParsingContext(context.Background(), options) - tgConfigCty, err := readTerragruntConfig(ctx, "../test/fixture-read-tf-vars/terragrunt.hcl", nil) + options := terragruntOptionsForTest(t, config.DefaultTerragruntConfigPath) + ctx := config.NewParsingContext(context.Background(), options) + tgConfigCty, err := config.ParseTerragruntConfig(ctx, "../test/fixture-read-tf-vars/terragrunt.hcl", nil) require.NoError(t, err) - tgConfigMap, err := parseCtyValueToMap(tgConfigCty) + tgConfigMap, err := config.ParseCtyValueToMap(tgConfigCty) require.NoError(t, err) locals := tgConfigMap["locals"].(map[string]interface{}) @@ -1188,9 +1216,9 @@ func TestReadTFVarsFiles(t *testing.T) { assert.False(t, locals["json_bool_var"].(bool)) } -func mockConfigWithSource(sourceUrl string) *TerragruntConfig { - cfg := TerragruntConfig{IsPartial: true} - cfg.Terraform = &TerraformConfig{Source: &sourceUrl} +func mockConfigWithSource(sourceUrl string) *config.TerragruntConfig { + cfg := config.TerragruntConfig{IsPartial: true} + cfg.Terraform = &config.TerraformConfig{Source: &sourceUrl} return &cfg } @@ -1203,17 +1231,17 @@ func getKeys(valueMap map[string]cty.Value) map[string]bool { return keys } -func getTrackIncludeFromTestData(includeMap map[string]IncludeConfig, params []string) *TrackInclude { +func getTrackIncludeFromTestData(includeMap map[string]config.IncludeConfig, params []string) *config.TrackInclude { if len(includeMap) == 0 { return nil } - currentList := make([]IncludeConfig, len(includeMap)) + currentList := make([]config.IncludeConfig, len(includeMap)) i := 0 for _, val := range includeMap { currentList[i] = val i++ } - trackInclude := &TrackInclude{ + trackInclude := &config.TrackInclude{ CurrentList: currentList, CurrentMap: includeMap, } diff --git a/config/config_partial.go b/config/config_partial.go index 443cfc118..c9695bb12 100644 --- a/config/config_partial.go +++ b/config/config_partial.go @@ -82,8 +82,8 @@ type terragruntVersionConstraints struct { Remain hcl.Body `hcl:",remain"` } -// terragruntDependency is a struct that can be used to only decode the dependency blocks in the terragrunt config -type terragruntDependency struct { +// TerragruntDependency is a struct that can be used to only decode the dependency blocks in the terragrunt config +type TerragruntDependency struct { Dependencies Dependencies `hcl:"dependency,block"` Remain hcl.Body `hcl:",remain"` } @@ -127,7 +127,7 @@ func DecodeBaseBlocks(ctx *ParsingContext, file *hclparse.File, includeFromChild // Evaluate all the expressions in the locals block separately and generate the variables list to use in the // evaluation ctx. - locals, err := evaluateLocalsBlock(ctx.WithTrackInclude(trackInclude), file) + locals, err := EvaluateLocalsBlock(ctx.WithTrackInclude(trackInclude), file) if err != nil { return nil, nil, err } @@ -279,7 +279,7 @@ func PartialParseConfig(ctx *ParsingContext, file *hclparse.File, includeFromChi } case DependencyBlock: - decoded := terragruntDependency{} + decoded := TerragruntDependency{} err := file.Decode(&decoded, evalParsingContext) if err != nil { return nil, err @@ -339,7 +339,7 @@ func PartialParseConfig(ctx *ParsingContext, file *hclparse.File, includeFromChi } if decoded.Inputs != nil { - inputs, err := parseCtyValueToMap(*decoded.Inputs) + inputs, err := ParseCtyValueToMap(*decoded.Inputs) if err != nil { return nil, err } diff --git a/config/config_partial_test.go b/config/config_partial_test.go index 1d70e7dcb..b039f409d 100644 --- a/config/config_partial_test.go +++ b/config/config_partial_test.go @@ -1,9 +1,10 @@ -package config +package config_test import ( "context" "testing" + "github.com/gruntwork-io/terragrunt/config" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/zclconf/go-cty/cty" @@ -12,7 +13,7 @@ import ( func TestPartialParseResolvesLocals(t *testing.T) { t.Parallel() - config := ` + cfg := ` locals { app1 = "../app1" } @@ -22,8 +23,8 @@ dependencies { } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(DependenciesBlock) - terragruntConfig, err := PartialParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(config.DependenciesBlock) + terragruntConfig, err := config.PartialParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) require.NoError(t, err) assert.True(t, terragruntConfig.IsPartial) @@ -42,7 +43,7 @@ dependencies { func TestPartialParseDoesNotResolveIgnoredBlock(t *testing.T) { t.Parallel() - config := ` + cfg := ` dependencies { # This function call will fail when attempting to decode paths = [file("i-am-a-file-that-does-not-exist")] @@ -51,18 +52,18 @@ dependencies { prevent_destroy = false ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - _, err := PartialParseConfigString(ctx.WithDecodeList(TerragruntFlags), DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + _, err := config.PartialParseConfigString(ctx.WithDecodeList(config.TerragruntFlags), config.DefaultTerragruntConfigPath, cfg, nil) require.NoError(t, err) - _, err = PartialParseConfigString(ctx.WithDecodeList(DependenciesBlock), DefaultTerragruntConfigPath, config, nil) + _, err = config.PartialParseConfigString(ctx.WithDecodeList(config.DependenciesBlock), config.DefaultTerragruntConfigPath, cfg, nil) assert.Error(t, err) } func TestPartialParseMultipleItems(t *testing.T) { t.Parallel() - config := ` + cfg := ` dependencies { paths = ["../app1"] } @@ -71,8 +72,8 @@ prevent_destroy = true skip = true ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(DependenciesBlock, TerragruntFlags) - terragruntConfig, err := PartialParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(config.DependenciesBlock, config.TerragruntFlags) + terragruntConfig, err := config.PartialParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) require.NoError(t, err) assert.True(t, terragruntConfig.IsPartial) @@ -92,8 +93,8 @@ skip = true func TestPartialParseOmittedItems(t *testing.T) { t.Parallel() - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(DependenciesBlock, TerragruntFlags) - terragruntConfig, err := PartialParseConfigString(ctx, DefaultTerragruntConfigPath, "", nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(config.DependenciesBlock, config.TerragruntFlags) + terragruntConfig, err := config.PartialParseConfigString(ctx, config.DefaultTerragruntConfigPath, "", nil) require.NoError(t, err) assert.True(t, terragruntConfig.IsPartial) @@ -109,23 +110,23 @@ func TestPartialParseOmittedItems(t *testing.T) { func TestPartialParseDoesNotResolveIgnoredBlockEvenInParent(t *testing.T) { t.Parallel() - opts := mockOptionsForTestWithConfigPath(t, "../test/fixture-partial-parse/ignore-bad-block-in-parent/child/"+DefaultTerragruntConfigPath) + opts := mockOptionsForTestWithConfigPath(t, "../test/fixture-partial-parse/ignore-bad-block-in-parent/child/"+config.DefaultTerragruntConfigPath) - ctx := NewParsingContext(context.Background(), opts) - _, err := PartialParseConfigFile(ctx.WithDecodeList(TerragruntFlags), opts.TerragruntConfigPath, nil) + ctx := config.NewParsingContext(context.Background(), opts) + _, err := config.PartialParseConfigFile(ctx.WithDecodeList(config.TerragruntFlags), opts.TerragruntConfigPath, nil) require.NoError(t, err) - _, err = PartialParseConfigFile(ctx.WithDecodeList(DependenciesBlock), opts.TerragruntConfigPath, nil) + _, err = config.PartialParseConfigFile(ctx.WithDecodeList(config.DependenciesBlock), opts.TerragruntConfigPath, nil) assert.Error(t, err) } func TestPartialParseOnlyInheritsSelectedBlocksFlags(t *testing.T) { t.Parallel() - opts := mockOptionsForTestWithConfigPath(t, "../test/fixture-partial-parse/partial-inheritance/child/"+DefaultTerragruntConfigPath) + opts := mockOptionsForTestWithConfigPath(t, "../test/fixture-partial-parse/partial-inheritance/child/"+config.DefaultTerragruntConfigPath) - ctx := NewParsingContext(context.Background(), opts).WithDecodeList(TerragruntFlags) - terragruntConfig, err := PartialParseConfigFile(ctx, opts.TerragruntConfigPath, nil) + ctx := config.NewParsingContext(context.Background(), opts).WithDecodeList(config.TerragruntFlags) + terragruntConfig, err := config.PartialParseConfigFile(ctx, opts.TerragruntConfigPath, nil) require.NoError(t, err) assert.True(t, terragruntConfig.IsPartial) @@ -141,10 +142,10 @@ func TestPartialParseOnlyInheritsSelectedBlocksFlags(t *testing.T) { func TestPartialParseOnlyInheritsSelectedBlocksDependencies(t *testing.T) { t.Parallel() - opts := mockOptionsForTestWithConfigPath(t, "../test/fixture-partial-parse/partial-inheritance/child/"+DefaultTerragruntConfigPath) + opts := mockOptionsForTestWithConfigPath(t, "../test/fixture-partial-parse/partial-inheritance/child/"+config.DefaultTerragruntConfigPath) - ctx := NewParsingContext(context.Background(), opts).WithDecodeList(DependenciesBlock) - terragruntConfig, err := PartialParseConfigFile(ctx, opts.TerragruntConfigPath, nil) + ctx := config.NewParsingContext(context.Background(), opts).WithDecodeList(config.DependenciesBlock) + terragruntConfig, err := config.PartialParseConfigFile(ctx, opts.TerragruntConfigPath, nil) require.NoError(t, err) assert.True(t, terragruntConfig.IsPartial) @@ -164,14 +165,14 @@ func TestPartialParseOnlyInheritsSelectedBlocksDependencies(t *testing.T) { func TestPartialParseDependencyBlockSetsTerragruntDependencies(t *testing.T) { t.Parallel() - config := ` + cfg := ` dependency "vpc" { config_path = "../app1" } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(DependencyBlock) - terragruntConfig, err := PartialParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(config.DependencyBlock) + terragruntConfig, err := config.PartialParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) require.NoError(t, err) assert.True(t, terragruntConfig.IsPartial) @@ -184,7 +185,7 @@ dependency "vpc" { func TestPartialParseMultipleDependencyBlockSetsTerragruntDependencies(t *testing.T) { t.Parallel() - config := ` + cfg := ` dependency "vpc" { config_path = "../app1" } @@ -194,8 +195,8 @@ dependency "sql" { } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(DependencyBlock) - terragruntConfig, err := PartialParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(config.DependencyBlock) + terragruntConfig, err := config.PartialParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) require.NoError(t, err) assert.True(t, terragruntConfig.IsPartial) @@ -210,7 +211,7 @@ dependency "sql" { func TestPartialParseDependencyBlockSetsDependencies(t *testing.T) { t.Parallel() - config := ` + cfg := ` dependency "vpc" { config_path = "../app1" } @@ -220,8 +221,8 @@ dependency "sql" { } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(DependencyBlock) - terragruntConfig, err := PartialParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(config.DependencyBlock) + terragruntConfig, err := config.PartialParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) require.NoError(t, err) assert.True(t, terragruntConfig.IsPartial) @@ -233,7 +234,7 @@ dependency "sql" { func TestPartialParseDependencyBlockMergesDependencies(t *testing.T) { t.Parallel() - config := ` + cfg := ` dependency "vpc" { config_path = "../app1" } @@ -247,8 +248,8 @@ dependency "sql" { } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(DependenciesBlock, DependencyBlock) - terragruntConfig, err := PartialParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(config.DependenciesBlock, config.DependencyBlock) + terragruntConfig, err := config.PartialParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) require.NoError(t, err) assert.True(t, terragruntConfig.IsPartial) @@ -260,7 +261,7 @@ dependency "sql" { func TestPartialParseDependencyBlockMergesDependenciesOrdering(t *testing.T) { t.Parallel() - config := ` + cfg := ` dependency "vpc" { config_path = "../app1" } @@ -274,8 +275,8 @@ dependency "sql" { } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(DependencyBlock, DependenciesBlock) - terragruntConfig, err := PartialParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(config.DependencyBlock, config.DependenciesBlock) + terragruntConfig, err := config.PartialParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) require.NoError(t, err) assert.True(t, terragruntConfig.IsPartial) @@ -287,7 +288,7 @@ dependency "sql" { func TestPartialParseDependencyBlockMergesDependenciesDedup(t *testing.T) { t.Parallel() - config := ` + cfg := ` dependency "vpc" { config_path = "../app1" } @@ -301,8 +302,8 @@ dependency "sql" { } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(DependencyBlock, DependenciesBlock) - terragruntConfig, err := PartialParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(config.DependencyBlock, config.DependenciesBlock) + terragruntConfig, err := config.PartialParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) require.NoError(t, err) assert.True(t, terragruntConfig.IsPartial) @@ -314,7 +315,7 @@ dependency "sql" { func TestPartialParseOnlyParsesTerraformSource(t *testing.T) { t.Parallel() - config := ` + cfg := ` dependency "vpc" { config_path = "../vpc" } @@ -328,8 +329,8 @@ terraform { } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(TerraformSource) - terragruntConfig, err := PartialParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(config.TerraformSource) + terragruntConfig, err := config.PartialParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) require.NoError(t, err) assert.True(t, terragruntConfig.IsPartial) @@ -341,7 +342,7 @@ terraform { func TestOptionalDependenciesAreSkipped(t *testing.T) { t.Parallel() - config := ` + cfg := ` dependency "vpc" { config_path = "../vpc" } @@ -351,8 +352,8 @@ dependency "ec2" { } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(DependencyBlock) - terragruntConfig, err := PartialParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)).WithDecodeList(config.DependencyBlock) + terragruntConfig, err := config.PartialParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) require.NoError(t, err) assert.Len(t, terragruntConfig.Dependencies.Paths, 1) } diff --git a/config/config_test.go b/config/config_test.go index 04bc65731..d4eec5960 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -1,4 +1,4 @@ -package config +package config_test import ( "context" @@ -8,6 +8,7 @@ import ( "testing" "github.com/gruntwork-io/go-commons/errors" + "github.com/gruntwork-io/terragrunt/config" "github.com/gruntwork-io/terragrunt/options" "github.com/gruntwork-io/terragrunt/util" "github.com/stretchr/testify/assert" @@ -17,15 +18,15 @@ import ( func TestParseTerragruntConfigRemoteStateMinimalConfig(t *testing.T) { t.Parallel() - config := ` + cfg := ` remote_state { backend = "s3" config = {} } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) require.NoError(t, err) assert.Nil(t, terragruntConfig.Terraform) @@ -41,15 +42,15 @@ remote_state { func TestParseTerragruntConfigRemoteStateAttrMinimalConfig(t *testing.T) { t.Parallel() - config := ` + cfg := ` remote_state = { backend = "s3" config = {} } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) require.NoError(t, err) assert.Nil(t, terragruntConfig.Terraform) @@ -65,7 +66,7 @@ remote_state = { func TestParseTerragruntJsonConfigRemoteStateMinimalConfig(t *testing.T) { t.Parallel() - config := ` + cfg := ` { "remote_state": { "backend": "s3", @@ -74,8 +75,8 @@ func TestParseTerragruntJsonConfigRemoteStateMinimalConfig(t *testing.T) { } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntJsonConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntJsonConfigPath, cfg, nil) require.NoError(t, err) assert.Nil(t, terragruntConfig.Terraform) @@ -91,12 +92,12 @@ func TestParseTerragruntJsonConfigRemoteStateMinimalConfig(t *testing.T) { func TestParseTerragruntHclConfigRemoteStateMissingBackend(t *testing.T) { t.Parallel() - config := ` + cfg := ` remote_state {} ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - _, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + _, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) require.Error(t, err) assert.Contains(t, err.Error(), "Missing required argument; The argument \"backend\" is required") } @@ -104,7 +105,7 @@ remote_state {} func TestParseTerragruntHclConfigRemoteStateFullConfig(t *testing.T) { t.Parallel() - config := ` + cfg := ` remote_state { backend = "s3" config = { @@ -116,8 +117,8 @@ remote_state { } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) if err != nil { t.Fatal(err) } @@ -139,7 +140,7 @@ remote_state { func TestParseTerragruntJsonConfigRemoteStateFullConfig(t *testing.T) { t.Parallel() - config := ` + cfg := ` { "remote_state":{ "backend":"s3", @@ -152,8 +153,8 @@ func TestParseTerragruntJsonConfigRemoteStateFullConfig(t *testing.T) { } } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntJsonConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntJsonConfigPath, cfg, nil) if err != nil { t.Fatal(err) } @@ -175,7 +176,7 @@ func TestParseTerragruntJsonConfigRemoteStateFullConfig(t *testing.T) { func TestParseTerragruntHclConfigRetryConfiguration(t *testing.T) { t.Parallel() - config := ` + cfg := ` retry_max_attempts = 10 retry_sleep_interval_sec = 60 retryable_errors = [ @@ -183,8 +184,8 @@ retryable_errors = [ "Another one of my errors" ] ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) require.NoError(t, err) assert.Nil(t, terragruntConfig.Terraform) @@ -201,7 +202,7 @@ retryable_errors = [ func TestParseTerragruntJsonConfigRetryConfiguration(t *testing.T) { t.Parallel() - config := ` + cfg := ` { "retry_max_attempts": 10, "retry_sleep_interval_sec": 60, @@ -211,8 +212,8 @@ func TestParseTerragruntJsonConfigRetryConfiguration(t *testing.T) { } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntJsonConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntJsonConfigPath, cfg, nil) require.NoError(t, err) assert.Nil(t, terragruntConfig.Terraform) @@ -229,10 +230,10 @@ func TestParseTerragruntJsonConfigRetryConfiguration(t *testing.T) { func TestParseIamRole(t *testing.T) { t.Parallel() - config := `iam_role = "terragrunt-iam-role"` + cfg := `iam_role = "terragrunt-iam-role"` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) if err != nil { t.Fatal(err) } @@ -248,10 +249,10 @@ func TestParseIamRole(t *testing.T) { func TestParseIamAssumeRoleDuration(t *testing.T) { t.Parallel() - config := `iam_assume_role_duration = 36000` + cfg := `iam_assume_role_duration = 36000` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) if err != nil { t.Fatal(err) } @@ -267,10 +268,10 @@ func TestParseIamAssumeRoleDuration(t *testing.T) { func TestParseIamAssumeRoleSessionName(t *testing.T) { t.Parallel() - config := `iam_assume_role_session_name = "terragrunt-iam-assume-role-session-name"` + cfg := `iam_assume_role_session_name = "terragrunt-iam-assume-role-session-name"` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) if err != nil { t.Fatal(err) } @@ -287,10 +288,10 @@ func TestParseIamWebIdentity(t *testing.T) { t.Parallel() token := "test-token" - config := fmt.Sprintf(`iam_web_identity_token = "%s"`, token) + cfg := fmt.Sprintf(`iam_web_identity_token = "%s"`, token) - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) if err != nil { t.Fatal(err) } @@ -305,14 +306,14 @@ func TestParseIamWebIdentity(t *testing.T) { func TestParseTerragruntConfigDependenciesOnePath(t *testing.T) { t.Parallel() - config := ` + cfg := ` dependencies { paths = ["../test/fixture-parent-folders/multiple-terragrunt-in-parents"] } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) if err != nil { t.Fatal(err) } @@ -331,14 +332,14 @@ dependencies { func TestParseTerragruntConfigDependenciesMultiplePaths(t *testing.T) { t.Parallel() - config := ` + cfg := ` dependencies { paths = ["../test/fixture", "../test/fixture-dirs", "../test/fixture-inputs"] } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) if err != nil { t.Fatal(err) } @@ -356,7 +357,7 @@ dependencies { func TestParseTerragruntConfigRemoteStateDynamoDbTerraformConfigAndDependenciesFullConfig(t *testing.T) { t.Parallel() - config := ` + cfg := ` terraform { source = "foo" } @@ -376,8 +377,8 @@ dependencies { } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) if err != nil { t.Fatal(err) } @@ -405,7 +406,7 @@ dependencies { func TestParseTerragruntJsonConfigRemoteStateDynamoDbTerraformConfigAndDependenciesFullConfig(t *testing.T) { t.Parallel() - config := ` + cfg := ` { "terraform": { "source": "foo" @@ -425,8 +426,8 @@ func TestParseTerragruntJsonConfigRemoteStateDynamoDbTerraformConfigAndDependenc } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntJsonConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntJsonConfigPath, cfg, nil) if err != nil { t.Fatal(err) } @@ -454,21 +455,21 @@ func TestParseTerragruntJsonConfigRemoteStateDynamoDbTerraformConfigAndDependenc func TestParseTerragruntConfigInclude(t *testing.T) { t.Parallel() - config := + cfg := fmt.Sprintf(` include { path = "../../../%s" } -`, DefaultTerragruntConfigPath) +`, config.DefaultTerragruntConfigPath) opts := &options.TerragruntOptions{ - TerragruntConfigPath: "../test/fixture-parent-folders/terragrunt-in-root/child/sub-child/sub-sub-child/" + DefaultTerragruntConfigPath, + TerragruntConfigPath: "../test/fixture-parent-folders/terragrunt-in-root/child/sub-child/sub-sub-child/" + config.DefaultTerragruntConfigPath, NonInteractive: true, Logger: util.CreateLogEntry("", util.GetDefaultLogLevel()), } - ctx := NewParsingContext(context.Background(), opts) - terragruntConfig, err := ParseConfigString(ctx, opts.TerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), opts) + terragruntConfig, err := config.ParseConfigString(ctx, opts.TerragruntConfigPath, cfg, nil) if assert.NoError(t, err, "Unexpected error: %v", errors.PrintErrorWithStackTrace(err)) { assert.Nil(t, terragruntConfig.Terraform) @@ -487,16 +488,16 @@ include { func TestParseTerragruntConfigIncludeWithFindInParentFolders(t *testing.T) { t.Parallel() - config := ` + cfg := ` include { path = find_in_parent_folders() } ` - opts := mockOptionsForTestWithConfigPath(t, "../test/fixture-parent-folders/terragrunt-in-root/child/sub-child/sub-sub-child/"+DefaultTerragruntConfigPath) + opts := mockOptionsForTestWithConfigPath(t, "../test/fixture-parent-folders/terragrunt-in-root/child/sub-child/sub-sub-child/"+config.DefaultTerragruntConfigPath) - ctx := NewParsingContext(context.Background(), opts) - terragruntConfig, err := ParseConfigString(ctx, opts.TerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), opts) + terragruntConfig, err := config.ParseConfigString(ctx, opts.TerragruntConfigPath, cfg, nil) if assert.NoError(t, err, "Unexpected error: %v", errors.PrintErrorWithStackTrace(err)) { assert.Nil(t, terragruntConfig.Terraform) @@ -515,7 +516,7 @@ include { func TestParseTerragruntConfigIncludeOverrideRemote(t *testing.T) { t.Parallel() - config := + cfg := fmt.Sprintf(` include { path = "../../../%s" @@ -531,12 +532,12 @@ remote_state { region = "override" } } -`, DefaultTerragruntConfigPath) +`, config.DefaultTerragruntConfigPath) - opts := mockOptionsForTestWithConfigPath(t, "../test/fixture-parent-folders/terragrunt-in-root/child/sub-child/sub-sub-child/"+DefaultTerragruntConfigPath) + opts := mockOptionsForTestWithConfigPath(t, "../test/fixture-parent-folders/terragrunt-in-root/child/sub-child/sub-sub-child/"+config.DefaultTerragruntConfigPath) - ctx := NewParsingContext(context.Background(), opts) - terragruntConfig, err := ParseConfigString(ctx, opts.TerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), opts) + terragruntConfig, err := config.ParseConfigString(ctx, opts.TerragruntConfigPath, cfg, nil) if assert.NoError(t, err, "Unexpected error: %v", errors.PrintErrorWithStackTrace(err)) { assert.Nil(t, terragruntConfig.Terraform) @@ -555,7 +556,7 @@ remote_state { func TestParseTerragruntConfigIncludeOverrideAll(t *testing.T) { t.Parallel() - config := + cfg := fmt.Sprintf(` include { path = "../../../%s" @@ -579,12 +580,12 @@ remote_state { dependencies { paths = ["override"] } -`, DefaultTerragruntConfigPath) +`, config.DefaultTerragruntConfigPath) - opts := mockOptionsForTestWithConfigPath(t, "../test/fixture-parent-folders/terragrunt-in-root/child/sub-child/sub-sub-child/"+DefaultTerragruntConfigPath) + opts := mockOptionsForTestWithConfigPath(t, "../test/fixture-parent-folders/terragrunt-in-root/child/sub-child/sub-sub-child/"+config.DefaultTerragruntConfigPath) - ctx := NewParsingContext(context.Background(), opts) - terragruntConfig, err := ParseConfigString(ctx, opts.TerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), opts) + terragruntConfig, err := config.ParseConfigString(ctx, opts.TerragruntConfigPath, cfg, nil) require.NoError(t, err, "Unexpected error: %v", errors.PrintErrorWithStackTrace(err)) assert.NotNil(t, terragruntConfig.Terraform) @@ -606,7 +607,7 @@ dependencies { func TestParseTerragruntJsonConfigIncludeOverrideAll(t *testing.T) { t.Parallel() - config := + cfg := fmt.Sprintf(` { "include":{ @@ -628,12 +629,12 @@ func TestParseTerragruntJsonConfigIncludeOverrideAll(t *testing.T) { "paths": ["override"] } } -`, DefaultTerragruntConfigPath) +`, config.DefaultTerragruntConfigPath) - opts := mockOptionsForTestWithConfigPath(t, "../test/fixture-parent-folders/terragrunt-in-root/child/sub-child/sub-sub-child/"+DefaultTerragruntJsonConfigPath) + opts := mockOptionsForTestWithConfigPath(t, "../test/fixture-parent-folders/terragrunt-in-root/child/sub-child/sub-sub-child/"+config.DefaultTerragruntJsonConfigPath) - ctx := NewParsingContext(context.Background(), opts) - terragruntConfig, err := ParseConfigString(ctx, opts.TerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), opts) + terragruntConfig, err := config.ParseConfigString(ctx, opts.TerragruntConfigPath, cfg, nil) require.NoError(t, err, "Unexpected error: %v", errors.PrintErrorWithStackTrace(err)) assert.NotNil(t, terragruntConfig.Terraform) @@ -655,21 +656,21 @@ func TestParseTerragruntJsonConfigIncludeOverrideAll(t *testing.T) { func TestParseTerragruntConfigTwoLevels(t *testing.T) { t.Parallel() - configPath := "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/sub-child/" + DefaultTerragruntConfigPath + configPath := "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/sub-child/" + config.DefaultTerragruntConfigPath - config, err := util.ReadFileAsString(configPath) + cfg, err := util.ReadFileAsString(configPath) if err != nil { t.Fatal(err) } opts := mockOptionsForTestWithConfigPath(t, configPath) - ctx := NewParsingContext(context.Background(), opts) - _, actualErr := ParseConfigString(ctx, configPath, config, nil) - expectedErr := TooManyLevelsOfInheritanceError{ + ctx := config.NewParsingContext(context.Background(), opts) + _, actualErr := config.ParseConfigString(ctx, configPath, cfg, nil) + expectedErr := config.TooManyLevelsOfInheritanceError{ ConfigPath: configPath, - FirstLevelIncludePath: filepath.ToSlash(absPath(t, "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/"+DefaultTerragruntConfigPath)), - SecondLevelIncludePath: filepath.ToSlash(absPath(t, "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/"+DefaultTerragruntConfigPath)), + FirstLevelIncludePath: filepath.ToSlash(absPath(t, "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/"+config.DefaultTerragruntConfigPath)), + SecondLevelIncludePath: filepath.ToSlash(absPath(t, "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/"+config.DefaultTerragruntConfigPath)), } assert.True(t, errors.IsError(actualErr, expectedErr), "Expected error %v but got %v", expectedErr, actualErr) } @@ -677,21 +678,21 @@ func TestParseTerragruntConfigTwoLevels(t *testing.T) { func TestParseTerragruntConfigThreeLevels(t *testing.T) { t.Parallel() - configPath := "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/sub-child/sub-sub-child/" + DefaultTerragruntConfigPath + configPath := "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/sub-child/sub-sub-child/" + config.DefaultTerragruntConfigPath - config, err := util.ReadFileAsString(configPath) + cfg, err := util.ReadFileAsString(configPath) if err != nil { t.Fatal(err) } opts := mockOptionsForTestWithConfigPath(t, configPath) - ctx := NewParsingContext(context.Background(), opts) - _, actualErr := ParseConfigString(ctx, configPath, config, nil) - expectedErr := TooManyLevelsOfInheritanceError{ + ctx := config.NewParsingContext(context.Background(), opts) + _, actualErr := config.ParseConfigString(ctx, configPath, cfg, nil) + expectedErr := config.TooManyLevelsOfInheritanceError{ ConfigPath: configPath, - FirstLevelIncludePath: absPath(t, "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/sub-child/"+DefaultTerragruntConfigPath), - SecondLevelIncludePath: absPath(t, "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/sub-child/"+DefaultTerragruntConfigPath), + FirstLevelIncludePath: absPath(t, "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/sub-child/"+config.DefaultTerragruntConfigPath), + SecondLevelIncludePath: absPath(t, "../test/fixture-parent-folders/multiple-terragrunt-in-parents/child/sub-child/"+config.DefaultTerragruntConfigPath), } assert.True(t, errors.IsError(actualErr, expectedErr), "Expected error %v but got %v", expectedErr, actualErr) } @@ -699,47 +700,47 @@ func TestParseTerragruntConfigThreeLevels(t *testing.T) { func TestParseTerragruntConfigEmptyConfig(t *testing.T) { t.Parallel() - config := `` + cfg := `` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - cfg, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) require.NoError(t, err) - assert.Nil(t, cfg.Terraform) - assert.Nil(t, cfg.RemoteState) - assert.Nil(t, cfg.Dependencies) - assert.Nil(t, cfg.PreventDestroy) - assert.False(t, cfg.Skip) - assert.Empty(t, cfg.IamRole) - assert.Empty(t, cfg.IamWebIdentityToken) - assert.Nil(t, cfg.RetryMaxAttempts) - assert.Nil(t, cfg.RetrySleepIntervalSec) - assert.Nil(t, cfg.RetryableErrors) + assert.Nil(t, terragruntConfig.Terraform) + assert.Nil(t, terragruntConfig.RemoteState) + assert.Nil(t, terragruntConfig.Dependencies) + assert.Nil(t, terragruntConfig.PreventDestroy) + assert.False(t, terragruntConfig.Skip) + assert.Empty(t, terragruntConfig.IamRole) + assert.Empty(t, terragruntConfig.IamWebIdentityToken) + assert.Nil(t, terragruntConfig.RetryMaxAttempts) + assert.Nil(t, terragruntConfig.RetrySleepIntervalSec) + assert.Nil(t, terragruntConfig.RetryableErrors) } func TestParseTerragruntConfigEmptyConfigOldConfig(t *testing.T) { t.Parallel() - config := `` + cfgString := `` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + cfg, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfgString, nil) if err != nil { t.Fatal(err) } - assert.Nil(t, terragruntConfig.RemoteState) + assert.Nil(t, cfg.RemoteState) } func TestParseTerragruntConfigTerraformNoSource(t *testing.T) { t.Parallel() - config := ` + cfg := ` terraform {} ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) if err != nil { t.Fatal(err) } @@ -754,14 +755,14 @@ terraform {} func TestParseTerragruntConfigTerraformWithSource(t *testing.T) { t.Parallel() - config := ` + cfg := ` terraform { source = "foo" } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) if err != nil { t.Fatal(err) } @@ -777,7 +778,7 @@ terraform { func TestParseTerragruntConfigTerraformWithExtraArguments(t *testing.T) { t.Parallel() - config := ` + cfg := ` terraform { extra_arguments "secrets" { arguments = [ @@ -792,8 +793,8 @@ terraform { } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) if err != nil { t.Fatal(err) } @@ -810,7 +811,7 @@ terraform { }, terragruntConfig.Terraform.ExtraArgs[0].Arguments) assert.Equal(t, - TERRAFORM_COMMANDS_NEED_VARS, + config.TERRAFORM_COMMANDS_NEED_VARS, terragruntConfig.Terraform.ExtraArgs[0].Commands) assert.Equal(t, @@ -822,7 +823,7 @@ terraform { func TestParseTerragruntConfigTerraformWithMultipleExtraArguments(t *testing.T) { t.Parallel() - config := ` + cfg := ` terraform { extra_arguments "json_output" { arguments = ["-json"] @@ -852,8 +853,8 @@ terraform { } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) require.NoError(t, err) assert.Nil(t, terragruntConfig.RemoteState) @@ -868,17 +869,17 @@ terraform { assert.Equal(t, []string{"fmt"}, terragruntConfig.Terraform.ExtraArgs[1].Commands) assert.Equal(t, "required_tfvars", terragruntConfig.Terraform.ExtraArgs[2].Name) assert.Equal(t, &[]string{"file1.tfvars", "file2.tfvars"}, terragruntConfig.Terraform.ExtraArgs[2].RequiredVarFiles) - assert.Equal(t, TERRAFORM_COMMANDS_NEED_VARS, terragruntConfig.Terraform.ExtraArgs[2].Commands) + assert.Equal(t, config.TERRAFORM_COMMANDS_NEED_VARS, terragruntConfig.Terraform.ExtraArgs[2].Commands) assert.Equal(t, "optional_tfvars", terragruntConfig.Terraform.ExtraArgs[3].Name) assert.Equal(t, &[]string{"opt1.tfvars", "opt2.tfvars"}, terragruntConfig.Terraform.ExtraArgs[3].OptionalVarFiles) - assert.Equal(t, TERRAFORM_COMMANDS_NEED_VARS, terragruntConfig.Terraform.ExtraArgs[3].Commands) + assert.Equal(t, config.TERRAFORM_COMMANDS_NEED_VARS, terragruntConfig.Terraform.ExtraArgs[3].Commands) } } func TestParseTerragruntJsonConfigTerraformWithMultipleExtraArguments(t *testing.T) { t.Parallel() - config := ` + cfg := ` { "terraform":{ "extra_arguments":{ @@ -909,8 +910,8 @@ func TestParseTerragruntJsonConfigTerraformWithMultipleExtraArguments(t *testing } ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntJsonConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntJsonConfigPath, cfg, nil) require.NoError(t, err) assert.Nil(t, terragruntConfig.RemoteState) @@ -925,10 +926,10 @@ func TestParseTerragruntJsonConfigTerraformWithMultipleExtraArguments(t *testing assert.Equal(t, []string{"fmt"}, terragruntConfig.Terraform.ExtraArgs[1].Commands) assert.Equal(t, "required_tfvars", terragruntConfig.Terraform.ExtraArgs[2].Name) assert.Equal(t, &[]string{"file1.tfvars", "file2.tfvars"}, terragruntConfig.Terraform.ExtraArgs[2].RequiredVarFiles) - assert.Equal(t, TERRAFORM_COMMANDS_NEED_VARS, terragruntConfig.Terraform.ExtraArgs[2].Commands) + assert.Equal(t, config.TERRAFORM_COMMANDS_NEED_VARS, terragruntConfig.Terraform.ExtraArgs[2].Commands) assert.Equal(t, "optional_tfvars", terragruntConfig.Terraform.ExtraArgs[3].Name) assert.Equal(t, &[]string{"opt1.tfvars", "opt2.tfvars"}, terragruntConfig.Terraform.ExtraArgs[3].OptionalVarFiles) - assert.Equal(t, TERRAFORM_COMMANDS_NEED_VARS, terragruntConfig.Terraform.ExtraArgs[3].Commands) + assert.Equal(t, config.TERRAFORM_COMMANDS_NEED_VARS, terragruntConfig.Terraform.ExtraArgs[3].Commands) } } @@ -939,7 +940,7 @@ func TestFindConfigFilesInPathNone(t *testing.T) { terragruntOptions, err := options.NewTerragruntOptionsForTest("test") require.NoError(t, err) - actual, err := FindConfigFilesInPath("../test/fixture-config-files/none", terragruntOptions) + actual, err := config.FindConfigFilesInPath("../test/fixture-config-files/none", terragruntOptions) require.NoError(t, err, "Unexpected error: %v", err) assert.Equal(t, expected, actual) @@ -952,7 +953,7 @@ func TestFindConfigFilesInPathOneConfig(t *testing.T) { terragruntOptions, err := options.NewTerragruntOptionsForTest("test") require.NoError(t, err) - actual, err := FindConfigFilesInPath("../test/fixture-config-files/one-config", terragruntOptions) + actual, err := config.FindConfigFilesInPath("../test/fixture-config-files/one-config", terragruntOptions) require.NoError(t, err, "Unexpected error: %v", err) assert.Equal(t, expected, actual) @@ -965,7 +966,7 @@ func TestFindConfigFilesInPathOneJsonConfig(t *testing.T) { terragruntOptions, err := options.NewTerragruntOptionsForTest("test") require.NoError(t, err) - actual, err := FindConfigFilesInPath("../test/fixture-config-files/one-json-config", terragruntOptions) + actual, err := config.FindConfigFilesInPath("../test/fixture-config-files/one-json-config", terragruntOptions) require.NoError(t, err, "Unexpected error: %v", err) assert.Equal(t, expected, actual) @@ -982,7 +983,7 @@ func TestFindConfigFilesInPathMultipleConfigs(t *testing.T) { terragruntOptions, err := options.NewTerragruntOptionsForTest("test") require.NoError(t, err) - actual, err := FindConfigFilesInPath("../test/fixture-config-files/multiple-configs", terragruntOptions) + actual, err := config.FindConfigFilesInPath("../test/fixture-config-files/multiple-configs", terragruntOptions) require.NoError(t, err, "Unexpected error: %v", err) assert.ElementsMatch(t, expected, actual) @@ -999,7 +1000,7 @@ func TestFindConfigFilesInPathMultipleJsonConfigs(t *testing.T) { terragruntOptions, err := options.NewTerragruntOptionsForTest("test") require.NoError(t, err) - actual, err := FindConfigFilesInPath("../test/fixture-config-files/multiple-json-configs", terragruntOptions) + actual, err := config.FindConfigFilesInPath("../test/fixture-config-files/multiple-json-configs", terragruntOptions) require.NoError(t, err, "Unexpected error: %v", err) assert.ElementsMatch(t, expected, actual) @@ -1016,7 +1017,7 @@ func TestFindConfigFilesInPathMultipleMixedConfigs(t *testing.T) { terragruntOptions, err := options.NewTerragruntOptionsForTest("test") require.NoError(t, err) - actual, err := FindConfigFilesInPath("../test/fixture-config-files/multiple-mixed-configs", terragruntOptions) + actual, err := config.FindConfigFilesInPath("../test/fixture-config-files/multiple-mixed-configs", terragruntOptions) require.NoError(t, err, "Unexpected error: %v", err) assert.ElementsMatch(t, expected, actual) @@ -1031,7 +1032,7 @@ func TestFindConfigFilesIgnoresTerragruntCache(t *testing.T) { terragruntOptions, err := options.NewTerragruntOptionsForTest("test") require.NoError(t, err) - actual, err := FindConfigFilesInPath("../test/fixture-config-files/ignore-cached-config", terragruntOptions) + actual, err := config.FindConfigFilesInPath("../test/fixture-config-files/ignore-cached-config", terragruntOptions) require.NoError(t, err, "Unexpected error: %v", err) assert.Equal(t, expected, actual) @@ -1049,7 +1050,7 @@ func TestFindConfigFilesIgnoresTerraformDataDir(t *testing.T) { terragruntOptions, err := options.NewTerragruntOptionsForTest("test") require.NoError(t, err) - actual, err := FindConfigFilesInPath("../test/fixture-config-files/ignore-terraform-data-dir", terragruntOptions) + actual, err := config.FindConfigFilesInPath("../test/fixture-config-files/ignore-terraform-data-dir", terragruntOptions) require.NoError(t, err, "Unexpected error: %v", err) assert.ElementsMatch(t, expected, actual) @@ -1067,7 +1068,7 @@ func TestFindConfigFilesIgnoresTerraformDataDirEnv(t *testing.T) { require.NoError(t, err) terragruntOptions.Env["TF_DATA_DIR"] = ".tf_data" - actual, err := FindConfigFilesInPath("../test/fixture-config-files/ignore-terraform-data-dir", terragruntOptions) + actual, err := config.FindConfigFilesInPath("../test/fixture-config-files/ignore-terraform-data-dir", terragruntOptions) require.NoError(t, err, "Unexpected error: %v", err) assert.ElementsMatch(t, expected, actual) @@ -1086,7 +1087,7 @@ func TestFindConfigFilesIgnoresTerraformDataDirEnvPath(t *testing.T) { require.NoError(t, err) terragruntOptions.Env["TF_DATA_DIR"] = "subdir/.tf_data" - actual, err := FindConfigFilesInPath("../test/fixture-config-files/ignore-terraform-data-dir", terragruntOptions) + actual, err := config.FindConfigFilesInPath("../test/fixture-config-files/ignore-terraform-data-dir", terragruntOptions) require.NoError(t, err, "Unexpected error: %v", err) assert.ElementsMatch(t, expected, actual) @@ -1109,7 +1110,7 @@ func TestFindConfigFilesIgnoresTerraformDataDirEnvRoot(t *testing.T) { require.NoError(t, err) terragruntOptions.Env["TF_DATA_DIR"] = filepath.Join(workingDir, ".tf_data") - actual, err := FindConfigFilesInPath(workingDir, terragruntOptions) + actual, err := config.FindConfigFilesInPath(workingDir, terragruntOptions) require.NoError(t, err, "Unexpected error: %v", err) assert.ElementsMatch(t, expected, actual) @@ -1126,7 +1127,7 @@ func TestFindConfigFilesIgnoresDownloadDir(t *testing.T) { require.NoError(t, err) terragruntOptions.DownloadDir = "../test/fixture-config-files/multiple-configs/subdir-2" - actual, err := FindConfigFilesInPath("../test/fixture-config-files/multiple-configs", terragruntOptions) + actual, err := config.FindConfigFilesInPath("../test/fixture-config-files/multiple-configs", terragruntOptions) require.NoError(t, err, "Unexpected error: %v", err) assert.ElementsMatch(t, expected, actual) @@ -1147,12 +1148,12 @@ func mockOptionsForTest(t *testing.T) *options.TerragruntOptions { func TestParseTerragruntConfigPreventDestroyTrue(t *testing.T) { t.Parallel() - config := ` + cfg := ` prevent_destroy = true ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) if err != nil { t.Fatal(err) } @@ -1166,12 +1167,12 @@ prevent_destroy = true func TestParseTerragruntConfigPreventDestroyFalse(t *testing.T) { t.Parallel() - config := ` + cfg := ` prevent_destroy = false ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) if err != nil { t.Fatal(err) } @@ -1185,12 +1186,12 @@ prevent_destroy = false func TestParseTerragruntConfigSkipTrue(t *testing.T) { t.Parallel() - config := ` + cfg := ` skip = true ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) if err != nil { t.Fatal(err) } @@ -1204,12 +1205,12 @@ skip = true func TestParseTerragruntConfigSkipFalse(t *testing.T) { t.Parallel() - config := ` + cfg := ` skip = false ` - ctx := NewParsingContext(context.Background(), mockOptionsForTest(t)) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTest(t)) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) if err != nil { t.Fatal(err) } @@ -1221,7 +1222,9 @@ skip = false } func TestIncludeFunctionsWorkInChildConfig(t *testing.T) { - config := ` + t.Parallel() + + cfg := ` include { path = find_in_parent_folders() } @@ -1230,14 +1233,14 @@ terraform { } ` opts := &options.TerragruntOptions{ - TerragruntConfigPath: "../test/fixture-parent-folders/terragrunt-in-root/child/" + DefaultTerragruntConfigPath, + TerragruntConfigPath: "../test/fixture-parent-folders/terragrunt-in-root/child/" + config.DefaultTerragruntConfigPath, NonInteractive: true, MaxFoldersToCheck: 5, Logger: util.CreateLogEntry("", util.GetDefaultLogLevel()), } - ctx := NewParsingContext(context.Background(), opts) - terragruntConfig, err := ParseConfigString(ctx, DefaultTerragruntConfigPath, config, nil) + ctx := config.NewParsingContext(context.Background(), opts) + terragruntConfig, err := config.ParseConfigString(ctx, config.DefaultTerragruntConfigPath, cfg, nil) if err != nil { t.Fatal(err) } @@ -1246,6 +1249,8 @@ terraform { } func TestModuleDependenciesMerge(t *testing.T) { + t.Parallel() + testCases := []struct { name string target []string @@ -1304,11 +1309,11 @@ func TestModuleDependenciesMerge(t *testing.T) { t.Run(testCase.name, func(t *testing.T) { t.Parallel() - target := &ModuleDependencies{Paths: testCase.target} + target := &config.ModuleDependencies{Paths: testCase.target} - var source *ModuleDependencies = nil + var source *config.ModuleDependencies = nil if testCase.source != nil { - source = &ModuleDependencies{Paths: testCase.source} + source = &config.ModuleDependencies{Paths: testCase.source} } target.Merge(source) @@ -1356,7 +1361,7 @@ func BenchmarkReadTerragruntConfig(b *testing.B) { b.ResetTimer() b.StartTimer() - actual, err := ReadTerragruntConfig(context.Background(), terragruntOptions, DefaultParserOptions(terragruntOptions)) + actual, err := config.ReadTerragruntConfig(context.Background(), terragruntOptions, config.DefaultParserOptions(terragruntOptions)) b.StopTimer() require.NoError(b, err) assert.NotNil(b, actual) diff --git a/config/cty_helpers.go b/config/cty_helpers.go index a10c975c9..b9d11b857 100644 --- a/config/cty_helpers.go +++ b/config/cty_helpers.go @@ -159,11 +159,11 @@ func ctySliceToStringSlice(args []cty.Value) ([]string, error) { // shallowMergeCtyMaps performs a shallow merge of two cty value objects. func shallowMergeCtyMaps(target cty.Value, source cty.Value) (*cty.Value, error) { - outMap, err := parseCtyValueToMap(target) + outMap, err := ParseCtyValueToMap(target) if err != nil { return nil, err } - SourceMap, err := parseCtyValueToMap(source) + SourceMap, err := ParseCtyValueToMap(source) if err != nil { return nil, err } @@ -190,11 +190,11 @@ func deepMergeCtyMaps(target cty.Value, source cty.Value) (*cty.Value, error) { // are already maps or objects in HCL land. func deepMergeCtyMapsMapOnly(target cty.Value, source cty.Value, opts ...func(*mergo.Config)) (*cty.Value, error) { outMap := make(map[string]interface{}) - targetMap, err := parseCtyValueToMap(target) + targetMap, err := ParseCtyValueToMap(target) if err != nil { return nil, err } - sourceMap, err := parseCtyValueToMap(source) + sourceMap, err := ParseCtyValueToMap(source) if err != nil { return nil, err } @@ -219,8 +219,8 @@ func deepMergeCtyMapsMapOnly(target cty.Value, source cty.Value, opts ...func(*m // requires you to specify all the output types and will error out when it hits interface{}. So, as an ugly workaround, // we convert the given value to JSON using cty's JSON library and then convert the JSON back to a // map[string]interface{} using the Go json library. -func parseCtyValueToMap(value cty.Value) (map[string]interface{}, error) { - updatedValue, err := updateUnknownCtyValValues(value) +func ParseCtyValueToMap(value cty.Value) (map[string]interface{}, error) { + updatedValue, err := UpdateUnknownCtyValValues(value) if err != nil { return nil, err } @@ -319,8 +319,8 @@ func includeConfigAsCtyVal(ctx *ParsingContext, includeConfig IncludeConfig) (ct return cty.NilVal, nil } -// updateUnknownCtyValValues deeply updates unknown values with default value -func updateUnknownCtyValValues(value cty.Value) (cty.Value, error) { +// UpdateUnknownCtyValValues deeply updates unknown values with default value +func UpdateUnknownCtyValValues(value cty.Value) (cty.Value, error) { var updatedValue any switch { @@ -331,7 +331,7 @@ func updateUnknownCtyValValues(value cty.Value) (cty.Value, error) { case value.Type().IsMapType(), value.Type().IsObjectType(): mapVals := value.AsValueMap() for key, val := range mapVals { - val, err := updateUnknownCtyValValues(val) + val, err := UpdateUnknownCtyValValues(val) if err != nil { return cty.NilVal, err } @@ -344,7 +344,7 @@ func updateUnknownCtyValValues(value cty.Value) (cty.Value, error) { case value.Type().IsTupleType(), value.Type().IsListType(): sliceVals := value.AsValueSlice() for key, val := range sliceVals { - val, err := updateUnknownCtyValValues(val) + val, err := UpdateUnknownCtyValValues(val) if err != nil { return cty.NilVal, err } diff --git a/config/cty_helpers_test.go b/config/cty_helpers_test.go index ad5de951b..3ae1d058c 100644 --- a/config/cty_helpers_test.go +++ b/config/cty_helpers_test.go @@ -1,9 +1,10 @@ -package config +package config_test import ( "fmt" "testing" + "github.com/gruntwork-io/terragrunt/config" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/zclconf/go-cty/cty" @@ -12,7 +13,7 @@ import ( func TestUpdateUnknownCtyValValues(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { value cty.Value expectedValue cty.Value }{ @@ -44,13 +45,13 @@ func TestUpdateUnknownCtyValValues(t *testing.T) { }, } - for i, testCase := range testCases { - testCase := testCase + for i, tt := range tc { + testCase := tt t.Run(fmt.Sprintf("testCase-%d", i), func(t *testing.T) { t.Parallel() - actualValue, err := updateUnknownCtyValValues(testCase.value) + actualValue, err := config.UpdateUnknownCtyValValues(testCase.value) require.NoError(t, err) assert.Equal(t, testCase.expectedValue, actualValue) diff --git a/config/dependency.go b/config/dependency.go index 76f2caef0..7a66d62da 100644 --- a/config/dependency.go +++ b/config/dependency.go @@ -185,7 +185,7 @@ func decodeAndRetrieveOutputs(ctx *ParsingContext, file *hclparse.File) (*cty.Va return nil, err } - decodedDependency := terragruntDependency{} + decodedDependency := TerragruntDependency{} if err := file.Decode(&decodedDependency, evalParsingContext); err != nil { return nil, err } @@ -215,8 +215,8 @@ func decodeAndRetrieveOutputs(ctx *ParsingContext, file *hclparse.File) (*cty.Va } // decodeDependencies decode dependencies and fetch inputs -func decodeDependencies(ctx *ParsingContext, decodedDependency terragruntDependency) (*terragruntDependency, error) { - updatedDependencies := terragruntDependency{} +func decodeDependencies(ctx *ParsingContext, decodedDependency TerragruntDependency) (*TerragruntDependency, error) { + updatedDependencies := TerragruntDependency{} depCache := cache.ContextCache[*dependencyOutputCache](ctx, DependencyOutputCacheContextKey) for _, dep := range decodedDependency.Dependencies { depPath := getCleanedTargetConfigPath(dep.ConfigPath.AsString(), ctx.TerragruntOptions.TerragruntConfigPath) @@ -275,7 +275,7 @@ func dependencyBlocksToModuleDependencies(decodedDependencyBlocks []Dependency) // Check for cyclic dependency blocks to avoid infinite `terragrunt output` loops. To avoid reparsing the config, we // kickstart the initial loop using what we already decoded. -func checkForDependencyBlockCycles(ctx *ParsingContext, configPath string, decodedDependency terragruntDependency) error { +func checkForDependencyBlockCycles(ctx *ParsingContext, configPath string, decodedDependency TerragruntDependency) error { visitedPaths := []string{} currentTraversalPaths := []string{configPath} for _, dependency := range decodedDependency.Dependencies { @@ -511,7 +511,7 @@ func getTerragruntOutput(ctx *ParsingContext, dependencyConfig Dependency) (*cty } isEmpty := string(jsonBytes) == "{}" - outputMap, err := terraformOutputJsonToCtyValueMap(targetConfigPath, jsonBytes) + outputMap, err := TerraformOutputJsonToCtyValueMap(targetConfigPath, jsonBytes) if err != nil { return nil, isEmpty, err } @@ -959,9 +959,9 @@ func runTerragruntOutputJson(ctx *ParsingContext, targetConfig string) ([]byte, return jsonBytes, nil } -// terraformOutputJsonToCtyValueMap takes the terraform output json and converts to a mapping between output keys to the +// TerraformOutputJsonToCtyValueMap takes the terraform output json and converts to a mapping between output keys to the // parsed cty.Value encoding of the json objects. -func terraformOutputJsonToCtyValueMap(targetConfigPath string, jsonBytes []byte) (map[string]cty.Value, error) { +func TerraformOutputJsonToCtyValueMap(targetConfigPath string, jsonBytes []byte) (map[string]cty.Value, error) { // When getting all outputs, terraform returns a json with the data containing metadata about the types, so we // can't quite return the data directly. Instead, we will need further processing to get the output we want. // To do so, we first Unmarshal the json into a simple go map to a OutputMeta struct. diff --git a/config/dependency_test.go b/config/dependency_test.go index 902c34be9..06fd4ae3b 100644 --- a/config/dependency_test.go +++ b/config/dependency_test.go @@ -1,10 +1,11 @@ -package config +package config_test import ( "context" "os" "testing" + "github.com/gruntwork-io/terragrunt/config" "github.com/gruntwork-io/terragrunt/options" "github.com/gruntwork-io/go-commons/env" @@ -19,7 +20,7 @@ import ( func TestDecodeDependencyBlockMultiple(t *testing.T) { t.Parallel() - config := ` + cfg := ` dependency "vpc" { config_path = "../vpc" } @@ -28,11 +29,11 @@ dependency "sql" { config_path = "../sql" } ` - filename := DefaultTerragruntConfigPath - file, err := hclparse.NewParser().ParseFromString(config, filename) + filename := config.DefaultTerragruntConfigPath + file, err := hclparse.NewParser().ParseFromString(cfg, filename) require.NoError(t, err) - decoded := terragruntDependency{} + decoded := config.TerragruntDependency{} require.NoError(t, file.Decode(&decoded, &hcl.EvalContext{})) assert.Len(t, decoded.Dependencies, 2) @@ -45,16 +46,16 @@ dependency "sql" { func TestDecodeNoDependencyBlock(t *testing.T) { t.Parallel() - config := ` + cfg := ` locals { path = "../vpc" } ` - filename := DefaultTerragruntConfigPath - file, err := hclparse.NewParser().ParseFromString(config, filename) + filename := config.DefaultTerragruntConfigPath + file, err := hclparse.NewParser().ParseFromString(cfg, filename) require.NoError(t, err) - decoded := terragruntDependency{} + decoded := config.TerragruntDependency{} require.NoError(t, file.Decode(&decoded, &hcl.EvalContext{})) assert.Empty(t, decoded.Dependencies) } @@ -62,23 +63,23 @@ locals { func TestDecodeDependencyNoLabelIsError(t *testing.T) { t.Parallel() - config := ` + cfg := ` dependency { config_path = "../vpc" } ` - filename := DefaultTerragruntConfigPath - file, err := hclparse.NewParser().ParseFromString(config, filename) + filename := config.DefaultTerragruntConfigPath + file, err := hclparse.NewParser().ParseFromString(cfg, filename) require.NoError(t, err) - decoded := terragruntDependency{} - assert.Error(t, file.Decode(&decoded, &hcl.EvalContext{})) + decoded := config.TerragruntDependency{} + require.Error(t, file.Decode(&decoded, &hcl.EvalContext{})) } func TestDecodeDependencyMockOutputs(t *testing.T) { t.Parallel() - config := ` + cfg := ` dependency "hitchhiker" { config_path = "../answers" mock_outputs = { @@ -87,11 +88,11 @@ dependency "hitchhiker" { mock_outputs_allowed_terraform_commands = ["validate", "apply"] } ` - filename := DefaultTerragruntConfigPath - file, err := hclparse.NewParser().ParseFromString(config, filename) + filename := config.DefaultTerragruntConfigPath + file, err := hclparse.NewParser().ParseFromString(cfg, filename) require.NoError(t, err) - decoded := terragruntDependency{} + decoded := config.TerragruntDependency{} require.NoError(t, file.Decode(&decoded, &hcl.EvalContext{})) assert.Len(t, decoded.Dependencies, 1) @@ -116,13 +117,13 @@ func TestParseDependencyBlockMultiple(t *testing.T) { t.Parallel() filename := "../test/fixture-regressions/multiple-dependency-load-sync/main/terragrunt.hcl" - ctx := NewParsingContext(context.Background(), mockOptionsForTestWithConfigPath(t, filename)) + ctx := config.NewParsingContext(context.Background(), mockOptionsForTestWithConfigPath(t, filename)) opts, err := options.NewTerragruntOptionsForTest(filename) require.NoError(t, err) ctx.TerragruntOptions = opts ctx.TerragruntOptions.FetchDependencyOutputFromState = true ctx.TerragruntOptions.Env = env.Parse(os.Environ()) - tfConfig, err := ParseConfigFile(ctx, filename, nil) + tfConfig, err := config.ParseConfigFile(ctx, filename, nil) require.NoError(t, err) assert.Len(t, tfConfig.TerragruntDependencies, 2) assert.Equal(t, "dependency_1", tfConfig.TerragruntDependencies[0].Name) @@ -132,7 +133,7 @@ func TestParseDependencyBlockMultiple(t *testing.T) { func TestDisabledDependency(t *testing.T) { t.Parallel() - config := ` + cfg := ` dependency "ec2" { config_path = "../ec2" enabled = false @@ -141,11 +142,11 @@ dependency "vpc" { config_path = "../vpc" } ` - filename := DefaultTerragruntConfigPath - file, err := hclparse.NewParser().ParseFromString(config, filename) + filename := config.DefaultTerragruntConfigPath + file, err := hclparse.NewParser().ParseFromString(cfg, filename) require.NoError(t, err) - decoded := terragruntDependency{} + decoded := config.TerragruntDependency{} require.NoError(t, file.Decode(&decoded, &hcl.EvalContext{})) assert.Len(t, decoded.Dependencies, 2) } diff --git a/config/include.go b/config/include.go index 91f36e54e..c8e607875 100644 --- a/config/include.go +++ b/config/include.go @@ -155,7 +155,7 @@ func handleInclude(ctx *ParsingContext, config *TerragruntConfig, isPartial bool // dependency block configurations between the included config and the child config. This allows us to merge the two // dependencies prior to retrieving the outputs, allowing you to have partial configuration that is overridden by a // child. -func handleIncludeForDependency(ctx *ParsingContext, childDecodedDependency terragruntDependency) (*terragruntDependency, error) { +func handleIncludeForDependency(ctx *ParsingContext, childDecodedDependency TerragruntDependency) (*TerragruntDependency, error) { if ctx.TrackInclude == nil { return nil, goErrors.New("You reached an impossible condition. This is most likely a bug in terragrunt. Please open an issue at github.com/gruntwork-io/terragrunt with this error message. Code: HANDLE_INCLUDE_DEPENDENCY_NIL_INCLUDE_CONFIG") } @@ -194,7 +194,7 @@ func handleIncludeForDependency(ctx *ParsingContext, childDecodedDependency terr return nil, fmt.Errorf("You reached an impossible condition. This is most likely a bug in terragrunt. Please open an issue at github.com/gruntwork-io/terragrunt with this error message. Code: UNKNOWN_MERGE_STRATEGY_%s_DEPENDENCY", mergeStrategy) } } - return &terragruntDependency{Dependencies: baseDependencyBlock}, nil + return &TerragruntDependency{Dependencies: baseDependencyBlock}, nil } // Merge performs a shallow merge of the given sourceConfig into the targetConfig. sourceConfig will override common @@ -303,7 +303,7 @@ func (targetConfig *TerragruntConfig) Merge(sourceConfig *TerragruntConfig, terr targetConfig.Inputs = mergeInputs(sourceConfig.Inputs, targetConfig.Inputs) } - copyFieldsMetadata(sourceConfig, targetConfig) + CopyFieldsMetadata(sourceConfig, targetConfig) return nil } @@ -460,7 +460,7 @@ func (targetConfig *TerragruntConfig) DeepMerge(sourceConfig *TerragruntConfig, targetConfig.GenerateConfigs[key] = val } - copyFieldsMetadata(sourceConfig, targetConfig) + CopyFieldsMetadata(sourceConfig, targetConfig) return nil } @@ -840,8 +840,8 @@ func jsonIsIncludeBlock(jsonData interface{}) bool { return false } -// copyFieldsMetadata Copy fields metadata between TerragruntConfig instances. -func copyFieldsMetadata(sourceConfig *TerragruntConfig, targetConfig *TerragruntConfig) { +// CopyFieldsMetadata Copy fields metadata between TerragruntConfig instances. +func CopyFieldsMetadata(sourceConfig *TerragruntConfig, targetConfig *TerragruntConfig) { fieldsCopyLocks.Lock(targetConfig.DownloadDir) defer fieldsCopyLocks.Unlock(targetConfig.DownloadDir) diff --git a/config/include_test.go b/config/include_test.go index abe114741..6f9c9e0c9 100644 --- a/config/include_test.go +++ b/config/include_test.go @@ -1,9 +1,10 @@ -package config +package config_test import ( "sync" "testing" + "github.com/gruntwork-io/terragrunt/config" "github.com/gruntwork-io/terragrunt/remote" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -14,141 +15,141 @@ func TestMergeConfigIntoIncludedConfig(t *testing.T) { t.Parallel() testCases := []struct { - config *TerragruntConfig - includedConfig *TerragruntConfig - expected *TerragruntConfig + config *config.TerragruntConfig + includedConfig *config.TerragruntConfig + expected *config.TerragruntConfig }{ { - &TerragruntConfig{}, - &TerragruntConfig{}, - &TerragruntConfig{}, + &config.TerragruntConfig{}, + &config.TerragruntConfig{}, + &config.TerragruntConfig{}, }, { - &TerragruntConfig{}, - &TerragruntConfig{Terraform: &TerraformConfig{Source: ptr("foo")}}, - &TerragruntConfig{Terraform: &TerraformConfig{Source: ptr("foo")}}, + &config.TerragruntConfig{}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{Source: ptr("foo")}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{Source: ptr("foo")}}, }, { - &TerragruntConfig{}, - &TerragruntConfig{RemoteState: &remote.RemoteState{Backend: "bar"}, Terraform: &TerraformConfig{Source: ptr("foo")}}, - &TerragruntConfig{RemoteState: &remote.RemoteState{Backend: "bar"}, Terraform: &TerraformConfig{Source: ptr("foo")}}, + &config.TerragruntConfig{}, + &config.TerragruntConfig{RemoteState: &remote.RemoteState{Backend: "bar"}, Terraform: &config.TerraformConfig{Source: ptr("foo")}}, + &config.TerragruntConfig{RemoteState: &remote.RemoteState{Backend: "bar"}, Terraform: &config.TerraformConfig{Source: ptr("foo")}}, }, { - &TerragruntConfig{RemoteState: &remote.RemoteState{Backend: "foo"}, Terraform: &TerraformConfig{Source: ptr("foo")}}, - &TerragruntConfig{RemoteState: &remote.RemoteState{Backend: "bar"}, Terraform: &TerraformConfig{Source: ptr("foo")}}, - &TerragruntConfig{RemoteState: &remote.RemoteState{Backend: "foo"}, Terraform: &TerraformConfig{Source: ptr("foo")}}, + &config.TerragruntConfig{RemoteState: &remote.RemoteState{Backend: "foo"}, Terraform: &config.TerraformConfig{Source: ptr("foo")}}, + &config.TerragruntConfig{RemoteState: &remote.RemoteState{Backend: "bar"}, Terraform: &config.TerraformConfig{Source: ptr("foo")}}, + &config.TerragruntConfig{RemoteState: &remote.RemoteState{Backend: "foo"}, Terraform: &config.TerraformConfig{Source: ptr("foo")}}, }, { - &TerragruntConfig{Terraform: &TerraformConfig{Source: ptr("foo")}}, - &TerragruntConfig{RemoteState: &remote.RemoteState{Backend: "bar"}, Terraform: &TerraformConfig{Source: ptr("foo")}}, - &TerragruntConfig{RemoteState: &remote.RemoteState{Backend: "bar"}, Terraform: &TerraformConfig{Source: ptr("foo")}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{Source: ptr("foo")}}, + &config.TerragruntConfig{RemoteState: &remote.RemoteState{Backend: "bar"}, Terraform: &config.TerraformConfig{Source: ptr("foo")}}, + &config.TerragruntConfig{RemoteState: &remote.RemoteState{Backend: "bar"}, Terraform: &config.TerraformConfig{Source: ptr("foo")}}, }, { - &TerragruntConfig{Terraform: &TerraformConfig{ExtraArgs: []TerraformExtraArguments{{Name: "childArgs"}}}}, - &TerragruntConfig{Terraform: &TerraformConfig{}}, - &TerragruntConfig{Terraform: &TerraformConfig{ExtraArgs: []TerraformExtraArguments{{Name: "childArgs"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{ExtraArgs: []config.TerraformExtraArguments{{Name: "childArgs"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{ExtraArgs: []config.TerraformExtraArguments{{Name: "childArgs"}}}}, }, { - &TerragruntConfig{Terraform: &TerraformConfig{ExtraArgs: []TerraformExtraArguments{{Name: "childArgs"}}}}, - &TerragruntConfig{Terraform: &TerraformConfig{ExtraArgs: []TerraformExtraArguments{{Name: "parentArgs"}}}}, - &TerragruntConfig{Terraform: &TerraformConfig{ExtraArgs: []TerraformExtraArguments{{Name: "parentArgs"}, {Name: "childArgs"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{ExtraArgs: []config.TerraformExtraArguments{{Name: "childArgs"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{ExtraArgs: []config.TerraformExtraArguments{{Name: "parentArgs"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{ExtraArgs: []config.TerraformExtraArguments{{Name: "parentArgs"}, {Name: "childArgs"}}}}, }, { - &TerragruntConfig{Terraform: &TerraformConfig{ExtraArgs: []TerraformExtraArguments{{Name: "overrideArgs", Arguments: &[]string{"-child"}}}}}, - &TerragruntConfig{Terraform: &TerraformConfig{ExtraArgs: []TerraformExtraArguments{{Name: "overrideArgs", Arguments: &[]string{"-parent"}}}}}, - &TerragruntConfig{Terraform: &TerraformConfig{ExtraArgs: []TerraformExtraArguments{{Name: "overrideArgs", Arguments: &[]string{"-child"}}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{ExtraArgs: []config.TerraformExtraArguments{{Name: "overrideArgs", Arguments: &[]string{"-child"}}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{ExtraArgs: []config.TerraformExtraArguments{{Name: "overrideArgs", Arguments: &[]string{"-parent"}}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{ExtraArgs: []config.TerraformExtraArguments{{Name: "overrideArgs", Arguments: &[]string{"-child"}}}}}, }, { - &TerragruntConfig{Terraform: &TerraformConfig{BeforeHooks: []Hook{{Name: "childHooks"}}}}, - &TerragruntConfig{Terraform: nil}, - &TerragruntConfig{Terraform: &TerraformConfig{BeforeHooks: []Hook{{Name: "childHooks"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{BeforeHooks: []config.Hook{{Name: "childHooks"}}}}, + &config.TerragruntConfig{Terraform: nil}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{BeforeHooks: []config.Hook{{Name: "childHooks"}}}}, }, { - &TerragruntConfig{Terraform: nil}, - &TerragruntConfig{Terraform: &TerraformConfig{BeforeHooks: []Hook{{Name: "parentHooks"}}}}, - &TerragruntConfig{Terraform: &TerraformConfig{BeforeHooks: []Hook{{Name: "parentHooks"}}}}, + &config.TerragruntConfig{Terraform: nil}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{BeforeHooks: []config.Hook{{Name: "parentHooks"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{BeforeHooks: []config.Hook{{Name: "parentHooks"}}}}, }, { - &TerragruntConfig{Terraform: &TerraformConfig{BeforeHooks: []Hook{{Name: "childHooks"}}}}, - &TerragruntConfig{Terraform: &TerraformConfig{}}, - &TerragruntConfig{Terraform: &TerraformConfig{BeforeHooks: []Hook{{Name: "childHooks"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{BeforeHooks: []config.Hook{{Name: "childHooks"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{BeforeHooks: []config.Hook{{Name: "childHooks"}}}}, }, { - &TerragruntConfig{Terraform: &TerraformConfig{BeforeHooks: []Hook{{Name: "childHooks"}}}}, - &TerragruntConfig{Terraform: &TerraformConfig{BeforeHooks: []Hook{{Name: "parentHooks"}}}}, - &TerragruntConfig{Terraform: &TerraformConfig{BeforeHooks: []Hook{{Name: "parentHooks"}, {Name: "childHooks"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{BeforeHooks: []config.Hook{{Name: "childHooks"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{BeforeHooks: []config.Hook{{Name: "parentHooks"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{BeforeHooks: []config.Hook{{Name: "parentHooks"}, {Name: "childHooks"}}}}, }, { - &TerragruntConfig{Terraform: &TerraformConfig{BeforeHooks: []Hook{{Name: "overrideHooks", Commands: []string{"child-apply"}}}}}, - &TerragruntConfig{Terraform: &TerraformConfig{BeforeHooks: []Hook{{Name: "overrideHooks", Commands: []string{"parent-apply"}}}}}, - &TerragruntConfig{Terraform: &TerraformConfig{BeforeHooks: []Hook{{Name: "overrideHooks", Commands: []string{"child-apply"}}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{BeforeHooks: []config.Hook{{Name: "overrideHooks", Commands: []string{"child-apply"}}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{BeforeHooks: []config.Hook{{Name: "overrideHooks", Commands: []string{"parent-apply"}}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{BeforeHooks: []config.Hook{{Name: "overrideHooks", Commands: []string{"child-apply"}}}}}, }, { - &TerragruntConfig{Terraform: &TerraformConfig{AfterHooks: []Hook{{Name: "childHooks"}}}}, - &TerragruntConfig{Terraform: &TerraformConfig{}}, - &TerragruntConfig{Terraform: &TerraformConfig{AfterHooks: []Hook{{Name: "childHooks"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{AfterHooks: []config.Hook{{Name: "childHooks"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{AfterHooks: []config.Hook{{Name: "childHooks"}}}}, }, { - &TerragruntConfig{Terraform: &TerraformConfig{AfterHooks: []Hook{{Name: "childHooks"}}}}, - &TerragruntConfig{Terraform: &TerraformConfig{AfterHooks: []Hook{{Name: "parentHooks"}}}}, - &TerragruntConfig{Terraform: &TerraformConfig{AfterHooks: []Hook{{Name: "parentHooks"}, {Name: "childHooks"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{AfterHooks: []config.Hook{{Name: "childHooks"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{AfterHooks: []config.Hook{{Name: "parentHooks"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{AfterHooks: []config.Hook{{Name: "parentHooks"}, {Name: "childHooks"}}}}, }, { - &TerragruntConfig{Terraform: &TerraformConfig{AfterHooks: []Hook{{Name: "overrideHooks", Commands: []string{"child-apply"}}}}}, - &TerragruntConfig{Terraform: &TerraformConfig{AfterHooks: []Hook{{Name: "overrideHooks", Commands: []string{"parent-apply"}}}}}, - &TerragruntConfig{Terraform: &TerraformConfig{AfterHooks: []Hook{{Name: "overrideHooks", Commands: []string{"child-apply"}}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{AfterHooks: []config.Hook{{Name: "overrideHooks", Commands: []string{"child-apply"}}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{AfterHooks: []config.Hook{{Name: "overrideHooks", Commands: []string{"parent-apply"}}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{AfterHooks: []config.Hook{{Name: "overrideHooks", Commands: []string{"child-apply"}}}}}, }, { - &TerragruntConfig{Terraform: &TerraformConfig{AfterHooks: []Hook{{Name: "overrideHooksPlusMore", Commands: []string{"child-apply"}}, {Name: "childHooks"}}}}, - &TerragruntConfig{Terraform: &TerraformConfig{AfterHooks: []Hook{{Name: "overrideHooksPlusMore", Commands: []string{"parent-apply"}}, {Name: "parentHooks"}}}}, - &TerragruntConfig{Terraform: &TerraformConfig{AfterHooks: []Hook{{Name: "overrideHooksPlusMore", Commands: []string{"child-apply"}}, {Name: "parentHooks"}, {Name: "childHooks"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{AfterHooks: []config.Hook{{Name: "overrideHooksPlusMore", Commands: []string{"child-apply"}}, {Name: "childHooks"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{AfterHooks: []config.Hook{{Name: "overrideHooksPlusMore", Commands: []string{"parent-apply"}}, {Name: "parentHooks"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{AfterHooks: []config.Hook{{Name: "overrideHooksPlusMore", Commands: []string{"child-apply"}}, {Name: "parentHooks"}, {Name: "childHooks"}}}}, }, { - &TerragruntConfig{Terraform: &TerraformConfig{AfterHooks: []Hook{{Name: "overrideWithEmptyHooks"}}}}, - &TerragruntConfig{Terraform: &TerraformConfig{AfterHooks: []Hook{{Name: "overrideWithEmptyHooks", Commands: []string{"parent-apply"}}}}}, - &TerragruntConfig{Terraform: &TerraformConfig{AfterHooks: []Hook{{Name: "overrideWithEmptyHooks"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{AfterHooks: []config.Hook{{Name: "overrideWithEmptyHooks"}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{AfterHooks: []config.Hook{{Name: "overrideWithEmptyHooks", Commands: []string{"parent-apply"}}}}}, + &config.TerragruntConfig{Terraform: &config.TerraformConfig{AfterHooks: []config.Hook{{Name: "overrideWithEmptyHooks"}}}}, }, { - &TerragruntConfig{}, - &TerragruntConfig{Skip: true}, - &TerragruntConfig{Skip: false}, + &config.TerragruntConfig{}, + &config.TerragruntConfig{Skip: true}, + &config.TerragruntConfig{Skip: false}, }, { - &TerragruntConfig{Skip: false}, - &TerragruntConfig{Skip: true}, - &TerragruntConfig{Skip: false}, + &config.TerragruntConfig{Skip: false}, + &config.TerragruntConfig{Skip: true}, + &config.TerragruntConfig{Skip: false}, }, { - &TerragruntConfig{Skip: true}, - &TerragruntConfig{Skip: true}, - &TerragruntConfig{Skip: true}, + &config.TerragruntConfig{Skip: true}, + &config.TerragruntConfig{Skip: true}, + &config.TerragruntConfig{Skip: true}, }, { - &TerragruntConfig{IamRole: "role2"}, - &TerragruntConfig{IamRole: "role1"}, - &TerragruntConfig{IamRole: "role2"}, + &config.TerragruntConfig{IamRole: "role2"}, + &config.TerragruntConfig{IamRole: "role1"}, + &config.TerragruntConfig{IamRole: "role2"}, }, { - &TerragruntConfig{IamWebIdentityToken: "token"}, - &TerragruntConfig{IamWebIdentityToken: "token"}, - &TerragruntConfig{IamWebIdentityToken: "token"}, + &config.TerragruntConfig{IamWebIdentityToken: "token"}, + &config.TerragruntConfig{IamWebIdentityToken: "token"}, + &config.TerragruntConfig{IamWebIdentityToken: "token"}, }, { - &TerragruntConfig{IamWebIdentityToken: "token"}, - &TerragruntConfig{IamWebIdentityToken: "token2"}, - &TerragruntConfig{IamWebIdentityToken: "token2"}, + &config.TerragruntConfig{IamWebIdentityToken: "token"}, + &config.TerragruntConfig{IamWebIdentityToken: "token2"}, + &config.TerragruntConfig{IamWebIdentityToken: "token2"}, }, { - &TerragruntConfig{}, - &TerragruntConfig{IamWebIdentityToken: "token"}, - &TerragruntConfig{IamWebIdentityToken: "token"}, + &config.TerragruntConfig{}, + &config.TerragruntConfig{IamWebIdentityToken: "token"}, + &config.TerragruntConfig{IamWebIdentityToken: "token"}, }, } for _, testCase := range testCases { // if nil, initialize to empty dependency list if testCase.expected.TerragruntDependencies == nil { - testCase.expected.TerragruntDependencies = Dependencies{} + testCase.expected.TerragruntDependencies = config.Dependencies{} } err := testCase.includedConfig.Merge(testCase.config, mockOptionsForTest(t)) @@ -210,64 +211,64 @@ func TestDeepMergeConfigIntoIncludedConfig(t *testing.T) { }, } - testCases := []struct { + tc := []struct { name string - source *TerragruntConfig - target *TerragruntConfig - expected *TerragruntConfig + source *config.TerragruntConfig + target *config.TerragruntConfig + expected *config.TerragruntConfig }{ // Base case: empty config { "base case", - &TerragruntConfig{}, - &TerragruntConfig{}, - &TerragruntConfig{}, + &config.TerragruntConfig{}, + &config.TerragruntConfig{}, + &config.TerragruntConfig{}, }, // Simple attribute in target { "simple in target", - &TerragruntConfig{}, - &TerragruntConfig{IamRole: "foo"}, - &TerragruntConfig{IamRole: "foo"}, + &config.TerragruntConfig{}, + &config.TerragruntConfig{IamRole: "foo"}, + &config.TerragruntConfig{IamRole: "foo"}, }, // Simple attribute in source { "simple in source", - &TerragruntConfig{IamRole: "foo"}, - &TerragruntConfig{}, - &TerragruntConfig{IamRole: "foo"}, + &config.TerragruntConfig{IamRole: "foo"}, + &config.TerragruntConfig{}, + &config.TerragruntConfig{IamRole: "foo"}, }, // Simple attribute in both { "simple in both", - &TerragruntConfig{IamRole: "foo"}, - &TerragruntConfig{IamRole: "bar"}, - &TerragruntConfig{IamRole: "foo"}, + &config.TerragruntConfig{IamRole: "foo"}, + &config.TerragruntConfig{IamRole: "bar"}, + &config.TerragruntConfig{IamRole: "foo"}, }, // Deep merge dependencies { "dependencies", - &TerragruntConfig{Dependencies: &ModuleDependencies{Paths: []string{"../vpc"}}, - TerragruntDependencies: Dependencies{ - { + &config.TerragruntConfig{Dependencies: &config.ModuleDependencies{Paths: []string{"../vpc"}}, + TerragruntDependencies: config.Dependencies{ + config.Dependency{ Name: "vpc", ConfigPath: cty.StringVal("../vpc"), }, }}, - &TerragruntConfig{Dependencies: &ModuleDependencies{Paths: []string{"../mysql"}}, - TerragruntDependencies: Dependencies{ - { + &config.TerragruntConfig{Dependencies: &config.ModuleDependencies{Paths: []string{"../mysql"}}, + TerragruntDependencies: config.Dependencies{ + config.Dependency{ Name: "mysql", ConfigPath: cty.StringVal("../mysql"), }, }}, - &TerragruntConfig{Dependencies: &ModuleDependencies{Paths: []string{"../mysql", "../vpc"}}, - TerragruntDependencies: Dependencies{ - { + &config.TerragruntConfig{Dependencies: &config.ModuleDependencies{Paths: []string{"../mysql", "../vpc"}}, + TerragruntDependencies: config.Dependencies{ + config.Dependency{ Name: "mysql", ConfigPath: cty.StringVal("../mysql"), }, - { + config.Dependency{ Name: "vpc", ConfigPath: cty.StringVal("../vpc"), }, @@ -276,43 +277,48 @@ func TestDeepMergeConfigIntoIncludedConfig(t *testing.T) { // Deep merge retryable errors { "retryable errors", - &TerragruntConfig{RetryableErrors: []string{"error", "override"}}, - &TerragruntConfig{RetryableErrors: []string{"original", "error"}}, - &TerragruntConfig{RetryableErrors: []string{"original", "error", "error", "override"}}, + &config.TerragruntConfig{RetryableErrors: []string{"error", "override"}}, + &config.TerragruntConfig{RetryableErrors: []string{"original", "error"}}, + &config.TerragruntConfig{RetryableErrors: []string{"original", "error", "error", "override"}}, }, // Deep merge inputs { "inputs", - &TerragruntConfig{Inputs: overrideMap}, - &TerragruntConfig{Inputs: originalMap}, - &TerragruntConfig{Inputs: mergedMap}, + &config.TerragruntConfig{Inputs: overrideMap}, + &config.TerragruntConfig{Inputs: originalMap}, + &config.TerragruntConfig{Inputs: mergedMap}, }, } - for _, testCase := range testCases { - // No need to capture range var because tests are run sequentially - t.Run(testCase.name, func(t *testing.T) { - err := testCase.target.DeepMerge(testCase.source, mockOptionsForTest(t)) + for _, tt := range tc { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + err := tt.target.DeepMerge(tt.source, mockOptionsForTest(t)) require.NoError(t, err) // if nil, initialize to empty dependency list - if testCase.expected.TerragruntDependencies == nil { - testCase.expected.TerragruntDependencies = Dependencies{} + if tt.expected.TerragruntDependencies == nil { + tt.expected.TerragruntDependencies = config.Dependencies{} } - assert.Equal(t, testCase.expected, testCase.target) + assert.Equal(t, tt.expected, tt.target) }) } } func TestConcurrentCopyFieldsMetadata(t *testing.T) { - sourceConfig := &TerragruntConfig{ + t.Parallel() + + sourceConfig := &config.TerragruntConfig{ FieldsMetadata: map[string]map[string]interface{}{ "field1": {"key1": "value1", "key2": "value2"}, "field2": {"key3": "value3", "key4": "value4"}, }, } - targetConfig := &TerragruntConfig{} + targetConfig := &config.TerragruntConfig{} var wg sync.WaitGroup numGoroutines := 666 @@ -321,7 +327,7 @@ func TestConcurrentCopyFieldsMetadata(t *testing.T) { for i := 0; i < numGoroutines; i++ { go func() { defer wg.Done() - copyFieldsMetadata(sourceConfig, targetConfig) + config.CopyFieldsMetadata(sourceConfig, targetConfig) }() } diff --git a/config/locals.go b/config/locals.go index 8a08f2096..392813cb7 100644 --- a/config/locals.go +++ b/config/locals.go @@ -15,7 +15,7 @@ import ( // MaxIter is the maximum number of depth we support in recursively evaluating locals. const MaxIter = 1000 -// evaluateLocalsBlock is a routine to evaluate the locals block in a way to allow references to other locals. This +// EvaluateLocalsBlock is a routine to evaluate the locals block in a way to allow references to other locals. This // will: // - Extract a reference to the locals block from the parsed file // - Continuously evaluate the block until all references are evaluated, defering evaluation of anything that references @@ -23,7 +23,7 @@ const MaxIter = 1000 // // This returns a map of the local names to the evaluated expressions (represented as `cty.Value` objects). This will // error if there are remaining unevaluated locals after all references that can be evaluated has been evaluated. -func evaluateLocalsBlock(ctx *ParsingContext, file *hclparse.File) (map[string]cty.Value, error) { +func EvaluateLocalsBlock(ctx *ParsingContext, file *hclparse.File) (map[string]cty.Value, error) { localsBlock, err := file.Blocks(MetadataLocals, false) if err != nil { return nil, err diff --git a/config/locals_test.go b/config/locals_test.go index 13e67d14f..74d26d419 100644 --- a/config/locals_test.go +++ b/config/locals_test.go @@ -1,4 +1,4 @@ -package config +package config_test import ( "context" @@ -10,6 +10,7 @@ import ( "github.com/zclconf/go-cty/cty/gocty" "github.com/gruntwork-io/go-commons/errors" + "github.com/gruntwork-io/terragrunt/config" "github.com/gruntwork-io/terragrunt/config/hclparse" ) @@ -22,8 +23,8 @@ func TestEvaluateLocalsBlock(t *testing.T) { file, err := hclparse.NewParser().ParseFromString(LocalsTestConfig, mockFilename) require.NoError(t, err) - ctx := NewParsingContext(context.Background(), terragruntOptions) - evaluatedLocals, err := evaluateLocalsBlock(ctx, file) + ctx := config.NewParsingContext(context.Background(), terragruntOptions) + evaluatedLocals, err := config.EvaluateLocalsBlock(ctx, file) require.NoError(t, err) var actualRegion string @@ -67,8 +68,8 @@ func TestEvaluateLocalsBlockMultiDeepReference(t *testing.T) { file, err := hclparse.NewParser().ParseFromString(LocalsTestMultiDeepReferenceConfig, mockFilename) require.NoError(t, err) - ctx := NewParsingContext(context.Background(), terragruntOptions) - evaluatedLocals, err := evaluateLocalsBlock(ctx, file) + ctx := config.NewParsingContext(context.Background(), terragruntOptions) + evaluatedLocals, err := config.EvaluateLocalsBlock(ctx, file) require.NoError(t, err) expected := "a" @@ -106,12 +107,12 @@ func TestEvaluateLocalsBlockImpossibleWillFail(t *testing.T) { file, err := hclparse.NewParser().ParseFromString(LocalsTestImpossibleConfig, mockFilename) require.NoError(t, err) - ctx := NewParsingContext(context.Background(), terragruntOptions) - _, err = evaluateLocalsBlock(ctx, file) + ctx := config.NewParsingContext(context.Background(), terragruntOptions) + _, err = config.EvaluateLocalsBlock(ctx, file) require.Error(t, err) switch errors.Unwrap(err).(type) { //nolint:errorlint - case CouldNotEvaluateAllLocalsError: + case config.CouldNotEvaluateAllLocalsError: default: t.Fatalf("Did not get expected error: %s", err) } @@ -126,8 +127,8 @@ func TestEvaluateLocalsBlockMultipleLocalsBlocksWillFail(t *testing.T) { file, err := hclparse.NewParser().ParseFromString(MultipleLocalsBlockConfig, mockFilename) require.NoError(t, err) - ctx := NewParsingContext(context.Background(), terragruntOptions) - _, err = evaluateLocalsBlock(ctx, file) + ctx := config.NewParsingContext(context.Background(), terragruntOptions) + _, err = config.EvaluateLocalsBlock(ctx, file) require.Error(t, err) } diff --git a/config/variable_test.go b/config/variable_test.go index d8ec57a3c..fcda607f8 100644 --- a/config/variable_test.go +++ b/config/variable_test.go @@ -1,8 +1,9 @@ -package config +package config_test import ( "testing" + "github.com/gruntwork-io/terragrunt/config" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -12,11 +13,11 @@ func TestScanVariables(t *testing.T) { opts := terragruntOptionsForTest(t, "") - inputs, err := ParseVariables(opts, "../test/fixture-inputs") + inputs, err := config.ParseVariables(opts, "../test/fixture-inputs") require.NoError(t, err) assert.Len(t, inputs, 11) - varByName := map[string]*ParsedVariable{} + varByName := map[string]*config.ParsedVariable{} for _, input := range inputs { varByName[input.Name] = input } @@ -44,11 +45,11 @@ func TestScanDefaultVariables(t *testing.T) { t.Parallel() opts := terragruntOptionsForTest(t, "") - inputs, err := ParseVariables(opts, "../test/fixture-inputs-defaults") + inputs, err := config.ParseVariables(opts, "../test/fixture-inputs-defaults") require.NoError(t, err) assert.Len(t, inputs, 11) - varByName := map[string]*ParsedVariable{} + varByName := map[string]*config.ParsedVariable{} for _, input := range inputs { varByName[input.Name] = input } diff --git a/configstack/errors.go b/configstack/errors.go index 72e960fa4..91c617241 100644 --- a/configstack/errors.go +++ b/configstack/errors.go @@ -73,7 +73,7 @@ func (err ProcessingModuleDependencyError) Unwrap() error { } type DependencyNotFoundWhileCrossLinkingError struct { - Module *runningModule + Module *RunningModule Dependency *TerraformModule } diff --git a/configstack/log_test.go b/configstack/log_test.go index 7efbe76ef..5d5721c8b 100644 --- a/configstack/log_test.go +++ b/configstack/log_test.go @@ -1,10 +1,11 @@ -package configstack +package configstack_test import ( "bytes" "strings" "testing" + "github.com/gruntwork-io/terragrunt/configstack" "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" @@ -16,7 +17,7 @@ func ptr(str string) *string { func TestLogReductionHook(t *testing.T) { t.Parallel() - var hook = NewForceLogLevelHook(logrus.ErrorLevel) + var hook = configstack.NewForceLogLevelHook(logrus.ErrorLevel) stdout := bytes.Buffer{} diff --git a/configstack/module.go b/configstack/module.go index d50a11191..b0a06cecd 100644 --- a/configstack/module.go +++ b/configstack/module.go @@ -315,7 +315,7 @@ func (modules TerraformModules) WriteDot(w io.Writer, terragruntOptions *options // TerragruntOptions object. The modules will be executed in an order determined by their inter-dependencies, using // as much concurrency as possible. func (modules TerraformModules) RunModules(ctx context.Context, opts *options.TerragruntOptions, parallelism int) error { - runningModules, err := modules.toRunningModules(NormalOrder) + runningModules, err := modules.ToRunningModules(NormalOrder) if err != nil { return err } @@ -326,7 +326,7 @@ func (modules TerraformModules) RunModules(ctx context.Context, opts *options.Te // TerragruntOptions object. The modules will be executed in the reverse order of their inter-dependencies, using // as much concurrency as possible. func (modules TerraformModules) RunModulesReverseOrder(ctx context.Context, opts *options.TerragruntOptions, parallelism int) error { - runningModules, err := modules.toRunningModules(ReverseOrder) + runningModules, err := modules.ToRunningModules(ReverseOrder) if err != nil { return err } @@ -336,7 +336,7 @@ func (modules TerraformModules) RunModulesReverseOrder(ctx context.Context, opts // Run the given map of module path to runningModule. To "run" a module, execute the RunTerragrunt command in its // TerragruntOptions object. The modules will be executed without caring for inter-dependencies. func (modules TerraformModules) RunModulesIgnoreOrder(ctx context.Context, opts *options.TerragruntOptions, parallelism int) error { - runningModules, err := modules.toRunningModules(IgnoreOrder) + runningModules, err := modules.ToRunningModules(IgnoreOrder) if err != nil { return err } @@ -346,8 +346,8 @@ func (modules TerraformModules) RunModulesIgnoreOrder(ctx context.Context, opts // Convert the list of modules to a map from module path to a runningModule struct. This struct contains information // about executing the module, such as whether it has finished running or not and any errors that happened. Note that // this does NOT actually run the module. For that, see the RunModules method. -func (modules TerraformModules) toRunningModules(dependencyOrder DependencyOrder) (runningModules, error) { - runningModules := runningModules{} +func (modules TerraformModules) ToRunningModules(dependencyOrder DependencyOrder) (RunningModules, error) { + runningModules := RunningModules{} for _, module := range modules { runningModules[module.Path] = newRunningModule(module) } @@ -357,7 +357,7 @@ func (modules TerraformModules) toRunningModules(dependencyOrder DependencyOrder return crossLinkedModules, err } - return crossLinkedModules.removeFlagExcluded(), nil + return crossLinkedModules.RemoveFlagExcluded(), nil } // Check for dependency cycles in the given list of modules and return an error if one is found diff --git a/configstack/module_test.go b/configstack/module_test.go index 158156a2a..6322e2af3 100644 --- a/configstack/module_test.go +++ b/configstack/module_test.go @@ -1,4 +1,4 @@ -package configstack +package configstack_test import ( "bytes" @@ -8,22 +8,25 @@ import ( "testing" "github.com/gruntwork-io/terragrunt/config" + "github.com/gruntwork-io/terragrunt/configstack" "github.com/gruntwork-io/terragrunt/options" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestGraph(t *testing.T) { - a := &TerraformModule{Path: "a"} - b := &TerraformModule{Path: "b"} - c := &TerraformModule{Path: "c"} - d := &TerraformModule{Path: "d"} - e := &TerraformModule{Path: "e", Dependencies: []*TerraformModule{a}} - f := &TerraformModule{Path: "f", Dependencies: []*TerraformModule{a, b}} - g := &TerraformModule{Path: "g", Dependencies: []*TerraformModule{e}} - h := &TerraformModule{Path: "h", Dependencies: []*TerraformModule{g, f, c}} + t.Parallel() + + a := &configstack.TerraformModule{Path: "a"} + b := &configstack.TerraformModule{Path: "b"} + c := &configstack.TerraformModule{Path: "c"} + d := &configstack.TerraformModule{Path: "d"} + e := &configstack.TerraformModule{Path: "e", Dependencies: []*configstack.TerraformModule{a}} + f := &configstack.TerraformModule{Path: "f", Dependencies: []*configstack.TerraformModule{a, b}} + g := &configstack.TerraformModule{Path: "g", Dependencies: []*configstack.TerraformModule{e}} + h := &configstack.TerraformModule{Path: "h", Dependencies: []*configstack.TerraformModule{g, f, c}} - modules := TerraformModules{a, b, c, d, e, f, g, h} + modules := configstack.TerraformModules{a, b, c, d, e, f, g, h} var stdout bytes.Buffer terragruntOptions, _ := options.NewTerragruntOptionsForTest("/terragrunt.hcl") @@ -51,16 +54,18 @@ digraph { } func TestGraphTrimPrefix(t *testing.T) { - a := &TerraformModule{Path: "/config/a"} - b := &TerraformModule{Path: "/config/b"} - c := &TerraformModule{Path: "/config/c"} - d := &TerraformModule{Path: "/config/d"} - e := &TerraformModule{Path: "/config/alpha/beta/gamma/e", Dependencies: []*TerraformModule{a}} - f := &TerraformModule{Path: "/config/alpha/beta/gamma/f", Dependencies: []*TerraformModule{a, b}} - g := &TerraformModule{Path: "/config/alpha/g", Dependencies: []*TerraformModule{e}} - h := &TerraformModule{Path: "/config/alpha/beta/h", Dependencies: []*TerraformModule{g, f, c}} + t.Parallel() - modules := TerraformModules{a, b, c, d, e, f, g, h} + a := &configstack.TerraformModule{Path: "/config/a"} + b := &configstack.TerraformModule{Path: "/config/b"} + c := &configstack.TerraformModule{Path: "/config/c"} + d := &configstack.TerraformModule{Path: "/config/d"} + e := &configstack.TerraformModule{Path: "/config/alpha/beta/gamma/e", Dependencies: []*configstack.TerraformModule{a}} + f := &configstack.TerraformModule{Path: "/config/alpha/beta/gamma/f", Dependencies: []*configstack.TerraformModule{a, b}} + g := &configstack.TerraformModule{Path: "/config/alpha/g", Dependencies: []*configstack.TerraformModule{e}} + h := &configstack.TerraformModule{Path: "/config/alpha/beta/h", Dependencies: []*configstack.TerraformModule{g, f, c}} + + modules := configstack.TerraformModules{a, b, c, d, e, f, g, h} var stdout bytes.Buffer terragruntOptions, _ := options.NewTerragruntOptionsWithConfigPath("/config/terragrunt.hcl") @@ -88,16 +93,18 @@ digraph { } func TestGraphFlagExcluded(t *testing.T) { - a := &TerraformModule{Path: "a", FlagExcluded: true} - b := &TerraformModule{Path: "b"} - c := &TerraformModule{Path: "c"} - d := &TerraformModule{Path: "d"} - e := &TerraformModule{Path: "e", Dependencies: []*TerraformModule{a}} - f := &TerraformModule{Path: "f", FlagExcluded: true, Dependencies: []*TerraformModule{a, b}} - g := &TerraformModule{Path: "g", Dependencies: []*TerraformModule{e}} - h := &TerraformModule{Path: "h", Dependencies: []*TerraformModule{g, f, c}} + t.Parallel() + + a := &configstack.TerraformModule{Path: "a", FlagExcluded: true} + b := &configstack.TerraformModule{Path: "b"} + c := &configstack.TerraformModule{Path: "c"} + d := &configstack.TerraformModule{Path: "d"} + e := &configstack.TerraformModule{Path: "e", Dependencies: []*configstack.TerraformModule{a}} + f := &configstack.TerraformModule{Path: "f", FlagExcluded: true, Dependencies: []*configstack.TerraformModule{a, b}} + g := &configstack.TerraformModule{Path: "g", Dependencies: []*configstack.TerraformModule{e}} + h := &configstack.TerraformModule{Path: "h", Dependencies: []*configstack.TerraformModule{g, f, c}} - modules := TerraformModules{a, b, c, d, e, f, g, h} + modules := configstack.TerraformModules{a, b, c, d, e, f, g, h} var stdout bytes.Buffer terragruntOptions, _ := options.NewTerragruntOptionsForTest("/terragrunt.hcl") @@ -130,66 +137,66 @@ func TestCheckForCycles(t *testing.T) { //////////////////////////////////// // These modules have no dependencies //////////////////////////////////// - a := &TerraformModule{Path: "a"} - b := &TerraformModule{Path: "b"} - c := &TerraformModule{Path: "c"} - d := &TerraformModule{Path: "d"} + a := &configstack.TerraformModule{Path: "a"} + b := &configstack.TerraformModule{Path: "b"} + c := &configstack.TerraformModule{Path: "c"} + d := &configstack.TerraformModule{Path: "d"} //////////////////////////////////// // These modules have dependencies, but no cycles //////////////////////////////////// // e -> a - e := &TerraformModule{Path: "e", Dependencies: []*TerraformModule{a}} + e := &configstack.TerraformModule{Path: "e", Dependencies: []*configstack.TerraformModule{a}} // f -> a, b - f := &TerraformModule{Path: "f", Dependencies: []*TerraformModule{a, b}} + f := &configstack.TerraformModule{Path: "f", Dependencies: []*configstack.TerraformModule{a, b}} // g -> e -> a - g := &TerraformModule{Path: "g", Dependencies: []*TerraformModule{e}} + g := &configstack.TerraformModule{Path: "g", Dependencies: []*configstack.TerraformModule{e}} // h -> g -> e -> a // | / // --> f -> b // | // --> c - h := &TerraformModule{Path: "h", Dependencies: []*TerraformModule{g, f, c}} + h := &configstack.TerraformModule{Path: "h", Dependencies: []*configstack.TerraformModule{g, f, c}} //////////////////////////////////// // These modules have dependencies and cycles //////////////////////////////////// // i -> i - i := &TerraformModule{Path: "i", Dependencies: []*TerraformModule{}} + i := &configstack.TerraformModule{Path: "i", Dependencies: []*configstack.TerraformModule{}} i.Dependencies = append(i.Dependencies, i) // j -> k -> j - j := &TerraformModule{Path: "j", Dependencies: []*TerraformModule{}} - k := &TerraformModule{Path: "k", Dependencies: []*TerraformModule{j}} + j := &configstack.TerraformModule{Path: "j", Dependencies: []*configstack.TerraformModule{}} + k := &configstack.TerraformModule{Path: "k", Dependencies: []*configstack.TerraformModule{j}} j.Dependencies = append(j.Dependencies, k) // l -> m -> n -> o -> l - l := &TerraformModule{Path: "l", Dependencies: []*TerraformModule{}} - o := &TerraformModule{Path: "o", Dependencies: []*TerraformModule{l}} - n := &TerraformModule{Path: "n", Dependencies: []*TerraformModule{o}} - m := &TerraformModule{Path: "m", Dependencies: []*TerraformModule{n}} + l := &configstack.TerraformModule{Path: "l", Dependencies: []*configstack.TerraformModule{}} + o := &configstack.TerraformModule{Path: "o", Dependencies: []*configstack.TerraformModule{l}} + n := &configstack.TerraformModule{Path: "n", Dependencies: []*configstack.TerraformModule{o}} + m := &configstack.TerraformModule{Path: "m", Dependencies: []*configstack.TerraformModule{n}} l.Dependencies = append(l.Dependencies, m) testCases := []struct { - modules TerraformModules - expected DependencyCycleError + modules configstack.TerraformModules + expected configstack.DependencyCycleError }{ - {[]*TerraformModule{}, nil}, - {[]*TerraformModule{a}, nil}, - {[]*TerraformModule{a, b, c, d}, nil}, - {[]*TerraformModule{a, e}, nil}, - {[]*TerraformModule{a, b, f}, nil}, - {[]*TerraformModule{a, e, g}, nil}, - {[]*TerraformModule{a, b, c, e, f, g, h}, nil}, - {[]*TerraformModule{i}, DependencyCycleError([]string{"i", "i"})}, - {[]*TerraformModule{j, k}, DependencyCycleError([]string{"j", "k", "j"})}, - {[]*TerraformModule{l, o, n, m}, DependencyCycleError([]string{"l", "m", "n", "o", "l"})}, - {[]*TerraformModule{a, l, b, o, n, f, m, h}, DependencyCycleError([]string{"l", "m", "n", "o", "l"})}, + {[]*configstack.TerraformModule{}, nil}, + {[]*configstack.TerraformModule{a}, nil}, + {[]*configstack.TerraformModule{a, b, c, d}, nil}, + {[]*configstack.TerraformModule{a, e}, nil}, + {[]*configstack.TerraformModule{a, b, f}, nil}, + {[]*configstack.TerraformModule{a, e, g}, nil}, + {[]*configstack.TerraformModule{a, b, c, e, f, g, h}, nil}, + {[]*configstack.TerraformModule{i}, configstack.DependencyCycleError([]string{"i", "i"})}, + {[]*configstack.TerraformModule{j, k}, configstack.DependencyCycleError([]string{"j", "k", "j"})}, + {[]*configstack.TerraformModule{l, o, n, m}, configstack.DependencyCycleError([]string{"l", "m", "n", "o", "l"})}, + {[]*configstack.TerraformModule{a, l, b, o, n, f, m, h}, configstack.DependencyCycleError([]string{"l", "m", "n", "o", "l"})}, } for _, testCase := range testCases { @@ -197,8 +204,7 @@ func TestCheckForCycles(t *testing.T) { if testCase.expected == nil { require.NoError(t, actual) } else if assert.Error(t, actual, "For modules %v", testCase.modules) { - var actualErr DependencyCycleError - // actualErr := errors.Unwrap(actual).(DependencyCycleError) + var actualErr configstack.DependencyCycleError errors.As(actual, &actualErr) assert.Equal(t, []string(testCase.expected), []string(actualErr), "For modules %v", testCase.modules) } @@ -211,7 +217,7 @@ func TestRunModulesNoModules(t *testing.T) { opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{} + modules := configstack.TerraformModules{} err = modules.RunModules(context.Background(), opts, options.DefaultParallelism) require.NoError(t, err, "Unexpected error: %v", err) } @@ -220,9 +226,9 @@ func TestRunModulesOneModuleSuccess(t *testing.T) { t.Parallel() aRan := false - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", nil, &aRan), } @@ -230,7 +236,7 @@ func TestRunModulesOneModuleSuccess(t *testing.T) { opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA} + modules := configstack.TerraformModules{moduleA} err = modules.RunModules(context.Background(), opts, options.DefaultParallelism) require.NoError(t, err, "Unexpected error: %v", err) assert.True(t, aRan) @@ -240,9 +246,9 @@ func TestRunModulesOneModuleAssumeAlreadyRan(t *testing.T) { t.Parallel() aRan := false - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", nil, &aRan), AssumeAlreadyApplied: true, @@ -251,7 +257,7 @@ func TestRunModulesOneModuleAssumeAlreadyRan(t *testing.T) { opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA} + modules := configstack.TerraformModules{moduleA} err = modules.RunModules(context.Background(), opts, options.DefaultParallelism) require.NoError(t, err, "Unexpected error: %v", err) assert.False(t, aRan) @@ -261,9 +267,9 @@ func TestRunModulesReverseOrderOneModuleSuccess(t *testing.T) { t.Parallel() aRan := false - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", nil, &aRan), } @@ -271,7 +277,7 @@ func TestRunModulesReverseOrderOneModuleSuccess(t *testing.T) { opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA} + modules := configstack.TerraformModules{moduleA} err = modules.RunModulesReverseOrder(context.Background(), opts, options.DefaultParallelism) require.NoError(t, err, "Unexpected error: %v", err) assert.True(t, aRan) @@ -281,9 +287,9 @@ func TestRunModulesIgnoreOrderOneModuleSuccess(t *testing.T) { t.Parallel() aRan := false - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", nil, &aRan), } @@ -291,7 +297,7 @@ func TestRunModulesIgnoreOrderOneModuleSuccess(t *testing.T) { opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA} + modules := configstack.TerraformModules{moduleA} err = modules.RunModulesIgnoreOrder(context.Background(), opts, options.DefaultParallelism) require.NoError(t, err, "Unexpected error: %v", err) assert.True(t, aRan) @@ -302,9 +308,9 @@ func TestRunModulesOneModuleError(t *testing.T) { aRan := false expectedErrA := errors.New("Expected error for module a") - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", expectedErrA, &aRan), } @@ -312,7 +318,7 @@ func TestRunModulesOneModuleError(t *testing.T) { opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA} + modules := configstack.TerraformModules{moduleA} err = modules.RunModules(context.Background(), opts, options.DefaultParallelism) assertMultiErrorContains(t, err, expectedErrA) assert.True(t, aRan) @@ -323,9 +329,9 @@ func TestRunModulesReverseOrderOneModuleError(t *testing.T) { aRan := false expectedErrA := errors.New("Expected error for module a") - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", expectedErrA, &aRan), } @@ -333,7 +339,7 @@ func TestRunModulesReverseOrderOneModuleError(t *testing.T) { opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA} + modules := configstack.TerraformModules{moduleA} err = modules.RunModulesReverseOrder(context.Background(), opts, options.DefaultParallelism) assertMultiErrorContains(t, err, expectedErrA) assert.True(t, aRan) @@ -344,9 +350,9 @@ func TestRunModulesIgnoreOrderOneModuleError(t *testing.T) { aRan := false expectedErrA := errors.New("Expected error for module a") - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", expectedErrA, &aRan), } @@ -354,7 +360,7 @@ func TestRunModulesIgnoreOrderOneModuleError(t *testing.T) { opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA} + modules := configstack.TerraformModules{moduleA} err = modules.RunModulesIgnoreOrder(context.Background(), opts, options.DefaultParallelism) assertMultiErrorContains(t, err, expectedErrA) assert.True(t, aRan) @@ -364,25 +370,25 @@ func TestRunModulesMultipleModulesNoDependenciesSuccess(t *testing.T) { t.Parallel() aRan := false - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", nil, &aRan), } bRan := false - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "b", nil, &bRan), } cRan := false - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "c", nil, &cRan), } @@ -390,7 +396,7 @@ func TestRunModulesMultipleModulesNoDependenciesSuccess(t *testing.T) { opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA, moduleB, moduleC} + modules := configstack.TerraformModules{moduleA, moduleB, moduleC} err = modules.RunModules(context.Background(), opts, options.DefaultParallelism) require.NoError(t, err, "Unexpected error: %v", err) @@ -403,25 +409,25 @@ func TestRunModulesMultipleModulesNoDependenciesSuccessNoParallelism(t *testing. t.Parallel() aRan := false - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", nil, &aRan), } bRan := false - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "b", nil, &bRan), } cRan := false - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "c", nil, &cRan), } @@ -429,7 +435,7 @@ func TestRunModulesMultipleModulesNoDependenciesSuccessNoParallelism(t *testing. opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA, moduleB, moduleC} + modules := configstack.TerraformModules{moduleA, moduleB, moduleC} err = modules.RunModules(context.Background(), opts, 1) require.NoError(t, err, "Unexpected error: %v", err) @@ -442,25 +448,25 @@ func TestRunModulesReverseOrderMultipleModulesNoDependenciesSuccess(t *testing.T t.Parallel() aRan := false - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", nil, &aRan), } bRan := false - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "b", nil, &bRan), } cRan := false - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "c", nil, &cRan), } @@ -468,7 +474,7 @@ func TestRunModulesReverseOrderMultipleModulesNoDependenciesSuccess(t *testing.T opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA, moduleB, moduleC} + modules := configstack.TerraformModules{moduleA, moduleB, moduleC} err = modules.RunModulesReverseOrder(context.Background(), opts, options.DefaultParallelism) require.NoError(t, err, "Unexpected error: %v", err) @@ -481,25 +487,25 @@ func TestRunModulesIgnoreOrderMultipleModulesNoDependenciesSuccess(t *testing.T) t.Parallel() aRan := false - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", nil, &aRan), } bRan := false - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "b", nil, &bRan), } cRan := false - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "c", nil, &cRan), } @@ -507,7 +513,7 @@ func TestRunModulesIgnoreOrderMultipleModulesNoDependenciesSuccess(t *testing.T) opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA, moduleB, moduleC} + modules := configstack.TerraformModules{moduleA, moduleB, moduleC} err = modules.RunModulesIgnoreOrder(context.Background(), opts, options.DefaultParallelism) require.NoError(t, err, "Unexpected error: %v", err) @@ -520,26 +526,26 @@ func TestRunModulesMultipleModulesNoDependenciesOneFailure(t *testing.T) { t.Parallel() aRan := false - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", nil, &aRan), } bRan := false expectedErrB := errors.New("Expected error for module b") - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "b", expectedErrB, &bRan), } cRan := false - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "c", nil, &cRan), } @@ -547,7 +553,7 @@ func TestRunModulesMultipleModulesNoDependenciesOneFailure(t *testing.T) { opts, optsErr := options.NewTerragruntOptionsForTest("") require.NoError(t, optsErr) - modules := TerraformModules{moduleA, moduleB, moduleC} + modules := configstack.TerraformModules{moduleA, moduleB, moduleC} err := modules.RunModules(context.Background(), opts, options.DefaultParallelism) assertMultiErrorContains(t, err, expectedErrB) @@ -561,27 +567,27 @@ func TestRunModulesMultipleModulesNoDependenciesMultipleFailures(t *testing.T) { aRan := false expectedErrA := errors.New("Expected error for module a") - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", expectedErrA, &aRan), } bRan := false expectedErrB := errors.New("Expected error for module b") - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "b", expectedErrB, &bRan), } cRan := false expectedErrC := errors.New("Expected error for module c") - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "c", expectedErrC, &cRan), } @@ -589,7 +595,7 @@ func TestRunModulesMultipleModulesNoDependenciesMultipleFailures(t *testing.T) { opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA, moduleB, moduleC} + modules := configstack.TerraformModules{moduleA, moduleB, moduleC} err = modules.RunModules(context.Background(), opts, options.DefaultParallelism) assertMultiErrorContains(t, err, expectedErrA, expectedErrB, expectedErrC) @@ -602,25 +608,25 @@ func TestRunModulesMultipleModulesWithDependenciesSuccess(t *testing.T) { t.Parallel() aRan := false - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", nil, &aRan), } bRan := false - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "b", nil, &bRan), } cRan := false - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{moduleB}, + Dependencies: configstack.TerraformModules{moduleB}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "c", nil, &cRan), } @@ -628,7 +634,7 @@ func TestRunModulesMultipleModulesWithDependenciesSuccess(t *testing.T) { opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA, moduleB, moduleC} + modules := configstack.TerraformModules{moduleA, moduleB, moduleC} err = modules.RunModules(context.Background(), opts, options.DefaultParallelism) require.NoError(t, err, "Unexpected error: %v", err) @@ -641,34 +647,34 @@ func TestRunModulesMultipleModulesWithDependenciesWithAssumeAlreadyRanSuccess(t t.Parallel() aRan := false - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", nil, &aRan), } bRan := false - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "b", nil, &bRan), } cRan := false - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{moduleB}, + Dependencies: configstack.TerraformModules{moduleB}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "c", nil, &cRan), AssumeAlreadyApplied: true, } dRan := false - moduleD := &TerraformModule{ + moduleD := &configstack.TerraformModule{ Path: "d", - Dependencies: TerraformModules{moduleC}, + Dependencies: configstack.TerraformModules{moduleC}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "d", nil, &dRan), } @@ -676,7 +682,7 @@ func TestRunModulesMultipleModulesWithDependenciesWithAssumeAlreadyRanSuccess(t opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA, moduleB, moduleC, moduleD} + modules := configstack.TerraformModules{moduleA, moduleB, moduleC, moduleD} err = modules.RunModules(context.Background(), opts, options.DefaultParallelism) require.NoError(t, err, "Unexpected error: %v", err) @@ -690,25 +696,25 @@ func TestRunModulesReverseOrderMultipleModulesWithDependenciesSuccess(t *testing t.Parallel() aRan := false - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", nil, &aRan), } bRan := false - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "b", nil, &bRan), } cRan := false - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{moduleB}, + Dependencies: configstack.TerraformModules{moduleB}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "c", nil, &cRan), } @@ -716,7 +722,7 @@ func TestRunModulesReverseOrderMultipleModulesWithDependenciesSuccess(t *testing opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA, moduleB, moduleC} + modules := configstack.TerraformModules{moduleA, moduleB, moduleC} err = modules.RunModulesReverseOrder(context.Background(), opts, options.DefaultParallelism) require.NoError(t, err, "Unexpected error: %v", err) @@ -729,25 +735,25 @@ func TestRunModulesIgnoreOrderMultipleModulesWithDependenciesSuccess(t *testing. t.Parallel() aRan := false - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", nil, &aRan), } bRan := false - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "b", nil, &bRan), } cRan := false - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{moduleB}, + Dependencies: configstack.TerraformModules{moduleB}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "c", nil, &cRan), } @@ -755,7 +761,7 @@ func TestRunModulesIgnoreOrderMultipleModulesWithDependenciesSuccess(t *testing. opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA, moduleB, moduleC} + modules := configstack.TerraformModules{moduleA, moduleB, moduleC} err = modules.RunModulesIgnoreOrder(context.Background(), opts, options.DefaultParallelism) require.NoError(t, err, "Unexpected error: %v", err) @@ -768,36 +774,36 @@ func TestRunModulesMultipleModulesWithDependenciesOneFailure(t *testing.T) { t.Parallel() aRan := false - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", nil, &aRan), } bRan := false expectedErrB := errors.New("Expected error for module b") - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "b", expectedErrB, &bRan), } cRan := false - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{moduleB}, + Dependencies: configstack.TerraformModules{moduleB}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "c", nil, &cRan), } - expectedErrC := ProcessingModuleDependencyError{moduleC, moduleB, expectedErrB} + expectedErrC := configstack.ProcessingModuleDependencyError{moduleC, moduleB, expectedErrB} opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA, moduleB, moduleC} + modules := configstack.TerraformModules{moduleA, moduleB, moduleC} err = modules.RunModules(context.Background(), opts, options.DefaultParallelism) assertMultiErrorContains(t, err, expectedErrB, expectedErrC) @@ -812,9 +818,9 @@ func TestRunModulesMultipleModulesWithDependenciesOneFailureIgnoreDependencyErro aRan := false terragruntOptionsA := optionsWithMockTerragruntCommand(t, "a", nil, &aRan) terragruntOptionsA.IgnoreDependencyErrors = true - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: terragruntOptionsA, } @@ -823,9 +829,9 @@ func TestRunModulesMultipleModulesWithDependenciesOneFailureIgnoreDependencyErro expectedErrB := errors.New("Expected error for module b") terragruntOptionsB := optionsWithMockTerragruntCommand(t, "b", expectedErrB, &bRan) terragruntOptionsB.IgnoreDependencyErrors = true - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: terragruntOptionsB, } @@ -833,9 +839,9 @@ func TestRunModulesMultipleModulesWithDependenciesOneFailureIgnoreDependencyErro cRan := false terragruntOptionsC := optionsWithMockTerragruntCommand(t, "c", nil, &cRan) terragruntOptionsC.IgnoreDependencyErrors = true - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{moduleB}, + Dependencies: configstack.TerraformModules{moduleB}, Config: config.TerragruntConfig{}, TerragruntOptions: terragruntOptionsC, } @@ -843,7 +849,7 @@ func TestRunModulesMultipleModulesWithDependenciesOneFailureIgnoreDependencyErro opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA, moduleB, moduleC} + modules := configstack.TerraformModules{moduleA, moduleB, moduleC} err = modules.RunModules(context.Background(), opts, options.DefaultParallelism) assertMultiErrorContains(t, err, expectedErrB) @@ -856,36 +862,36 @@ func TestRunModulesReverseOrderMultipleModulesWithDependenciesOneFailure(t *test t.Parallel() aRan := false - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", nil, &aRan), } bRan := false expectedErrB := errors.New("Expected error for module b") - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "b", expectedErrB, &bRan), } cRan := false - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{moduleB}, + Dependencies: configstack.TerraformModules{moduleB}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "c", nil, &cRan), } - expectedErrA := ProcessingModuleDependencyError{moduleA, moduleB, expectedErrB} + expectedErrA := configstack.ProcessingModuleDependencyError{moduleA, moduleB, expectedErrB} opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA, moduleB, moduleC} + modules := configstack.TerraformModules{moduleA, moduleB, moduleC} err = modules.RunModulesReverseOrder(context.Background(), opts, options.DefaultParallelism) assertMultiErrorContains(t, err, expectedErrB, expectedErrA) @@ -898,26 +904,26 @@ func TestRunModulesIgnoreOrderMultipleModulesWithDependenciesOneFailure(t *testi t.Parallel() aRan := false - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", nil, &aRan), } bRan := false expectedErrB := errors.New("Expected error for module b") - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "b", expectedErrB, &bRan), } cRan := false - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{moduleB}, + Dependencies: configstack.TerraformModules{moduleB}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "c", nil, &cRan), } @@ -925,7 +931,7 @@ func TestRunModulesIgnoreOrderMultipleModulesWithDependenciesOneFailure(t *testi opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA, moduleB, moduleC} + modules := configstack.TerraformModules{moduleA, moduleB, moduleC} err = modules.RunModulesIgnoreOrder(context.Background(), opts, options.DefaultParallelism) assertMultiErrorContains(t, err, expectedErrB) @@ -939,36 +945,36 @@ func TestRunModulesMultipleModulesWithDependenciesMultipleFailures(t *testing.T) aRan := false expectedErrA := errors.New("Expected error for module a") - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", expectedErrA, &aRan), } bRan := false - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "b", nil, &bRan), } cRan := false - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{moduleB}, + Dependencies: configstack.TerraformModules{moduleB}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "c", nil, &cRan), } - expectedErrB := ProcessingModuleDependencyError{moduleB, moduleA, expectedErrA} - expectedErrC := ProcessingModuleDependencyError{moduleC, moduleB, expectedErrB} + expectedErrB := configstack.ProcessingModuleDependencyError{moduleB, moduleA, expectedErrA} + expectedErrC := configstack.ProcessingModuleDependencyError{moduleC, moduleB, expectedErrB} opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA, moduleB, moduleC} + modules := configstack.TerraformModules{moduleA, moduleB, moduleC} err = modules.RunModules(context.Background(), opts, options.DefaultParallelism) assertMultiErrorContains(t, err, expectedErrA, expectedErrB, expectedErrC) @@ -982,25 +988,25 @@ func TestRunModulesIgnoreOrderMultipleModulesWithDependenciesMultipleFailures(t aRan := false expectedErrA := errors.New("Expected error for module a") - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", expectedErrA, &aRan), } bRan := false - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "b", nil, &bRan), } cRan := false - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{moduleB}, + Dependencies: configstack.TerraformModules{moduleB}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "c", nil, &cRan), } @@ -1008,7 +1014,7 @@ func TestRunModulesIgnoreOrderMultipleModulesWithDependenciesMultipleFailures(t opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA, moduleB, moduleC} + modules := configstack.TerraformModules{moduleA, moduleB, moduleC} err = modules.RunModulesIgnoreOrder(context.Background(), opts, options.DefaultParallelism) assertMultiErrorContains(t, err, expectedErrA) @@ -1021,49 +1027,49 @@ func TestRunModulesMultipleModulesWithDependenciesLargeGraphAllSuccess(t *testin t.Parallel() aRan := false - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", nil, &aRan), } bRan := false - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "b", nil, &bRan), } cRan := false - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{moduleB}, + Dependencies: configstack.TerraformModules{moduleB}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "c", nil, &cRan), } dRan := false - moduleD := &TerraformModule{ + moduleD := &configstack.TerraformModule{ Path: "d", - Dependencies: TerraformModules{moduleA, moduleB, moduleC}, + Dependencies: configstack.TerraformModules{moduleA, moduleB, moduleC}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "d", nil, &dRan), } eRan := false - moduleE := &TerraformModule{ + moduleE := &configstack.TerraformModule{ Path: "e", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "e", nil, &eRan), } fRan := false - moduleF := &TerraformModule{ + moduleF := &configstack.TerraformModule{ Path: "f", - Dependencies: TerraformModules{moduleE, moduleD}, + Dependencies: configstack.TerraformModules{moduleE, moduleD}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "f", nil, &fRan), } @@ -1071,7 +1077,7 @@ func TestRunModulesMultipleModulesWithDependenciesLargeGraphAllSuccess(t *testin opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA, moduleB, moduleC, moduleD, moduleE, moduleF} + modules := configstack.TerraformModules{moduleA, moduleB, moduleC, moduleD, moduleE, moduleF} err = modules.RunModules(context.Background(), opts, options.DefaultParallelism) require.NoError(t, err) @@ -1087,70 +1093,70 @@ func TestRunModulesMultipleModulesWithDependenciesLargeGraphPartialFailure(t *te t.Parallel() aRan := false - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "large-graph-a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "large-graph-a", nil, &aRan), } bRan := false - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "large-graph-b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "large-graph-b", nil, &bRan), } cRan := false expectedErrC := errors.New("Expected error for module large-graph-c") - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "large-graph-c", - Dependencies: TerraformModules{moduleB}, + Dependencies: configstack.TerraformModules{moduleB}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "large-graph-c", expectedErrC, &cRan), } dRan := false - moduleD := &TerraformModule{ + moduleD := &configstack.TerraformModule{ Path: "large-graph-d", - Dependencies: TerraformModules{moduleA, moduleB, moduleC}, + Dependencies: configstack.TerraformModules{moduleA, moduleB, moduleC}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "large-graph-d", nil, &dRan), } eRan := false - moduleE := &TerraformModule{ + moduleE := &configstack.TerraformModule{ Path: "large-graph-e", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "large-graph-e", nil, &eRan), AssumeAlreadyApplied: true, } fRan := false - moduleF := &TerraformModule{ + moduleF := &configstack.TerraformModule{ Path: "large-graph-f", - Dependencies: TerraformModules{moduleE, moduleD}, + Dependencies: configstack.TerraformModules{moduleE, moduleD}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "large-graph-f", nil, &fRan), } gRan := false - moduleG := &TerraformModule{ + moduleG := &configstack.TerraformModule{ Path: "large-graph-g", - Dependencies: TerraformModules{moduleE}, + Dependencies: configstack.TerraformModules{moduleE}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "large-graph-g", nil, &gRan), } - expectedErrD := ProcessingModuleDependencyError{moduleD, moduleC, expectedErrC} - expectedErrF := ProcessingModuleDependencyError{moduleF, moduleD, expectedErrD} + expectedErrD := configstack.ProcessingModuleDependencyError{moduleD, moduleC, expectedErrC} + expectedErrF := configstack.ProcessingModuleDependencyError{moduleF, moduleD, expectedErrD} opts, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) - modules := TerraformModules{moduleA, moduleB, moduleC, moduleD, moduleE, moduleF, moduleG} + modules := configstack.TerraformModules{moduleA, moduleB, moduleC, moduleD, moduleE, moduleF, moduleG} err = modules.RunModules(context.Background(), opts, options.DefaultParallelism) assertMultiErrorContains(t, err, expectedErrC, expectedErrD, expectedErrF) @@ -1167,61 +1173,61 @@ func TestRunModulesReverseOrderMultipleModulesWithDependenciesLargeGraphPartialF t.Parallel() aRan := false - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "a", nil, &aRan), } bRan := false - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "b", nil, &bRan), } cRan := false expectedErrC := errors.New("Expected error for module c") - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{moduleB}, + Dependencies: configstack.TerraformModules{moduleB}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "c", expectedErrC, &cRan), } dRan := false - moduleD := &TerraformModule{ + moduleD := &configstack.TerraformModule{ Path: "d", - Dependencies: TerraformModules{moduleA, moduleB, moduleC}, + Dependencies: configstack.TerraformModules{moduleA, moduleB, moduleC}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "d", nil, &dRan), } eRan := false - moduleE := &TerraformModule{ + moduleE := &configstack.TerraformModule{ Path: "e", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "e", nil, &eRan), } fRan := false - moduleF := &TerraformModule{ + moduleF := &configstack.TerraformModule{ Path: "f", - Dependencies: TerraformModules{moduleE, moduleD}, + Dependencies: configstack.TerraformModules{moduleE, moduleD}, Config: config.TerragruntConfig{}, TerragruntOptions: optionsWithMockTerragruntCommand(t, "f", nil, &fRan), } - expectedErrB := ProcessingModuleDependencyError{moduleB, moduleC, expectedErrC} - expectedErrA := ProcessingModuleDependencyError{moduleA, moduleB, expectedErrB} + expectedErrB := configstack.ProcessingModuleDependencyError{moduleB, moduleC, expectedErrC} + expectedErrA := configstack.ProcessingModuleDependencyError{moduleA, moduleB, expectedErrB} opts, optsErr := options.NewTerragruntOptionsForTest("") require.NoError(t, optsErr) - modules := TerraformModules{moduleA, moduleB, moduleC, moduleD, moduleE, moduleF} + modules := configstack.TerraformModules{moduleA, moduleB, moduleC, moduleD, moduleE, moduleF} err := modules.RunModulesReverseOrder(context.Background(), opts, options.DefaultParallelism) assertMultiErrorContains(t, err, expectedErrC, expectedErrB, expectedErrA) diff --git a/configstack/running_module.go b/configstack/running_module.go index 6d9ebe9c7..3f005b364 100644 --- a/configstack/running_module.go +++ b/configstack/running_module.go @@ -35,32 +35,32 @@ type ModuleStatus int type DependencyOrder int // Represents a module we are trying to "run" (i.e. apply or destroy) as part of the apply-all or destroy-all command -type runningModule struct { +type RunningModule struct { Module *TerraformModule Status ModuleStatus Err error - DependencyDone chan *runningModule - Dependencies map[string]*runningModule - NotifyWhenDone []*runningModule + DependencyDone chan *RunningModule + Dependencies map[string]*RunningModule + NotifyWhenDone []*RunningModule FlagExcluded bool } // Create a new RunningModule struct for the given module. This will initialize all fields to reasonable defaults, // except for the Dependencies and NotifyWhenDone, both of which will be empty. You should fill these using a // function such as crossLinkDependencies. -func newRunningModule(module *TerraformModule) *runningModule { - return &runningModule{ +func newRunningModule(module *TerraformModule) *RunningModule { + return &RunningModule{ Module: module, Status: Waiting, - DependencyDone: make(chan *runningModule, channelSize), - Dependencies: map[string]*runningModule{}, - NotifyWhenDone: []*runningModule{}, + DependencyDone: make(chan *RunningModule, channelSize), + Dependencies: map[string]*RunningModule{}, + NotifyWhenDone: []*RunningModule{}, FlagExcluded: module.FlagExcluded, } } // Run a module once all of its dependencies have finished executing. -func (module *runningModule) runModuleWhenReady(ctx context.Context, opts *options.TerragruntOptions, semaphore chan struct{}) { +func (module *RunningModule) runModuleWhenReady(ctx context.Context, opts *options.TerragruntOptions, semaphore chan struct{}) { err := telemetry.Telemetry(ctx, opts, "wait_for_module_ready", map[string]interface{}{ "path": module.Module.Path, @@ -86,7 +86,7 @@ func (module *runningModule) runModuleWhenReady(ctx context.Context, opts *optio // Wait for all of this modules dependencies to finish executing. Return an error if any of those dependencies complete // with an error. Return immediately if this module has no dependencies. -func (module *runningModule) waitForDependencies() error { +func (module *RunningModule) waitForDependencies() error { module.Module.TerragruntOptions.Logger.Debugf("Module %s must wait for %d dependencies to finish", module.Module.Path, len(module.Dependencies)) for len(module.Dependencies) > 0 { doneDependency := <-module.DependencyDone @@ -108,7 +108,7 @@ func (module *runningModule) waitForDependencies() error { } // Run a module right now by executing the RunTerragrunt command of its TerragruntOptions field. -func (module *runningModule) runNow(ctx context.Context, rootOptions *options.TerragruntOptions) error { +func (module *RunningModule) runNow(ctx context.Context, rootOptions *options.TerragruntOptions) error { module.Status = Running if module.Module.AssumeAlreadyApplied { @@ -147,7 +147,7 @@ func (module *runningModule) runNow(ctx context.Context, rootOptions *options.Te } // Record that a module has finished executing and notify all of this module's dependencies -func (module *runningModule) moduleFinished(moduleErr error) { +func (module *RunningModule) moduleFinished(moduleErr error) { if moduleErr == nil { module.Module.TerragruntOptions.Logger.Debugf("Module %s has finished successfully!", module.Module.Path) } else { @@ -162,9 +162,9 @@ func (module *runningModule) moduleFinished(moduleErr error) { } } -type runningModules map[string]*runningModule +type RunningModules map[string]*RunningModule -func (modules runningModules) toTerraformModuleGroups(maxDepth int) []TerraformModules { +func (modules RunningModules) toTerraformModuleGroups(maxDepth int) []TerraformModules { // Walk the graph in run order, capturing which groups will run at each iteration. In each iteration, this pops out // the modules that have no dependencies and captures that as a run group. groups := []TerraformModules{} @@ -173,7 +173,7 @@ func (modules runningModules) toTerraformModuleGroups(maxDepth int) []TerraformM currentIterationDeploy := TerraformModules{} // next tracks which modules are being deferred to a later run. - next := runningModules{} + next := RunningModules{} // removeDep tracks which modules are run in the current iteration so that they need to be removed in the // dependency list for the next iteration. This is separately tracked from currentIterationDeploy for // convenience: this tracks the map key of the Dependencies attribute. @@ -229,7 +229,7 @@ func (modules runningModules) toTerraformModuleGroups(maxDepth int) []TerraformM // modules that depend on M into the NotifyWhenDone field. // - If dependencyOrder is ReverseOrder, do the reverse. // - If dependencyOrder is IgnoreOrder, do nothing. -func (modules runningModules) crossLinkDependencies(dependencyOrder DependencyOrder) (runningModules, error) { +func (modules RunningModules) crossLinkDependencies(dependencyOrder DependencyOrder) (RunningModules, error) { for _, module := range modules { for _, dependency := range module.Module.Dependencies { runningDependency, hasDependency := modules[dependency.Path] @@ -255,16 +255,16 @@ func (modules runningModules) crossLinkDependencies(dependencyOrder DependencyOr } // Return a cleaned-up map that only contains modules and dependencies that should not be excluded -func (modules runningModules) removeFlagExcluded() map[string]*runningModule { - var finalModules = make(map[string]*runningModule) +func (modules RunningModules) RemoveFlagExcluded() map[string]*RunningModule { + var finalModules = make(map[string]*RunningModule) for key, module := range modules { // Only add modules that should not be excluded if !module.FlagExcluded { - finalModules[key] = &runningModule{ + finalModules[key] = &RunningModule{ Module: module.Module, - Dependencies: make(map[string]*runningModule), + Dependencies: make(map[string]*RunningModule), DependencyDone: module.DependencyDone, Err: module.Err, NotifyWhenDone: module.NotifyWhenDone, @@ -286,13 +286,13 @@ func (modules runningModules) removeFlagExcluded() map[string]*runningModule { // Run the given map of module path to runningModule. To "run" a module, execute the RunTerragrunt command in its // TerragruntOptions object. The modules will be executed in an order determined by their inter-dependencies, using // as much concurrency as possible. -func (modules runningModules) runModules(ctx context.Context, opts *options.TerragruntOptions, parallelism int) error { +func (modules RunningModules) runModules(ctx context.Context, opts *options.TerragruntOptions, parallelism int) error { var waitGroup sync.WaitGroup var semaphore = make(chan struct{}, parallelism) // Make a semaphore from a buffered channel for _, module := range modules { waitGroup.Add(1) - go func(module *runningModule) { + go func(module *RunningModule) { defer waitGroup.Done() module.runModuleWhenReady(ctx, opts, semaphore) }(module) @@ -305,7 +305,7 @@ func (modules runningModules) runModules(ctx context.Context, opts *options.Terr // Collect the errors from the given modules and return a single error object to represent them, or nil if no errors // occurred -func (modules runningModules) collectErrors() error { +func (modules RunningModules) collectErrors() error { var result *multierror.Error for _, module := range modules { if module.Err != nil { diff --git a/configstack/running_module_test.go b/configstack/running_module_test.go index b9ac4d100..21850c321 100644 --- a/configstack/running_module_test.go +++ b/configstack/running_module_test.go @@ -1,9 +1,10 @@ -package configstack +package configstack_test import ( "testing" "github.com/gruntwork-io/terragrunt/config" + "github.com/gruntwork-io/terragrunt/configstack" "github.com/gruntwork-io/terragrunt/options" "github.com/stretchr/testify/assert" ) @@ -13,283 +14,283 @@ var mockOptions, _ = options.NewTerragruntOptionsForTest("running_module_test") func TestToRunningModulesNoModules(t *testing.T) { t.Parallel() - testToRunningModules(t, TerraformModules{}, NormalOrder, runningModules{}) + testToRunningModules(t, configstack.TerraformModules{}, configstack.NormalOrder, configstack.RunningModules{}) } func TestToRunningModulesOneModuleNoDependencies(t *testing.T) { t.Parallel() - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleA := &runningModule{ + runningModuleA := &configstack.RunningModule{ Module: moduleA, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{}, } - modules := TerraformModules{moduleA} - expected := runningModules{"a": runningModuleA} + modules := configstack.TerraformModules{moduleA} + expected := configstack.RunningModules{"a": runningModuleA} - testToRunningModules(t, modules, NormalOrder, expected) + testToRunningModules(t, modules, configstack.NormalOrder, expected) } func TestToRunningModulesTwoModulesNoDependencies(t *testing.T) { t.Parallel() - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleA := &runningModule{ + runningModuleA := &configstack.RunningModule{ Module: moduleA, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{}, } - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleB := &runningModule{ + runningModuleB := &configstack.RunningModule{ Module: moduleB, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{}, } - modules := TerraformModules{moduleA, moduleB} - expected := runningModules{"a": runningModuleA, "b": runningModuleB} + modules := configstack.TerraformModules{moduleA, moduleB} + expected := configstack.RunningModules{"a": runningModuleA, "b": runningModuleB} - testToRunningModules(t, modules, NormalOrder, expected) + testToRunningModules(t, modules, configstack.NormalOrder, expected) } func TestToRunningModulesTwoModulesWithDependencies(t *testing.T) { t.Parallel() - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleA := &runningModule{ + runningModuleA := &configstack.RunningModule{ Module: moduleA, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{}, } - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleB := &runningModule{ + runningModuleB := &configstack.RunningModule{ Module: moduleB, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{"a": runningModuleA}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{"a": runningModuleA}, + NotifyWhenDone: []*configstack.RunningModule{}, } - runningModuleA.NotifyWhenDone = []*runningModule{runningModuleB} + runningModuleA.NotifyWhenDone = []*configstack.RunningModule{runningModuleB} - modules := TerraformModules{moduleA, moduleB} - expected := runningModules{"a": runningModuleA, "b": runningModuleB} + modules := configstack.TerraformModules{moduleA, moduleB} + expected := configstack.RunningModules{"a": runningModuleA, "b": runningModuleB} - testToRunningModules(t, modules, NormalOrder, expected) + testToRunningModules(t, modules, configstack.NormalOrder, expected) } func TestToRunningModulesTwoModulesWithDependenciesReverseOrder(t *testing.T) { t.Parallel() - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleA := &runningModule{ + runningModuleA := &configstack.RunningModule{ Module: moduleA, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{}, } - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleB := &runningModule{ + runningModuleB := &configstack.RunningModule{ Module: moduleB, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{runningModuleA}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{runningModuleA}, } - runningModuleA.Dependencies = runningModules{"b": runningModuleB} + runningModuleA.Dependencies = configstack.RunningModules{"b": runningModuleB} - modules := TerraformModules{moduleA, moduleB} - expected := runningModules{"a": runningModuleA, "b": runningModuleB} + modules := configstack.TerraformModules{moduleA, moduleB} + expected := configstack.RunningModules{"a": runningModuleA, "b": runningModuleB} - testToRunningModules(t, modules, ReverseOrder, expected) + testToRunningModules(t, modules, configstack.ReverseOrder, expected) } func TestToRunningModulesTwoModulesWithDependenciesIgnoreOrder(t *testing.T) { t.Parallel() - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleA := &runningModule{ + runningModuleA := &configstack.RunningModule{ Module: moduleA, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{}, } - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleB := &runningModule{ + runningModuleB := &configstack.RunningModule{ Module: moduleB, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{}, } - modules := TerraformModules{moduleA, moduleB} - expected := runningModules{"a": runningModuleA, "b": runningModuleB} + modules := configstack.TerraformModules{moduleA, moduleB} + expected := configstack.RunningModules{"a": runningModuleA, "b": runningModuleB} - testToRunningModules(t, modules, IgnoreOrder, expected) + testToRunningModules(t, modules, configstack.IgnoreOrder, expected) } func TestToRunningModulesMultipleModulesWithAndWithoutDependencies(t *testing.T) { t.Parallel() - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleA := &runningModule{ + runningModuleA := &configstack.RunningModule{ Module: moduleA, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{}, } - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleB := &runningModule{ + runningModuleB := &configstack.RunningModule{ Module: moduleB, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{"a": runningModuleA}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{"a": runningModuleA}, + NotifyWhenDone: []*configstack.RunningModule{}, } - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleC := &runningModule{ + runningModuleC := &configstack.RunningModule{ Module: moduleC, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{"a": runningModuleA}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{"a": runningModuleA}, + NotifyWhenDone: []*configstack.RunningModule{}, } - moduleD := &TerraformModule{ + moduleD := &configstack.TerraformModule{ Path: "d", - Dependencies: TerraformModules{moduleC}, + Dependencies: configstack.TerraformModules{moduleC}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleD := &runningModule{ + runningModuleD := &configstack.RunningModule{ Module: moduleD, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{"c": runningModuleC}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{"c": runningModuleC}, + NotifyWhenDone: []*configstack.RunningModule{}, } - moduleE := &TerraformModule{ + moduleE := &configstack.TerraformModule{ Path: "e", - Dependencies: TerraformModules{moduleA, moduleB, moduleC, moduleD}, + Dependencies: configstack.TerraformModules{moduleA, moduleB, moduleC, moduleD}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleE := &runningModule{ + runningModuleE := &configstack.RunningModule{ Module: moduleE, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{ + Dependencies: configstack.RunningModules{ "a": runningModuleA, "b": runningModuleB, "c": runningModuleC, "d": runningModuleD, }, - NotifyWhenDone: []*runningModule{}, + NotifyWhenDone: []*configstack.RunningModule{}, } - runningModuleA.NotifyWhenDone = []*runningModule{runningModuleB, runningModuleC, runningModuleE} - runningModuleB.NotifyWhenDone = []*runningModule{runningModuleE} - runningModuleC.NotifyWhenDone = []*runningModule{runningModuleD, runningModuleE} - runningModuleD.NotifyWhenDone = []*runningModule{runningModuleE} + runningModuleA.NotifyWhenDone = []*configstack.RunningModule{runningModuleB, runningModuleC, runningModuleE} + runningModuleB.NotifyWhenDone = []*configstack.RunningModule{runningModuleE} + runningModuleC.NotifyWhenDone = []*configstack.RunningModule{runningModuleD, runningModuleE} + runningModuleD.NotifyWhenDone = []*configstack.RunningModule{runningModuleE} - modules := TerraformModules{moduleA, moduleB, moduleC, moduleD, moduleE} - expected := runningModules{ + modules := configstack.TerraformModules{moduleA, moduleB, moduleC, moduleD, moduleE} + expected := configstack.RunningModules{ "a": runningModuleA, "b": runningModuleB, "c": runningModuleC, @@ -297,94 +298,94 @@ func TestToRunningModulesMultipleModulesWithAndWithoutDependencies(t *testing.T) "e": runningModuleE, } - testToRunningModules(t, modules, NormalOrder, expected) + testToRunningModules(t, modules, configstack.NormalOrder, expected) } func TestToRunningModulesMultipleModulesWithAndWithoutDependenciesReverseOrder(t *testing.T) { t.Parallel() - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleA := &runningModule{ + runningModuleA := &configstack.RunningModule{ Module: moduleA, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{}, } - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleB := &runningModule{ + runningModuleB := &configstack.RunningModule{ Module: moduleB, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{runningModuleA}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{runningModuleA}, } - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleC := &runningModule{ + runningModuleC := &configstack.RunningModule{ Module: moduleC, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{runningModuleA}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{runningModuleA}, } - moduleD := &TerraformModule{ + moduleD := &configstack.TerraformModule{ Path: "d", - Dependencies: TerraformModules{moduleC}, + Dependencies: configstack.TerraformModules{moduleC}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleD := &runningModule{ + runningModuleD := &configstack.RunningModule{ Module: moduleD, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{runningModuleC}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{runningModuleC}, } - moduleE := &TerraformModule{ + moduleE := &configstack.TerraformModule{ Path: "e", - Dependencies: TerraformModules{moduleA, moduleB, moduleC, moduleD}, + Dependencies: configstack.TerraformModules{moduleA, moduleB, moduleC, moduleD}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleE := &runningModule{ + runningModuleE := &configstack.RunningModule{ Module: moduleE, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{runningModuleA, runningModuleB, runningModuleC, runningModuleD}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{runningModuleA, runningModuleB, runningModuleC, runningModuleD}, } - runningModuleA.Dependencies = runningModules{"b": runningModuleB, "c": runningModuleC, "e": runningModuleE} - runningModuleB.Dependencies = runningModules{"e": runningModuleE} - runningModuleC.Dependencies = runningModules{"d": runningModuleD, "e": runningModuleE} - runningModuleD.Dependencies = runningModules{"e": runningModuleE} + runningModuleA.Dependencies = configstack.RunningModules{"b": runningModuleB, "c": runningModuleC, "e": runningModuleE} + runningModuleB.Dependencies = configstack.RunningModules{"e": runningModuleE} + runningModuleC.Dependencies = configstack.RunningModules{"d": runningModuleD, "e": runningModuleE} + runningModuleD.Dependencies = configstack.RunningModules{"e": runningModuleE} - modules := TerraformModules{moduleA, moduleB, moduleC, moduleD, moduleE} - expected := runningModules{ + modules := configstack.TerraformModules{moduleA, moduleB, moduleC, moduleD, moduleE} + expected := configstack.RunningModules{ "a": runningModuleA, "b": runningModuleB, "c": runningModuleC, @@ -392,89 +393,89 @@ func TestToRunningModulesMultipleModulesWithAndWithoutDependenciesReverseOrder(t "e": runningModuleE, } - testToRunningModules(t, modules, ReverseOrder, expected) + testToRunningModules(t, modules, configstack.ReverseOrder, expected) } func TestToRunningModulesMultipleModulesWithAndWithoutDependenciesIgnoreOrder(t *testing.T) { t.Parallel() - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleA := &runningModule{ + runningModuleA := &configstack.RunningModule{ Module: moduleA, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{}, } - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleB := &runningModule{ + runningModuleB := &configstack.RunningModule{ Module: moduleB, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{}, } - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleC := &runningModule{ + runningModuleC := &configstack.RunningModule{ Module: moduleC, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{}, } - moduleD := &TerraformModule{ + moduleD := &configstack.TerraformModule{ Path: "d", - Dependencies: TerraformModules{moduleC}, + Dependencies: configstack.TerraformModules{moduleC}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleD := &runningModule{ + runningModuleD := &configstack.RunningModule{ Module: moduleD, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{}, } - moduleE := &TerraformModule{ + moduleE := &configstack.TerraformModule{ Path: "e", - Dependencies: TerraformModules{moduleA, moduleB, moduleC, moduleD}, + Dependencies: configstack.TerraformModules{moduleA, moduleB, moduleC, moduleD}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleE := &runningModule{ + runningModuleE := &configstack.RunningModule{ Module: moduleE, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{}, } - modules := TerraformModules{moduleA, moduleB, moduleC, moduleD, moduleE} - expected := runningModules{ + modules := configstack.TerraformModules{moduleA, moduleB, moduleC, moduleD, moduleE} + expected := configstack.RunningModules{ "a": runningModuleA, "b": runningModuleB, "c": runningModuleC, @@ -482,11 +483,11 @@ func TestToRunningModulesMultipleModulesWithAndWithoutDependenciesIgnoreOrder(t "e": runningModuleE, } - testToRunningModules(t, modules, IgnoreOrder, expected) + testToRunningModules(t, modules, configstack.IgnoreOrder, expected) } -func testToRunningModules(t *testing.T, modules TerraformModules, order DependencyOrder, expected runningModules) { - actual, err := modules.toRunningModules(order) +func testToRunningModules(t *testing.T, modules configstack.TerraformModules, order configstack.DependencyOrder, expected configstack.RunningModules) { + actual, err := modules.ToRunningModules(order) if assert.NoError(t, err, "For modules %v and order %v", modules, order) { assertRunningModuleMapsEqual(t, expected, actual, true, "For modules %v and order %v", modules, order) } @@ -495,90 +496,90 @@ func testToRunningModules(t *testing.T, modules TerraformModules, order Dependen func TestRemoveFlagExcludedNoExclude(t *testing.T) { t.Parallel() - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleA := &runningModule{ + runningModuleA := &configstack.RunningModule{ Module: moduleA, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{}, FlagExcluded: false, } - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleB := &runningModule{ + runningModuleB := &configstack.RunningModule{ Module: moduleB, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{"a": runningModuleA}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{"a": runningModuleA}, + NotifyWhenDone: []*configstack.RunningModule{}, FlagExcluded: false, } - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleC := &runningModule{ + runningModuleC := &configstack.RunningModule{ Module: moduleC, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{"a": runningModuleA}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{"a": runningModuleA}, + NotifyWhenDone: []*configstack.RunningModule{}, FlagExcluded: false, } - moduleD := &TerraformModule{ + moduleD := &configstack.TerraformModule{ Path: "d", - Dependencies: TerraformModules{moduleC}, + Dependencies: configstack.TerraformModules{moduleC}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleD := &runningModule{ + runningModuleD := &configstack.RunningModule{ Module: moduleD, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{"c": runningModuleC}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{"c": runningModuleC}, + NotifyWhenDone: []*configstack.RunningModule{}, FlagExcluded: false, } - moduleE := &TerraformModule{ + moduleE := &configstack.TerraformModule{ Path: "e", - Dependencies: TerraformModules{moduleB, moduleD}, + Dependencies: configstack.TerraformModules{moduleB, moduleD}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleE := &runningModule{ + runningModuleE := &configstack.RunningModule{ Module: moduleE, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{ + Dependencies: configstack.RunningModules{ "b": runningModuleB, "d": runningModuleD, }, - NotifyWhenDone: []*runningModule{}, + NotifyWhenDone: []*configstack.RunningModule{}, FlagExcluded: false, } - running_modules := runningModules{ + running_modules := configstack.RunningModules{ "a": runningModuleA, "b": runningModuleB, "c": runningModuleC, @@ -586,7 +587,7 @@ func TestRemoveFlagExcludedNoExclude(t *testing.T) { "e": runningModuleE, } - expected := runningModules{ + expected := configstack.RunningModules{ "a": runningModuleA, "b": runningModuleB, "c": runningModuleC, @@ -594,184 +595,184 @@ func TestRemoveFlagExcludedNoExclude(t *testing.T) { "e": runningModuleE, } - actual := running_modules.removeFlagExcluded() + actual := running_modules.RemoveFlagExcluded() assertRunningModuleMapsEqual(t, expected, actual, true) } func TestRemoveFlagExcludedOneExcludeNoDependencies(t *testing.T) { t.Parallel() - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleA := &runningModule{ + runningModuleA := &configstack.RunningModule{ Module: moduleA, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{}, FlagExcluded: false, } - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleB := &runningModule{ + runningModuleB := &configstack.RunningModule{ Module: moduleB, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{"a": runningModuleA}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{"a": runningModuleA}, + NotifyWhenDone: []*configstack.RunningModule{}, FlagExcluded: false, } - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleC := &runningModule{ + runningModuleC := &configstack.RunningModule{ Module: moduleC, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{"a": runningModuleA}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{"a": runningModuleA}, + NotifyWhenDone: []*configstack.RunningModule{}, FlagExcluded: true, } - running_modules := runningModules{ + running_modules := configstack.RunningModules{ "a": runningModuleA, "b": runningModuleB, "c": runningModuleC, } - expected := runningModules{ + expected := configstack.RunningModules{ "a": runningModuleA, "b": runningModuleB, } - actual := running_modules.removeFlagExcluded() + actual := running_modules.RemoveFlagExcluded() assertRunningModuleMapsEqual(t, expected, actual, true) } func TestRemoveFlagExcludedOneExcludeWithDependencies(t *testing.T) { t.Parallel() - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: "a", - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleA := &runningModule{ + runningModuleA := &configstack.RunningModule{ Module: moduleA, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{}, + NotifyWhenDone: []*configstack.RunningModule{}, FlagExcluded: false, } - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: "b", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleB := &runningModule{ + runningModuleB := &configstack.RunningModule{ Module: moduleB, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{"a": runningModuleA}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{"a": runningModuleA}, + NotifyWhenDone: []*configstack.RunningModule{}, FlagExcluded: false, } - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: "c", - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleC := &runningModule{ + runningModuleC := &configstack.RunningModule{ Module: moduleC, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{"a": runningModuleA}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{"a": runningModuleA}, + NotifyWhenDone: []*configstack.RunningModule{}, FlagExcluded: true, } - moduleD := &TerraformModule{ + moduleD := &configstack.TerraformModule{ Path: "d", - Dependencies: TerraformModules{moduleB, moduleC}, + Dependencies: configstack.TerraformModules{moduleB, moduleC}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleD := &runningModule{ + runningModuleD := &configstack.RunningModule{ Module: moduleD, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{ + Dependencies: configstack.RunningModules{ "b": runningModuleB, "c": runningModuleC, }, - NotifyWhenDone: []*runningModule{}, + NotifyWhenDone: []*configstack.RunningModule{}, FlagExcluded: false, } - moduleE := &TerraformModule{ + moduleE := &configstack.TerraformModule{ Path: "e", - Dependencies: TerraformModules{moduleB, moduleD}, + Dependencies: configstack.TerraformModules{moduleB, moduleD}, Config: config.TerragruntConfig{}, TerragruntOptions: mockOptions, } - runningModuleE := &runningModule{ + runningModuleE := &configstack.RunningModule{ Module: moduleE, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{ + Dependencies: configstack.RunningModules{ "b": runningModuleB, "d": runningModuleD, }, - NotifyWhenDone: []*runningModule{}, + NotifyWhenDone: []*configstack.RunningModule{}, FlagExcluded: false, } - running_modules := runningModules{ + running_modules := configstack.RunningModules{ "a": runningModuleA, "b": runningModuleB, "c": runningModuleC, "d": runningModuleD, "e": runningModuleE, } - actual := running_modules.removeFlagExcluded() + actual := running_modules.RemoveFlagExcluded() - _runningModuleD := &runningModule{ + _runningModuleD := &configstack.RunningModule{ Module: moduleD, - Status: Waiting, + Status: configstack.Waiting, Err: nil, - Dependencies: runningModules{"b": runningModuleB}, - NotifyWhenDone: []*runningModule{}, + Dependencies: configstack.RunningModules{"b": runningModuleB}, + NotifyWhenDone: []*configstack.RunningModule{}, FlagExcluded: false, } - expected := runningModules{ + expected := configstack.RunningModules{ "a": runningModuleA, "b": runningModuleB, "d": _runningModuleD, diff --git a/configstack/stack.go b/configstack/stack.go index 805771d3f..67c604b52 100644 --- a/configstack/stack.go +++ b/configstack/stack.go @@ -92,7 +92,7 @@ func (stack *Stack) String() string { // in reverse. func (stack *Stack) LogModuleDeployOrder(logger *logrus.Entry, terraformCommand string) error { outStr := fmt.Sprintf("The stack at %s will be processed in the following order for command %s:\n", stack.terragruntOptions.WorkingDir, terraformCommand) - runGraph, err := stack.getModuleRunGraph(terraformCommand) + runGraph, err := stack.GetModuleRunGraph(terraformCommand) if err != nil { return err } @@ -110,7 +110,7 @@ func (stack *Stack) LogModuleDeployOrder(logger *logrus.Entry, terraformCommand // JsonModuleDeployOrder will return the modules that will be deployed by a plan/apply operation, in the order // that the operations happen. func (stack *Stack) JsonModuleDeployOrder(terraformCommand string) (string, error) { - runGraph, err := stack.getModuleRunGraph(terraformCommand) + runGraph, err := stack.GetModuleRunGraph(terraformCommand) if err != nil { return "", errors.WithStackTrace(err) } @@ -246,20 +246,20 @@ func (stack *Stack) syncTerraformCliArgs(terragruntOptions *options.TerragruntOp } } -func (stack *Stack) toRunningModules(terraformCommand string) (runningModules, error) { +func (stack *Stack) toRunningModules(terraformCommand string) (RunningModules, error) { switch terraformCommand { case terraform.CommandNameDestroy: - return stack.Modules.toRunningModules(ReverseOrder) + return stack.Modules.ToRunningModules(ReverseOrder) default: - return stack.Modules.toRunningModules(NormalOrder) + return stack.Modules.ToRunningModules(NormalOrder) } } -// getModuleRunGraph converts the module list to a graph that shows the order in which the modules will be +// GetModuleRunGraph converts the module list to a graph that shows the order in which the modules will be // applied/destroyed. The return structure is a list of lists, where the nested list represents modules that can be // deployed concurrently, and the outer list indicates the order. This will only include those modules that do NOT have // the exclude flag set. -func (stack *Stack) getModuleRunGraph(terraformCommand string) ([]TerraformModules, error) { +func (stack *Stack) GetModuleRunGraph(terraformCommand string) ([]TerraformModules, error) { moduleRunGraph, err := stack.toRunningModules(terraformCommand) if err != nil { return nil, err diff --git a/configstack/stack_test.go b/configstack/stack_test.go index c8a5fd10c..651194d41 100644 --- a/configstack/stack_test.go +++ b/configstack/stack_test.go @@ -1,4 +1,4 @@ -package configstack +package configstack_test import ( "context" @@ -12,6 +12,7 @@ import ( "github.com/gruntwork-io/go-commons/errors" "github.com/gruntwork-io/terragrunt/codegen" "github.com/gruntwork-io/terragrunt/config" + "github.com/gruntwork-io/terragrunt/configstack" "github.com/gruntwork-io/terragrunt/options" "github.com/gruntwork-io/terragrunt/terraform" "github.com/gruntwork-io/terragrunt/util" @@ -40,7 +41,7 @@ func TestFindStackInSubfolders(t *testing.T) { terragruntOptions.WorkingDir = envFolder - stack, err := FindStackInSubfolders(context.Background(), terragruntOptions) + stack, err := configstack.FindStackInSubfolders(context.Background(), terragruntOptions) require.NoError(t, err) var modulePaths = make([]string, 0, len(stack.Modules)) @@ -62,12 +63,12 @@ func TestGetModuleRunGraphApplyOrder(t *testing.T) { t.Parallel() stack := createTestStack() - runGraph, err := stack.getModuleRunGraph(terraform.CommandNameApply) + runGraph, err := stack.GetModuleRunGraph(terraform.CommandNameApply) require.NoError(t, err) require.Equal( t, - []TerraformModules{ + []configstack.TerraformModules{ { stack.Modules[1], }, @@ -87,12 +88,12 @@ func TestGetModuleRunGraphDestroyOrder(t *testing.T) { t.Parallel() stack := createTestStack() - runGraph, err := stack.getModuleRunGraph(terraform.CommandNameDestroy) + runGraph, err := stack.GetModuleRunGraph(terraform.CommandNameDestroy) require.NoError(t, err) require.Equal( t, - []TerraformModules{ + []configstack.TerraformModules{ { stack.Modules[5], }, @@ -109,7 +110,7 @@ func TestGetModuleRunGraphDestroyOrder(t *testing.T) { } -func createTestStack() *Stack { +func createTestStack() *configstack.Stack { // Create the following module stack: // - account-baseline (excluded) // - vpc; depends on account-baseline @@ -118,34 +119,34 @@ func createTestStack() *Stack { // - redis; depends on vpc // - myapp; depends on mysql and redis basePath := "/stage/mystack" - accountBaseline := &TerraformModule{ + accountBaseline := &configstack.TerraformModule{ Path: filepath.Join(basePath, "account-baseline"), FlagExcluded: true, } - vpc := &TerraformModule{ + vpc := &configstack.TerraformModule{ Path: filepath.Join(basePath, "vpc"), - Dependencies: TerraformModules{accountBaseline}, + Dependencies: configstack.TerraformModules{accountBaseline}, } - lambda := &TerraformModule{ + lambda := &configstack.TerraformModule{ Path: filepath.Join(basePath, "lambda"), - Dependencies: TerraformModules{vpc}, + Dependencies: configstack.TerraformModules{vpc}, AssumeAlreadyApplied: true, } - mysql := &TerraformModule{ + mysql := &configstack.TerraformModule{ Path: filepath.Join(basePath, "mysql"), - Dependencies: TerraformModules{vpc}, + Dependencies: configstack.TerraformModules{vpc}, } - redis := &TerraformModule{ + redis := &configstack.TerraformModule{ Path: filepath.Join(basePath, "redis"), - Dependencies: TerraformModules{vpc}, + Dependencies: configstack.TerraformModules{vpc}, } - myapp := &TerraformModule{ + myapp := &configstack.TerraformModule{ Path: filepath.Join(basePath, "myapp"), - Dependencies: TerraformModules{mysql, redis}, + Dependencies: configstack.TerraformModules{mysql, redis}, } - stack := NewStack(&options.TerragruntOptions{WorkingDir: "/stage/mystack"}) - stack.Modules = TerraformModules{ + stack := configstack.NewStack(&options.TerragruntOptions{WorkingDir: "/stage/mystack"}) + stack.Modules = configstack.TerraformModules{ accountBaseline, vpc, lambda, @@ -195,8 +196,8 @@ func TestResolveTerraformModulesNoPaths(t *testing.T) { t.Parallel() configPaths := []string{} - expected := TerraformModules{} - stack := NewStack(mockOptions) + expected := configstack.TerraformModules{} + stack := configstack.NewStack(mockOptions) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -205,9 +206,9 @@ func TestResolveTerraformModulesNoPaths(t *testing.T) { func TestResolveTerraformModulesOneModuleNoDependencies(t *testing.T) { t.Parallel() - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-a"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{ Terraform: &config.TerraformConfig{Source: ptr("test")}, IsPartial: true, @@ -217,9 +218,9 @@ func TestResolveTerraformModulesOneModuleNoDependencies(t *testing.T) { } configPaths := []string{"../test/fixture-modules/module-a/" + config.DefaultTerragruntConfigPath} - expected := TerraformModules{moduleA} + expected := configstack.TerraformModules{moduleA} - stack := NewStack(mockOptions) + stack := configstack.NewStack(mockOptions) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -228,9 +229,9 @@ func TestResolveTerraformModulesOneModuleNoDependencies(t *testing.T) { func TestResolveTerraformModulesOneJsonModuleNoDependencies(t *testing.T) { t.Parallel() - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/json-module-a"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{ Terraform: &config.TerraformConfig{Source: ptr("test")}, IsPartial: true, @@ -240,9 +241,9 @@ func TestResolveTerraformModulesOneJsonModuleNoDependencies(t *testing.T) { } configPaths := []string{"../test/fixture-modules/json-module-a/" + config.DefaultTerragruntJsonConfigPath} - expected := TerraformModules{moduleA} + expected := configstack.TerraformModules{moduleA} - stack := NewStack(mockOptions) + stack := configstack.NewStack(mockOptions) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -251,9 +252,9 @@ func TestResolveTerraformModulesOneJsonModuleNoDependencies(t *testing.T) { func TestResolveTerraformModulesOneModuleWithIncludesNoDependencies(t *testing.T) { t.Parallel() - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-b/module-b-child"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{ Terraform: &config.TerraformConfig{Source: ptr("...")}, IsPartial: true, @@ -266,9 +267,9 @@ func TestResolveTerraformModulesOneModuleWithIncludesNoDependencies(t *testing.T } configPaths := []string{"../test/fixture-modules/module-b/module-b-child/" + config.DefaultTerragruntConfigPath} - expected := TerraformModules{moduleB} + expected := configstack.TerraformModules{moduleB} - stack := NewStack(mockOptions) + stack := configstack.NewStack(mockOptions) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -318,9 +319,9 @@ func TestResolveTerraformModulesReadConfigFromParentConfig(t *testing.T) { } } - moduleM := &TerraformModule{ + moduleM := &configstack.TerraformModule{ Path: canonical(t, childDir), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{ Terraform: &config.TerraformConfig{Source: ptr("...")}, IsPartial: true, @@ -349,12 +350,12 @@ func TestResolveTerraformModulesReadConfigFromParentConfig(t *testing.T) { }, }, } - expected := TerraformModules{moduleM} + expected := configstack.TerraformModules{moduleM} mockOptions, _ := options.NewTerragruntOptionsForTest("running_module_test") mockOptions.OriginalTerragruntConfigPath = childConfigPath - stack := NewStack(mockOptions, WithChildTerragruntConfig(childTerragruntConfig)) + stack := configstack.NewStack(mockOptions, configstack.WithChildTerragruntConfig(childTerragruntConfig)) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -363,9 +364,9 @@ func TestResolveTerraformModulesReadConfigFromParentConfig(t *testing.T) { func TestResolveTerraformModulesOneJsonModuleWithIncludesNoDependencies(t *testing.T) { t.Parallel() - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/json-module-b/module-b-child"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{ Terraform: &config.TerraformConfig{Source: ptr("...")}, IsPartial: true, @@ -378,9 +379,9 @@ func TestResolveTerraformModulesOneJsonModuleWithIncludesNoDependencies(t *testi } configPaths := []string{"../test/fixture-modules/json-module-b/module-b-child/" + config.DefaultTerragruntJsonConfigPath} - expected := TerraformModules{moduleB} + expected := configstack.TerraformModules{moduleB} - stack := NewStack(mockOptions) + stack := configstack.NewStack(mockOptions) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -389,9 +390,9 @@ func TestResolveTerraformModulesOneJsonModuleWithIncludesNoDependencies(t *testi func TestResolveTerraformModulesOneHclModuleWithIncludesNoDependencies(t *testing.T) { t.Parallel() - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/hcl-module-b/module-b-child"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{ Terraform: &config.TerraformConfig{Source: ptr("...")}, IsPartial: true, @@ -404,9 +405,9 @@ func TestResolveTerraformModulesOneHclModuleWithIncludesNoDependencies(t *testin } configPaths := []string{"../test/fixture-modules/hcl-module-b/module-b-child/" + config.DefaultTerragruntConfigPath} - expected := TerraformModules{moduleB} + expected := configstack.TerraformModules{moduleB} - stack := NewStack(mockOptions) + stack := configstack.NewStack(mockOptions) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -415,9 +416,9 @@ func TestResolveTerraformModulesOneHclModuleWithIncludesNoDependencies(t *testin func TestResolveTerraformModulesTwoModulesWithDependencies(t *testing.T) { t.Parallel() - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-a"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{ Terraform: &config.TerraformConfig{Source: ptr("test")}, IsPartial: true, @@ -426,9 +427,9 @@ func TestResolveTerraformModulesTwoModulesWithDependencies(t *testing.T) { TerragruntOptions: mockOptions.Clone(canonical(t, "../test/fixture-modules/module-a/"+config.DefaultTerragruntConfigPath)), } - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-c"), - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{ Dependencies: &config.ModuleDependencies{Paths: []string{"../module-a"}}, Terraform: &config.TerraformConfig{Source: ptr("temp")}, @@ -439,9 +440,9 @@ func TestResolveTerraformModulesTwoModulesWithDependencies(t *testing.T) { } configPaths := []string{"../test/fixture-modules/module-a/" + config.DefaultTerragruntConfigPath, "../test/fixture-modules/module-c/" + config.DefaultTerragruntConfigPath} - expected := TerraformModules{moduleA, moduleC} + expected := configstack.TerraformModules{moduleA, moduleC} - stack := NewStack(mockOptions) + stack := configstack.NewStack(mockOptions) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -450,9 +451,9 @@ func TestResolveTerraformModulesTwoModulesWithDependencies(t *testing.T) { func TestResolveTerraformModulesJsonModulesWithHclDependencies(t *testing.T) { t.Parallel() - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-a"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{ Terraform: &config.TerraformConfig{Source: ptr("test")}, IsPartial: true, @@ -461,9 +462,9 @@ func TestResolveTerraformModulesJsonModulesWithHclDependencies(t *testing.T) { TerragruntOptions: mockOptions.Clone(canonical(t, "../test/fixture-modules/module-a/"+config.DefaultTerragruntConfigPath)), } - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/json-module-c"), - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{ Dependencies: &config.ModuleDependencies{Paths: []string{"../module-a"}}, Terraform: &config.TerraformConfig{Source: ptr("temp")}, @@ -474,9 +475,9 @@ func TestResolveTerraformModulesJsonModulesWithHclDependencies(t *testing.T) { } configPaths := []string{"../test/fixture-modules/module-a/" + config.DefaultTerragruntConfigPath, "../test/fixture-modules/json-module-c/" + config.DefaultTerragruntJsonConfigPath} - expected := TerraformModules{moduleA, moduleC} + expected := configstack.TerraformModules{moduleA, moduleC} - stack := NewStack(mockOptions) + stack := configstack.NewStack(mockOptions) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -485,9 +486,9 @@ func TestResolveTerraformModulesJsonModulesWithHclDependencies(t *testing.T) { func TestResolveTerraformModulesHclModulesWithJsonDependencies(t *testing.T) { t.Parallel() - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/json-module-a"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{ Terraform: &config.TerraformConfig{Source: ptr("test")}, IsPartial: true, @@ -496,9 +497,9 @@ func TestResolveTerraformModulesHclModulesWithJsonDependencies(t *testing.T) { TerragruntOptions: mockOptions.Clone(canonical(t, "../test/fixture-modules/json-module-a/"+config.DefaultTerragruntJsonConfigPath)), } - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/hcl-module-c"), - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{ Dependencies: &config.ModuleDependencies{Paths: []string{"../json-module-a"}}, Terraform: &config.TerraformConfig{Source: ptr("temp")}, @@ -509,9 +510,9 @@ func TestResolveTerraformModulesHclModulesWithJsonDependencies(t *testing.T) { } configPaths := []string{"../test/fixture-modules/json-module-a/" + config.DefaultTerragruntJsonConfigPath, "../test/fixture-modules/hcl-module-c/" + config.DefaultTerragruntConfigPath} - expected := TerraformModules{moduleA, moduleC} + expected := configstack.TerraformModules{moduleA, moduleC} - stack := NewStack(mockOptions) + stack := configstack.NewStack(mockOptions) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -523,15 +524,15 @@ func TestResolveTerraformModulesTwoModulesWithDependenciesExcludedDirsWithDepend opts, _ := options.NewTerragruntOptionsForTest("running_module_test") opts.ExcludeDirs = []string{canonical(t, "../test/fixture-modules/module-a")} - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-a"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, TerragruntOptions: opts.Clone(canonical(t, "../test/fixture-modules/module-a/"+config.DefaultTerragruntConfigPath)), } - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-c"), - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{ Dependencies: &config.ModuleDependencies{Paths: []string{"../module-a"}}, Terraform: &config.TerraformConfig{Source: ptr("temp")}, @@ -543,12 +544,12 @@ func TestResolveTerraformModulesTwoModulesWithDependenciesExcludedDirsWithDepend configPaths := []string{"../test/fixture-modules/module-a/" + config.DefaultTerragruntConfigPath, "../test/fixture-modules/module-c/" + config.DefaultTerragruntConfigPath} - stack := NewStack(opts) + stack := configstack.NewStack(opts) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) // construct the expected list moduleA.FlagExcluded = true - expected := TerraformModules{moduleA, moduleC} + expected := configstack.TerraformModules{moduleA, moduleC} require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -560,15 +561,15 @@ func TestResolveTerraformModulesTwoModulesWithDependenciesExcludedDirsWithDepend opts, _ := options.NewTerragruntOptionsForTest("running_module_test") opts.ExcludeDirs = []string{canonical(t, "../test/fixture-modules/module-a")} - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-a"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, TerragruntOptions: opts.Clone(canonical(t, "../test/fixture-modules/module-a/"+config.DefaultTerragruntConfigPath)), } - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-c"), - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{ Dependencies: &config.ModuleDependencies{Paths: []string{"../module-a"}}, Terraform: &config.TerraformConfig{Source: ptr("temp")}, @@ -578,9 +579,9 @@ func TestResolveTerraformModulesTwoModulesWithDependenciesExcludedDirsWithDepend TerragruntOptions: opts.Clone(canonical(t, "../test/fixture-modules/module-c/"+config.DefaultTerragruntConfigPath)), } - moduleAbba := &TerraformModule{ + moduleAbba := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-abba"), - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{ Dependencies: &config.ModuleDependencies{Paths: []string{"../module-a"}}, Terraform: &config.TerraformConfig{Source: ptr("temp")}, @@ -592,12 +593,12 @@ func TestResolveTerraformModulesTwoModulesWithDependenciesExcludedDirsWithDepend configPaths := []string{"../test/fixture-modules/module-a/" + config.DefaultTerragruntConfigPath, "../test/fixture-modules/module-c/" + config.DefaultTerragruntConfigPath, "../test/fixture-modules/module-abba/" + config.DefaultTerragruntConfigPath} - stack := NewStack(opts) + stack := configstack.NewStack(opts) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) // construct the expected list moduleA.FlagExcluded = true - expected := TerraformModules{moduleA, moduleC, moduleAbba} + expected := configstack.TerraformModules{moduleA, moduleC, moduleAbba} require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -609,15 +610,15 @@ func TestResolveTerraformModulesTwoModulesWithDependenciesExcludedDirsWithDepend opts, _ := options.NewTerragruntOptionsForTest("running_module_test") opts.ExcludeDirs = globCanonical(t, "../test/fixture-modules/module-a*") - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-a"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, TerragruntOptions: opts.Clone(canonical(t, "../test/fixture-modules/module-a/"+config.DefaultTerragruntConfigPath)), } - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-c"), - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{ Dependencies: &config.ModuleDependencies{Paths: []string{"../module-a"}}, Terraform: &config.TerraformConfig{Source: ptr("temp")}, @@ -627,20 +628,20 @@ func TestResolveTerraformModulesTwoModulesWithDependenciesExcludedDirsWithDepend TerragruntOptions: opts.Clone(canonical(t, "../test/fixture-modules/module-c/"+config.DefaultTerragruntConfigPath)), } - moduleAbba := &TerraformModule{ + moduleAbba := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-abba"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, TerragruntOptions: opts.Clone(canonical(t, "../test/fixture-modules/module-abba/"+config.DefaultTerragruntConfigPath)), } configPaths := []string{"../test/fixture-modules/module-a/" + config.DefaultTerragruntConfigPath, "../test/fixture-modules/module-c/" + config.DefaultTerragruntConfigPath, "../test/fixture-modules/module-abba/" + config.DefaultTerragruntConfigPath} - stack := NewStack(opts) + stack := configstack.NewStack(opts) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) // construct the expected list moduleA.FlagExcluded = true moduleAbba.FlagExcluded = true - expected := TerraformModules{moduleA, moduleC, moduleAbba} + expected := configstack.TerraformModules{moduleA, moduleC, moduleAbba} require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -652,9 +653,9 @@ func TestResolveTerraformModulesTwoModulesWithDependenciesExcludedDirsWithNoDepe opts, _ := options.NewTerragruntOptionsForTest("running_module_test") opts.ExcludeDirs = []string{canonical(t, "../test/fixture-modules/module-c")} - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-a"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{ Terraform: &config.TerraformConfig{Source: ptr("test")}, IsPartial: true, @@ -663,19 +664,19 @@ func TestResolveTerraformModulesTwoModulesWithDependenciesExcludedDirsWithNoDepe TerragruntOptions: opts.Clone(canonical(t, "../test/fixture-modules/module-a/"+config.DefaultTerragruntConfigPath)), } - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-c"), TerragruntOptions: opts.Clone(canonical(t, "../test/fixture-modules/module-c/"+config.DefaultTerragruntConfigPath)), } configPaths := []string{"../test/fixture-modules/module-a/" + config.DefaultTerragruntConfigPath, "../test/fixture-modules/module-c/" + config.DefaultTerragruntConfigPath} - stack := NewStack(opts) + stack := configstack.NewStack(opts) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) // construct the expected list moduleC.FlagExcluded = true - expected := TerraformModules{moduleA, moduleC} + expected := configstack.TerraformModules{moduleA, moduleC} require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -687,9 +688,9 @@ func TestResolveTerraformModulesTwoModulesWithDependenciesIncludedDirsWithDepend opts, _ := options.NewTerragruntOptionsForTest("running_module_test") opts.IncludeDirs = []string{canonical(t, "../test/fixture-modules/module-c")} - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-a"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{ Terraform: &config.TerraformConfig{Source: ptr("test")}, IsPartial: true, @@ -698,9 +699,9 @@ func TestResolveTerraformModulesTwoModulesWithDependenciesIncludedDirsWithDepend TerragruntOptions: opts.Clone(canonical(t, "../test/fixture-modules/module-a/"+config.DefaultTerragruntConfigPath)), } - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-c"), - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{ Dependencies: &config.ModuleDependencies{Paths: []string{"../module-a"}}, Terraform: &config.TerraformConfig{Source: ptr("temp")}, @@ -712,12 +713,12 @@ func TestResolveTerraformModulesTwoModulesWithDependenciesIncludedDirsWithDepend configPaths := []string{"../test/fixture-modules/module-a/" + config.DefaultTerragruntConfigPath, "../test/fixture-modules/module-c/" + config.DefaultTerragruntConfigPath} - stack := NewStack(opts) + stack := configstack.NewStack(opts) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) // construct the expected list moduleA.FlagExcluded = false - expected := TerraformModules{moduleA, moduleC} + expected := configstack.TerraformModules{moduleA, moduleC} require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -730,9 +731,9 @@ func TestResolveTerraformModulesTwoModulesWithDependenciesIncludedDirsWithNoDepe opts.IncludeDirs = []string{canonical(t, "../test/fixture-modules/module-a")} opts.ExcludeByDefault = true - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-a"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{ Terraform: &config.TerraformConfig{Source: ptr("test")}, IsPartial: true, @@ -741,9 +742,9 @@ func TestResolveTerraformModulesTwoModulesWithDependenciesIncludedDirsWithNoDepe TerragruntOptions: opts.Clone(canonical(t, "../test/fixture-modules/module-a/"+config.DefaultTerragruntConfigPath)), } - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-c"), - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{ Dependencies: &config.ModuleDependencies{Paths: []string{"../module-a"}}, Terraform: &config.TerraformConfig{Source: ptr("temp")}, @@ -755,12 +756,12 @@ func TestResolveTerraformModulesTwoModulesWithDependenciesIncludedDirsWithNoDepe configPaths := []string{"../test/fixture-modules/module-a/" + config.DefaultTerragruntConfigPath, "../test/fixture-modules/module-c/" + config.DefaultTerragruntConfigPath} - stack := NewStack(opts) + stack := configstack.NewStack(opts) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) // construct the expected list moduleC.FlagExcluded = true - expected := TerraformModules{moduleA, moduleC} + expected := configstack.TerraformModules{moduleA, moduleC} require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -773,9 +774,9 @@ func TestResolveTerraformModulesTwoModulesWithDependenciesIncludedDirsWithDepend opts.IncludeDirs = []string{canonical(t, "../test/fixture-modules/module-c"), canonical(t, "../test/fixture-modules/module-f")} opts.ExcludeDirs = []string{canonical(t, "../test/fixture-modules/module-f")} - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-a"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{ Terraform: &config.TerraformConfig{Source: ptr("test")}, IsPartial: true, @@ -784,9 +785,9 @@ func TestResolveTerraformModulesTwoModulesWithDependenciesIncludedDirsWithDepend TerragruntOptions: opts.Clone(canonical(t, "../test/fixture-modules/module-a/"+config.DefaultTerragruntConfigPath)), } - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-c"), - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{ Dependencies: &config.ModuleDependencies{Paths: []string{"../module-a"}}, Terraform: &config.TerraformConfig{Source: ptr("temp")}, @@ -796,21 +797,21 @@ func TestResolveTerraformModulesTwoModulesWithDependenciesIncludedDirsWithDepend TerragruntOptions: opts.Clone(canonical(t, "../test/fixture-modules/module-c/"+config.DefaultTerragruntConfigPath)), } - moduleF := &TerraformModule{ + moduleF := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-f"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, TerragruntOptions: mockOptions.Clone(canonical(t, "../test/fixture-modules/module-f/"+config.DefaultTerragruntConfigPath)), AssumeAlreadyApplied: false, } configPaths := []string{"../test/fixture-modules/module-a/" + config.DefaultTerragruntConfigPath, "../test/fixture-modules/module-c/" + config.DefaultTerragruntConfigPath, "../test/fixture-modules/module-f/" + config.DefaultTerragruntConfigPath} - stack := NewStack(opts) + stack := configstack.NewStack(opts) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) // construct the expected list moduleF.FlagExcluded = true - expected := TerraformModules{moduleA, moduleC, moduleF} + expected := configstack.TerraformModules{moduleA, moduleC, moduleF} require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -819,9 +820,9 @@ func TestResolveTerraformModulesTwoModulesWithDependenciesIncludedDirsWithDepend func TestResolveTerraformModulesMultipleModulesWithDependencies(t *testing.T) { t.Parallel() - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-a"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{ Terraform: &config.TerraformConfig{Source: ptr("test")}, IsPartial: true, @@ -830,9 +831,9 @@ func TestResolveTerraformModulesMultipleModulesWithDependencies(t *testing.T) { TerragruntOptions: mockOptions.Clone(canonical(t, "../test/fixture-modules/module-a/"+config.DefaultTerragruntConfigPath)), } - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-b/module-b-child"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{ Terraform: &config.TerraformConfig{Source: ptr("...")}, IsPartial: true, @@ -844,9 +845,9 @@ func TestResolveTerraformModulesMultipleModulesWithDependencies(t *testing.T) { TerragruntOptions: mockOptions.Clone(canonical(t, "../test/fixture-modules/module-b/module-b-child/"+config.DefaultTerragruntConfigPath)), } - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-c"), - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{ Dependencies: &config.ModuleDependencies{Paths: []string{"../module-a"}}, Terraform: &config.TerraformConfig{Source: ptr("temp")}, @@ -856,9 +857,9 @@ func TestResolveTerraformModulesMultipleModulesWithDependencies(t *testing.T) { TerragruntOptions: mockOptions.Clone(canonical(t, "../test/fixture-modules/module-c/"+config.DefaultTerragruntConfigPath)), } - moduleD := &TerraformModule{ + moduleD := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-d"), - Dependencies: TerraformModules{moduleA, moduleB, moduleC}, + Dependencies: configstack.TerraformModules{moduleA, moduleB, moduleC}, Config: config.TerragruntConfig{ Dependencies: &config.ModuleDependencies{Paths: []string{"../module-a", "../module-b/module-b-child", "../module-c"}}, IsPartial: true, @@ -868,9 +869,9 @@ func TestResolveTerraformModulesMultipleModulesWithDependencies(t *testing.T) { } configPaths := []string{"../test/fixture-modules/module-a/" + config.DefaultTerragruntConfigPath, "../test/fixture-modules/module-b/module-b-child/" + config.DefaultTerragruntConfigPath, "../test/fixture-modules/module-c/" + config.DefaultTerragruntConfigPath, "../test/fixture-modules/module-d/" + config.DefaultTerragruntConfigPath} - expected := TerraformModules{moduleA, moduleB, moduleC, moduleD} + expected := configstack.TerraformModules{moduleA, moduleB, moduleC, moduleD} - stack := NewStack(mockOptions) + stack := configstack.NewStack(mockOptions) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -879,9 +880,9 @@ func TestResolveTerraformModulesMultipleModulesWithDependencies(t *testing.T) { func TestResolveTerraformModulesMultipleModulesWithMixedDependencies(t *testing.T) { t.Parallel() - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-a"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{ Terraform: &config.TerraformConfig{Source: ptr("test")}, IsPartial: true, @@ -890,9 +891,9 @@ func TestResolveTerraformModulesMultipleModulesWithMixedDependencies(t *testing. TerragruntOptions: mockOptions.Clone(canonical(t, "../test/fixture-modules/module-a/"+config.DefaultTerragruntConfigPath)), } - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/json-module-b/module-b-child"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{ Terraform: &config.TerraformConfig{Source: ptr("...")}, IsPartial: true, @@ -904,9 +905,9 @@ func TestResolveTerraformModulesMultipleModulesWithMixedDependencies(t *testing. TerragruntOptions: mockOptions.Clone(canonical(t, "../test/fixture-modules/json-module-b/module-b-child/"+config.DefaultTerragruntJsonConfigPath)), } - moduleC := &TerraformModule{ + moduleC := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-c"), - Dependencies: TerraformModules{moduleA}, + Dependencies: configstack.TerraformModules{moduleA}, Config: config.TerragruntConfig{ Dependencies: &config.ModuleDependencies{Paths: []string{"../module-a"}}, Terraform: &config.TerraformConfig{Source: ptr("temp")}, @@ -916,9 +917,9 @@ func TestResolveTerraformModulesMultipleModulesWithMixedDependencies(t *testing. TerragruntOptions: mockOptions.Clone(canonical(t, "../test/fixture-modules/module-c/"+config.DefaultTerragruntConfigPath)), } - moduleD := &TerraformModule{ + moduleD := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/json-module-d"), - Dependencies: TerraformModules{moduleA, moduleB, moduleC}, + Dependencies: configstack.TerraformModules{moduleA, moduleB, moduleC}, Config: config.TerragruntConfig{ Dependencies: &config.ModuleDependencies{Paths: []string{"../module-a", "../json-module-b/module-b-child", "../module-c"}}, IsPartial: true, @@ -928,9 +929,9 @@ func TestResolveTerraformModulesMultipleModulesWithMixedDependencies(t *testing. } configPaths := []string{"../test/fixture-modules/module-a/" + config.DefaultTerragruntConfigPath, "../test/fixture-modules/json-module-b/module-b-child/" + config.DefaultTerragruntJsonConfigPath, "../test/fixture-modules/module-c/" + config.DefaultTerragruntConfigPath, "../test/fixture-modules/json-module-d/" + config.DefaultTerragruntJsonConfigPath} - expected := TerraformModules{moduleA, moduleB, moduleC, moduleD} + expected := configstack.TerraformModules{moduleA, moduleB, moduleC, moduleD} - stack := NewStack(mockOptions) + stack := configstack.NewStack(mockOptions) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -939,9 +940,9 @@ func TestResolveTerraformModulesMultipleModulesWithMixedDependencies(t *testing. func TestResolveTerraformModulesMultipleModulesWithDependenciesWithIncludes(t *testing.T) { t.Parallel() - moduleA := &TerraformModule{ + moduleA := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-a"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{ Terraform: &config.TerraformConfig{Source: ptr("test")}, IsPartial: true, @@ -950,9 +951,9 @@ func TestResolveTerraformModulesMultipleModulesWithDependenciesWithIncludes(t *t TerragruntOptions: mockOptions.Clone(canonical(t, "../test/fixture-modules/module-a/"+config.DefaultTerragruntConfigPath)), } - moduleB := &TerraformModule{ + moduleB := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-b/module-b-child"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{ Terraform: &config.TerraformConfig{Source: ptr("...")}, IsPartial: true, @@ -964,9 +965,9 @@ func TestResolveTerraformModulesMultipleModulesWithDependenciesWithIncludes(t *t TerragruntOptions: mockOptions.Clone(canonical(t, "../test/fixture-modules/module-b/module-b-child/"+config.DefaultTerragruntConfigPath)), } - moduleE := &TerraformModule{ + moduleE := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-e/module-e-child"), - Dependencies: TerraformModules{moduleA, moduleB}, + Dependencies: configstack.TerraformModules{moduleA, moduleB}, Config: config.TerragruntConfig{ Dependencies: &config.ModuleDependencies{Paths: []string{"../../module-a", "../../module-b/module-b-child"}}, Terraform: &config.TerraformConfig{Source: ptr("test")}, @@ -980,9 +981,9 @@ func TestResolveTerraformModulesMultipleModulesWithDependenciesWithIncludes(t *t } configPaths := []string{"../test/fixture-modules/module-a/" + config.DefaultTerragruntConfigPath, "../test/fixture-modules/module-b/module-b-child/" + config.DefaultTerragruntConfigPath, "../test/fixture-modules/module-e/module-e-child/" + config.DefaultTerragruntConfigPath} - expected := TerraformModules{moduleA, moduleB, moduleE} + expected := configstack.TerraformModules{moduleA, moduleB, moduleE} - stack := NewStack(mockOptions) + stack := configstack.NewStack(mockOptions) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -991,9 +992,9 @@ func TestResolveTerraformModulesMultipleModulesWithDependenciesWithIncludes(t *t func TestResolveTerraformModulesMultipleModulesWithExternalDependencies(t *testing.T) { t.Parallel() - moduleF := &TerraformModule{ + moduleF := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-f"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{ IsPartial: true, GenerateConfigs: make(map[string]codegen.GenerateConfig), @@ -1002,9 +1003,9 @@ func TestResolveTerraformModulesMultipleModulesWithExternalDependencies(t *testi AssumeAlreadyApplied: true, } - moduleG := &TerraformModule{ + moduleG := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-g"), - Dependencies: TerraformModules{moduleF}, + Dependencies: configstack.TerraformModules{moduleF}, Config: config.TerragruntConfig{ Dependencies: &config.ModuleDependencies{Paths: []string{"../module-f"}}, Terraform: &config.TerraformConfig{Source: ptr("test")}, @@ -1015,9 +1016,9 @@ func TestResolveTerraformModulesMultipleModulesWithExternalDependencies(t *testi } configPaths := []string{"../test/fixture-modules/module-g/" + config.DefaultTerragruntConfigPath} - expected := TerraformModules{moduleF, moduleG} + expected := configstack.TerraformModules{moduleF, moduleG} - stack := NewStack(mockOptions) + stack := configstack.NewStack(mockOptions) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -1026,9 +1027,9 @@ func TestResolveTerraformModulesMultipleModulesWithExternalDependencies(t *testi func TestResolveTerraformModulesMultipleModulesWithNestedExternalDependencies(t *testing.T) { t.Parallel() - moduleH := &TerraformModule{ + moduleH := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-h"), - Dependencies: TerraformModules{}, + Dependencies: configstack.TerraformModules{}, Config: config.TerragruntConfig{ IsPartial: true, GenerateConfigs: make(map[string]codegen.GenerateConfig), @@ -1037,9 +1038,9 @@ func TestResolveTerraformModulesMultipleModulesWithNestedExternalDependencies(t AssumeAlreadyApplied: true, } - moduleI := &TerraformModule{ + moduleI := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-i"), - Dependencies: TerraformModules{moduleH}, + Dependencies: configstack.TerraformModules{moduleH}, Config: config.TerragruntConfig{ Dependencies: &config.ModuleDependencies{Paths: []string{"../module-h"}}, IsPartial: true, @@ -1049,9 +1050,9 @@ func TestResolveTerraformModulesMultipleModulesWithNestedExternalDependencies(t AssumeAlreadyApplied: true, } - moduleJ := &TerraformModule{ + moduleJ := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-j"), - Dependencies: TerraformModules{moduleI}, + Dependencies: configstack.TerraformModules{moduleI}, Config: config.TerragruntConfig{ Dependencies: &config.ModuleDependencies{Paths: []string{"../module-i"}}, Terraform: &config.TerraformConfig{Source: ptr("temp")}, @@ -1061,9 +1062,9 @@ func TestResolveTerraformModulesMultipleModulesWithNestedExternalDependencies(t TerragruntOptions: mockOptions.Clone(canonical(t, "../test/fixture-modules/module-j/"+config.DefaultTerragruntConfigPath)), } - moduleK := &TerraformModule{ + moduleK := &configstack.TerraformModule{ Path: canonical(t, "../test/fixture-modules/module-k"), - Dependencies: TerraformModules{moduleH}, + Dependencies: configstack.TerraformModules{moduleH}, Config: config.TerragruntConfig{ Dependencies: &config.ModuleDependencies{Paths: []string{"../module-h"}}, Terraform: &config.TerraformConfig{Source: ptr("fire")}, @@ -1074,9 +1075,9 @@ func TestResolveTerraformModulesMultipleModulesWithNestedExternalDependencies(t } configPaths := []string{"../test/fixture-modules/module-j/" + config.DefaultTerragruntConfigPath, "../test/fixture-modules/module-k/" + config.DefaultTerragruntConfigPath} - expected := TerraformModules{moduleH, moduleI, moduleJ, moduleK} + expected := configstack.TerraformModules{moduleH, moduleI, moduleJ, moduleK} - stack := NewStack(mockOptions) + stack := configstack.NewStack(mockOptions) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) require.NoError(t, actualErr) assertModuleListsEqual(t, expected, actualModules) @@ -1087,12 +1088,11 @@ func TestResolveTerraformModulesInvalidPaths(t *testing.T) { configPaths := []string{"../test/fixture-modules/module-missing-dependency/" + config.DefaultTerragruntConfigPath} - stack := NewStack(mockOptions) + stack := configstack.NewStack(mockOptions) _, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) require.Error(t, actualErr) - var processingModuleError ProcessingModuleError - // underlying, ok := errors.Unwrap(actualErr).(ProcessingModuleError) + var processingModuleError configstack.ProcessingModuleError ok := goErrors.As(actualErr, &processingModuleError) require.True(t, ok) @@ -1104,21 +1104,23 @@ func TestResolveTerraformModuleNoTerraformConfig(t *testing.T) { t.Parallel() configPaths := []string{"../test/fixture-modules/module-l/" + config.DefaultTerragruntConfigPath} - expected := TerraformModules{} + expected := configstack.TerraformModules{} - stack := NewStack(mockOptions) + stack := configstack.NewStack(mockOptions) actualModules, actualErr := stack.ResolveTerraformModules(context.Background(), configPaths) require.NoError(t, actualErr, "Unexpected error: %v", actualErr) assertModuleListsEqual(t, expected, actualModules) } func TestBasicDependency(t *testing.T) { - moduleC := &TerraformModule{Path: "C", Dependencies: TerraformModules{}} - moduleB := &TerraformModule{Path: "B", Dependencies: TerraformModules{moduleC}} - moduleA := &TerraformModule{Path: "A", Dependencies: TerraformModules{moduleB}} + t.Parallel() + + moduleC := &configstack.TerraformModule{Path: "C", Dependencies: configstack.TerraformModules{}} + moduleB := &configstack.TerraformModule{Path: "B", Dependencies: configstack.TerraformModules{moduleC}} + moduleA := &configstack.TerraformModule{Path: "A", Dependencies: configstack.TerraformModules{moduleB}} - stack := NewStack(&options.TerragruntOptions{WorkingDir: "test-stack"}) - stack.Modules = TerraformModules{moduleA, moduleB, moduleC} + stack := configstack.NewStack(&options.TerragruntOptions{WorkingDir: "test-stack"}) + stack.Modules = configstack.TerraformModules{moduleA, moduleB, moduleC} expected := map[string][]string{ "B": {"A"}, @@ -1132,14 +1134,16 @@ func TestBasicDependency(t *testing.T) { } } func TestNestedDependencies(t *testing.T) { - moduleD := &TerraformModule{Path: "D", Dependencies: TerraformModules{}} - moduleC := &TerraformModule{Path: "C", Dependencies: TerraformModules{moduleD}} - moduleB := &TerraformModule{Path: "B", Dependencies: TerraformModules{moduleC}} - moduleA := &TerraformModule{Path: "A", Dependencies: TerraformModules{moduleB}} + t.Parallel() + + moduleD := &configstack.TerraformModule{Path: "D", Dependencies: configstack.TerraformModules{}} + moduleC := &configstack.TerraformModule{Path: "C", Dependencies: configstack.TerraformModules{moduleD}} + moduleB := &configstack.TerraformModule{Path: "B", Dependencies: configstack.TerraformModules{moduleC}} + moduleA := &configstack.TerraformModule{Path: "A", Dependencies: configstack.TerraformModules{moduleB}} // Create a mock stack - stack := NewStack(&options.TerragruntOptions{WorkingDir: "nested-stack"}) - stack.Modules = TerraformModules{moduleA, moduleB, moduleC, moduleD} + stack := configstack.NewStack(&options.TerragruntOptions{WorkingDir: "nested-stack"}) + stack.Modules = configstack.TerraformModules{moduleA, moduleB, moduleC, moduleD} // Expected result expected := map[string][]string{ @@ -1157,17 +1161,19 @@ func TestNestedDependencies(t *testing.T) { } func TestCircularDependencies(t *testing.T) { + t.Parallel() + // Mock modules with circular dependencies - moduleA := &TerraformModule{Path: "A"} - moduleB := &TerraformModule{Path: "B"} - moduleC := &TerraformModule{Path: "C"} + moduleA := &configstack.TerraformModule{Path: "A"} + moduleB := &configstack.TerraformModule{Path: "B"} + moduleC := &configstack.TerraformModule{Path: "C"} - moduleA.Dependencies = TerraformModules{moduleB} - moduleB.Dependencies = TerraformModules{moduleC} - moduleC.Dependencies = TerraformModules{moduleA} // Circular dependency + moduleA.Dependencies = configstack.TerraformModules{moduleB} + moduleB.Dependencies = configstack.TerraformModules{moduleC} + moduleC.Dependencies = configstack.TerraformModules{moduleA} // Circular dependency - stack := NewStack(&options.TerragruntOptions{WorkingDir: "circular-stack"}) - stack.Modules = TerraformModules{moduleA, moduleB, moduleC} + stack := configstack.NewStack(&options.TerragruntOptions{WorkingDir: "circular-stack"}) + stack.Modules = configstack.TerraformModules{moduleA, moduleB, moduleC} expected := map[string][]string{ "A": {"C", "B"}, diff --git a/configstack/test_helpers.go b/configstack/test_helpers_test.go similarity index 83% rename from configstack/test_helpers.go rename to configstack/test_helpers_test.go index 3a32e62a1..4741bb045 100644 --- a/configstack/test_helpers.go +++ b/configstack/test_helpers_test.go @@ -1,4 +1,4 @@ -package configstack +package configstack_test import ( "context" @@ -8,19 +8,20 @@ import ( "github.com/gruntwork-io/go-commons/errors" "github.com/gruntwork-io/terragrunt/config" + "github.com/gruntwork-io/terragrunt/configstack" "github.com/gruntwork-io/terragrunt/options" "github.com/gruntwork-io/terragrunt/util" "github.com/hashicorp/go-multierror" "github.com/stretchr/testify/assert" ) -type TerraformModuleByPath TerraformModules +type TerraformModuleByPath configstack.TerraformModules func (byPath TerraformModuleByPath) Len() int { return len(byPath) } func (byPath TerraformModuleByPath) Swap(i, j int) { byPath[i], byPath[j] = byPath[j], byPath[i] } func (byPath TerraformModuleByPath) Less(i, j int) bool { return byPath[i].Path < byPath[j].Path } -type RunningModuleByPath []*runningModule +type RunningModuleByPath []*configstack.RunningModule func (byPath RunningModuleByPath) Len() int { return len(byPath) } func (byPath RunningModuleByPath) Swap(i, j int) { byPath[i], byPath[j] = byPath[j], byPath[i] } @@ -30,7 +31,7 @@ func (byPath RunningModuleByPath) Less(i, j int) bool { // We can't use assert.Equals on TerraformModule or any data structure that contains it because it contains some // fields (e.g. TerragruntOptions) that cannot be compared directly -func assertModuleListsEqual(t *testing.T, expectedModules TerraformModules, actualModules TerraformModules, messageAndArgs ...interface{}) { +func assertModuleListsEqual(t *testing.T, expectedModules configstack.TerraformModules, actualModules configstack.TerraformModules, messageAndArgs ...interface{}) { if !assert.Equal(t, len(expectedModules), len(actualModules), messageAndArgs...) { t.Logf("%s != %s", expectedModules, actualModules) return @@ -48,7 +49,7 @@ func assertModuleListsEqual(t *testing.T, expectedModules TerraformModules, actu // We can't use assert.Equals on TerraformModule because it contains some fields (e.g. TerragruntOptions) that cannot // be compared directly -func assertModulesEqual(t *testing.T, expected *TerraformModule, actual *TerraformModule, messageAndArgs ...interface{}) { +func assertModulesEqual(t *testing.T, expected *configstack.TerraformModule, actual *configstack.TerraformModule, messageAndArgs ...interface{}) { if assert.NotNil(t, actual, messageAndArgs...) { // When comparing the TerragruntConfig objects, we need to normalize the dependency list to explicitly set the // expected to empty list when nil, as the parsing routine will set it to empty list instead of nil. @@ -69,9 +70,9 @@ func assertModulesEqual(t *testing.T, expected *TerraformModule, actual *Terrafo } } -// We can't use assert.Equals on TerraformModule or any data structure that contains it (e.g. runningModule) because it +// We can't use assert.Equals on TerraformModule or any data structure that contains it (e.g. configstack.RunningModule) because it // contains some fields (e.g. TerragruntOptions) that cannot be compared directly -func assertRunningModuleMapsEqual(t *testing.T, expectedModules map[string]*runningModule, actualModules map[string]*runningModule, doDeepCheck bool, messageAndArgs ...interface{}) { +func assertRunningModuleMapsEqual(t *testing.T, expectedModules map[string]*configstack.RunningModule, actualModules map[string]*configstack.RunningModule, doDeepCheck bool, messageAndArgs ...interface{}) { if !assert.Equal(t, len(expectedModules), len(actualModules), messageAndArgs...) { t.Logf("%v != %v", expectedModules, actualModules) return @@ -85,9 +86,9 @@ func assertRunningModuleMapsEqual(t *testing.T, expectedModules map[string]*runn } } -// We can't use assert.Equals on TerraformModule or any data structure that contains it (e.g. runningModule) because it +// We can't use assert.Equals on TerraformModule or any data structure that contains it (e.g. configstack.RunningModule) because it // contains some fields (e.g. TerragruntOptions) that cannot be compared directly -func assertRunningModuleListsEqual(t *testing.T, expectedModules []*runningModule, actualModules []*runningModule, doDeepCheck bool, messageAndArgs ...interface{}) { +func assertRunningModuleListsEqual(t *testing.T, expectedModules []*configstack.RunningModule, actualModules []*configstack.RunningModule, doDeepCheck bool, messageAndArgs ...interface{}) { if !assert.Equal(t, len(expectedModules), len(actualModules), messageAndArgs...) { t.Logf("%v != %v", expectedModules, actualModules) return @@ -103,9 +104,9 @@ func assertRunningModuleListsEqual(t *testing.T, expectedModules []*runningModul } } -// We can't use assert.Equals on TerraformModule or any data structure that contains it (e.g. runningModule) because it +// We can't use assert.Equals on TerraformModule or any data structure that contains it (e.g. configstack.RunningModule) because it // contains some fields (e.g. TerragruntOptions) that cannot be compared directly -func assertRunningModulesEqual(t *testing.T, expected *runningModule, actual *runningModule, doDeepCheck bool, messageAndArgs ...interface{}) { +func assertRunningModulesEqual(t *testing.T, expected *configstack.RunningModule, actual *configstack.RunningModule, doDeepCheck bool, messageAndArgs ...interface{}) { if assert.NotNil(t, actual, messageAndArgs...) { assert.Equal(t, expected.Status, actual.Status, messageAndArgs...) @@ -121,15 +122,15 @@ func assertRunningModulesEqual(t *testing.T, expected *runningModule, actual *ru } } -// We can't do a simple IsError comparison for UnrecognizedDependencyError because that error is a struct that +// We can't do a simple IsError comparison for configstack.UnrecognizedDependencyError because that error is a struct that // contains an array, and in Go, trying to compare arrays gives a "comparing uncomparable type -// configstack.UnrecognizedDependencyError" panic. Therefore, we have to compare that error more manually. +// configstack.configstack.UnrecognizedDependencyError" panic. Therefore, we have to compare that error more manually. func assertErrorsEqual(t *testing.T, expected error, actual error, messageAndArgs ...interface{}) { actual = errors.Unwrap(actual) - var unrecognizedDependencyError UnrecognizedDependencyError + var unrecognizedDependencyError configstack.UnrecognizedDependencyError if ok := goErrors.As(expected, &unrecognizedDependencyError); ok { - var actualUnrecognized UnrecognizedDependencyError + var actualUnrecognized configstack.UnrecognizedDependencyError ok = goErrors.As(actual, &actualUnrecognized) if assert.True(t, ok, messageAndArgs...) { assert.Equal(t, unrecognizedDependencyError, actualUnrecognized, messageAndArgs...) diff --git a/dynamodb/counting_semaphore_test.go b/dynamodb/counting_semaphore_test.go index 0c2c401c0..a009079c1 100644 --- a/dynamodb/counting_semaphore_test.go +++ b/dynamodb/counting_semaphore_test.go @@ -1,5 +1,5 @@ //nolint:govet -package dynamodb +package dynamodb_test import ( "math/rand" @@ -7,12 +7,14 @@ import ( "sync/atomic" "testing" "time" + + "github.com/gruntwork-io/terragrunt/dynamodb" ) func TestCountingSemaphoreHappyPath(t *testing.T) { t.Parallel() - semaphore := NewCountingSemaphore(1) + semaphore := dynamodb.NewCountingSemaphore(1) semaphore.Acquire() semaphore.Release() } @@ -26,7 +28,7 @@ func TestCountingSemaphoreConcurrency(t *testing.T) { permits := 10 goroutines := 100 - semaphore := NewCountingSemaphore(permits) + semaphore := dynamodb.NewCountingSemaphore(permits) var goRoutinesExecutingSimultaneously uint32 var waitForAllGoRoutinesToFinish sync.WaitGroup diff --git a/dynamodb/dynamo_lock_table.go b/dynamodb/dynamo_lock_table.go index 71fe9dcb0..876780fa5 100644 --- a/dynamodb/dynamo_lock_table.go +++ b/dynamodb/dynamo_lock_table.go @@ -202,13 +202,13 @@ func isTableAlreadyBeingCreatedOrUpdatedError(err error) bool { // Wait for the given DynamoDB table to be in the "active" state. If it's not in "active" state, sleep for the // specified amount of time, and try again, up to a maximum of maxRetries retries. func waitForTableToBeActive(tableName string, client *dynamodb.DynamoDB, maxRetries int, sleepBetweenRetries time.Duration, terragruntOptions *options.TerragruntOptions) error { - return waitForTableToBeActiveWithRandomSleep(tableName, client, maxRetries, sleepBetweenRetries, sleepBetweenRetries, terragruntOptions) + return WaitForTableToBeActiveWithRandomSleep(tableName, client, maxRetries, sleepBetweenRetries, sleepBetweenRetries, terragruntOptions) } // Waits for the given table as described above, but sleeps a random amount of time greater than sleepBetweenRetriesMin // and less than sleepBetweenRetriesMax between tries. This is to avoid an AWS issue where all waiting requests fire at // the same time, which continually triggered AWS's "subscriber limit exceeded" API error. -func waitForTableToBeActiveWithRandomSleep(tableName string, client *dynamodb.DynamoDB, maxRetries int, sleepBetweenRetriesMin time.Duration, sleepBetweenRetriesMax time.Duration, terragruntOptions *options.TerragruntOptions) error { +func WaitForTableToBeActiveWithRandomSleep(tableName string, client *dynamodb.DynamoDB, maxRetries int, sleepBetweenRetriesMin time.Duration, sleepBetweenRetriesMax time.Duration, terragruntOptions *options.TerragruntOptions) error { for i := 0; i < maxRetries; i++ { tableReady, err := LockTableExistsAndIsActive(tableName, client) if err != nil { diff --git a/dynamodb/dynamo_lock_table_test.go b/dynamodb/dynamo_lock_table_test.go index bf4f3fde1..0a3a9418c 100644 --- a/dynamodb/dynamo_lock_table_test.go +++ b/dynamodb/dynamo_lock_table_test.go @@ -1,4 +1,4 @@ -package dynamodb +package dynamodb_test import ( "reflect" @@ -7,16 +7,18 @@ import ( "time" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/dynamodb" + awsDynamodb "github.com/aws/aws-sdk-go/service/dynamodb" "github.com/gruntwork-io/go-commons/errors" + "github.com/gruntwork-io/terragrunt/dynamodb" "github.com/gruntwork-io/terragrunt/options" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestCreateLockTableIfNecessaryTableDoesntAlreadyExist(t *testing.T) { t.Parallel() - withLockTable(t, func(tableName string, client *dynamodb.DynamoDB) { + withLockTable(t, func(tableName string, client *awsDynamodb.DynamoDB) { assertCanWriteToTable(t, tableName, client) }) } @@ -44,7 +46,7 @@ func TestCreateLockTableConcurrency(t *testing.T) { waitGroup.Add(1) go func() { defer waitGroup.Done() - err := CreateLockTableIfNecessary(tableName, nil, client, mockOptions) + err := dynamodb.CreateLockTableIfNecessary(tableName, nil, client, mockOptions) assert.NoError(t, err, "Unexpected error: %v", err) }() } @@ -64,9 +66,9 @@ func TestWaitForTableToBeActiveTableDoesNotExist(t *testing.T) { tableName := "terragrunt-table-does-not-exist" retries := 5 - err = waitForTableToBeActiveWithRandomSleep(tableName, client, retries, 1*time.Millisecond, 500*time.Millisecond, mockOptions) + err = dynamodb.WaitForTableToBeActiveWithRandomSleep(tableName, client, retries, 1*time.Millisecond, 500*time.Millisecond, mockOptions) - assert.True(t, errors.IsError(err, TableActiveRetriesExceeded{TableName: tableName, Retries: retries}), "Unexpected error of type %s: %s", reflect.TypeOf(err), err) + assert.True(t, errors.IsError(err, dynamodb.TableActiveRetriesExceeded{TableName: tableName, Retries: retries}), "Unexpected error of type %s: %s", reflect.TypeOf(err), err) } func TestCreateLockTableIfNecessaryTableAlreadyExists(t *testing.T) { @@ -78,12 +80,12 @@ func TestCreateLockTableIfNecessaryTableAlreadyExists(t *testing.T) { } // Create the table the first time - withLockTable(t, func(tableName string, client *dynamodb.DynamoDB) { + withLockTable(t, func(tableName string, client *awsDynamodb.DynamoDB) { assertCanWriteToTable(t, tableName, client) // Try to create the table the second time and make sure you get no errors - err = CreateLockTableIfNecessary(tableName, nil, client, mockOptions) - assert.NoError(t, err, "Unexpected error: %v", err) + err = dynamodb.CreateLockTableIfNecessary(tableName, nil, client, mockOptions) + require.NoError(t, err, "Unexpected error: %v", err) }) } @@ -98,25 +100,25 @@ func TestTableTagging(t *testing.T) { tags := map[string]string{"team": "team A"} // Create the table the first time - withLockTableTagged(t, tags, func(tableName string, client *dynamodb.DynamoDB) { + withLockTableTagged(t, tags, func(tableName string, client *awsDynamodb.DynamoDB) { assertCanWriteToTable(t, tableName, client) assertTags(tags, tableName, client, t) // Try to create the table the second time and make sure you get no errors - err = CreateLockTableIfNecessary(tableName, nil, client, mockOptions) - assert.NoError(t, err, "Unexpected error: %v", err) + err = dynamodb.CreateLockTableIfNecessary(tableName, nil, client, mockOptions) + require.NoError(t, err, "Unexpected error: %v", err) }) } -func assertTags(expectedTags map[string]string, tableName string, client *dynamodb.DynamoDB, t *testing.T) { - var description, err = client.DescribeTable(&dynamodb.DescribeTableInput{TableName: aws.String(tableName)}) +func assertTags(expectedTags map[string]string, tableName string, client *awsDynamodb.DynamoDB, t *testing.T) { + var description, err = client.DescribeTable(&awsDynamodb.DescribeTableInput{TableName: aws.String(tableName)}) if err != nil { t.Fatal(err) } - var tags, err2 = client.ListTagsOfResource(&dynamodb.ListTagsOfResourceInput{ResourceArn: description.Table.TableArn}) + var tags, err2 = client.ListTagsOfResource(&awsDynamodb.ListTagsOfResourceInput{ResourceArn: description.Table.TableArn}) if err2 != nil { t.Fatal(err2) diff --git a/dynamodb/dynamo_lock_test_utils.go b/dynamodb/dynamo_lock_test_utils_test.go similarity index 67% rename from dynamodb/dynamo_lock_test_utils.go rename to dynamodb/dynamo_lock_test_utils_test.go index 78e515129..588c7a1f8 100644 --- a/dynamodb/dynamo_lock_test_utils.go +++ b/dynamodb/dynamo_lock_test_utils_test.go @@ -1,11 +1,12 @@ -package dynamodb +package dynamodb_test import ( "testing" "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/dynamodb" + awsDynamodb "github.com/aws/aws-sdk-go/service/dynamodb" "github.com/gruntwork-io/terragrunt/aws_helper" + "github.com/gruntwork-io/terragrunt/dynamodb" "github.com/gruntwork-io/terragrunt/options" "github.com/gruntwork-io/terragrunt/util" "github.com/stretchr/testify/require" @@ -15,7 +16,7 @@ import ( const DEFAULT_TEST_REGION = "us-east-1" // Create a DynamoDB client we can use at test time. If there are any errors creating the client, fail the test. -func createDynamoDbClientForTest(t *testing.T) *dynamodb.DynamoDB { +func createDynamoDbClientForTest(t *testing.T) *awsDynamodb.DynamoDB { mockOptions, err := options.NewTerragruntOptionsForTest("dynamo_lock_test_utils") if err != nil { t.Fatal(err) @@ -25,7 +26,7 @@ func createDynamoDbClientForTest(t *testing.T) *dynamodb.DynamoDB { Region: DEFAULT_TEST_REGION, } - client, err := CreateDynamoDbClient(sessionConfig, mockOptions) + client, err := dynamodb.CreateDynamoDbClient(sessionConfig, mockOptions) if err != nil { t.Fatal(err) } @@ -36,15 +37,15 @@ func uniqueTableNameForTest() string { return "terragrunt_test_" + util.UniqueId() } -func cleanupTableForTest(t *testing.T, tableName string, client *dynamodb.DynamoDB) { - err := DeleteTable(tableName, client) +func cleanupTableForTest(t *testing.T, tableName string, client *awsDynamodb.DynamoDB) { + err := dynamodb.DeleteTable(tableName, client) require.NoError(t, err, "Unexpected error: %v", err) } -func assertCanWriteToTable(t *testing.T, tableName string, client *dynamodb.DynamoDB) { +func assertCanWriteToTable(t *testing.T, tableName string, client *awsDynamodb.DynamoDB) { item := createKeyFromItemId(util.UniqueId()) - _, err := client.PutItem(&dynamodb.PutItemInput{ + _, err := client.PutItem(&awsDynamodb.PutItemInput{ TableName: aws.String(tableName), Item: item, }) @@ -52,11 +53,11 @@ func assertCanWriteToTable(t *testing.T, tableName string, client *dynamodb.Dyna require.NoError(t, err, "Unexpected error: %v", err) } -func withLockTable(t *testing.T, action func(tableName string, client *dynamodb.DynamoDB)) { +func withLockTable(t *testing.T, action func(tableName string, client *awsDynamodb.DynamoDB)) { withLockTableTagged(t, nil, action) } -func withLockTableTagged(t *testing.T, tags map[string]string, action func(tableName string, client *dynamodb.DynamoDB)) { +func withLockTableTagged(t *testing.T, tags map[string]string, action func(tableName string, client *awsDynamodb.DynamoDB)) { client := createDynamoDbClientForTest(t) tableName := uniqueTableNameForTest() @@ -65,15 +66,15 @@ func withLockTableTagged(t *testing.T, tags map[string]string, action func(table t.Fatal(err) } - err = CreateLockTableIfNecessary(tableName, tags, client, mockOptions) + err = dynamodb.CreateLockTableIfNecessary(tableName, tags, client, mockOptions) require.NoError(t, err, "Unexpected error: %v", err) defer cleanupTableForTest(t, tableName, client) action(tableName, client) } -func createKeyFromItemId(itemId string) map[string]*dynamodb.AttributeValue { - return map[string]*dynamodb.AttributeValue{ - ATTR_LOCK_ID: {S: aws.String(itemId)}, +func createKeyFromItemId(itemId string) map[string]*awsDynamodb.AttributeValue { + return map[string]*awsDynamodb.AttributeValue{ + dynamodb.ATTR_LOCK_ID: {S: aws.String(itemId)}, } } diff --git a/engine/engine.go b/engine/engine.go index e95b9db09..bb0ffb0e1 100644 --- a/engine/engine.go +++ b/engine/engine.go @@ -431,7 +431,7 @@ func createEngine(terragruntOptions *options.TerragruntOptions) (*proto.EngineCl func invoke(ctx context.Context, runOptions *ExecutionOptions, client *proto.EngineClient) (*util.CmdOutput, error) { terragruntOptions := runOptions.TerragruntOptions - meta, err := convertMetaToProtobuf(runOptions.TerragruntOptions.Engine.Meta) + meta, err := ConvertMetaToProtobuf(runOptions.TerragruntOptions.Engine.Meta) if err != nil { return nil, errors.WithStackTrace(err) } @@ -523,7 +523,7 @@ func flushBuffer(lineBuf *bytes.Buffer, output io.Writer) error { // initialize engine for working directory func initialize(ctx context.Context, runOptions *ExecutionOptions, client *proto.EngineClient) error { terragruntOptions := runOptions.TerragruntOptions - meta, err := convertMetaToProtobuf(runOptions.TerragruntOptions.Engine.Meta) + meta, err := ConvertMetaToProtobuf(runOptions.TerragruntOptions.Engine.Meta) if err != nil { return errors.WithStackTrace(err) } @@ -538,7 +538,7 @@ func initialize(ctx context.Context, runOptions *ExecutionOptions, client *proto } terragruntOptions.Logger.Debugf("Reading init output for engine in %s", runOptions.WorkingDir) - return readEngineOutput(runOptions, func() (*outputLine, error) { + return ReadEngineOutput(runOptions, func() (*OutputLine, error) { output, err := request.Recv() if err != nil { return nil, err @@ -546,7 +546,7 @@ func initialize(ctx context.Context, runOptions *ExecutionOptions, client *proto if output == nil { return nil, nil } - return &outputLine{ + return &OutputLine{ Stderr: output.GetStderr(), Stdout: output.GetStdout(), }, nil @@ -557,7 +557,7 @@ func initialize(ctx context.Context, runOptions *ExecutionOptions, client *proto func shutdown(ctx context.Context, runOptions *ExecutionOptions, terragruntEngine *proto.EngineClient) error { terragruntOptions := runOptions.TerragruntOptions - meta, err := convertMetaToProtobuf(runOptions.TerragruntOptions.Engine.Meta) + meta, err := ConvertMetaToProtobuf(runOptions.TerragruntOptions.Engine.Meta) if err != nil { return errors.WithStackTrace(err) } @@ -571,7 +571,7 @@ func shutdown(ctx context.Context, runOptions *ExecutionOptions, terragruntEngin } terragruntOptions.Logger.Debugf("Reading shutdown output for engine in %s", runOptions.WorkingDir) - return readEngineOutput(runOptions, func() (*outputLine, error) { + return ReadEngineOutput(runOptions, func() (*OutputLine, error) { output, err := request.Recv() if err != nil { return nil, err @@ -579,7 +579,7 @@ func shutdown(ctx context.Context, runOptions *ExecutionOptions, terragruntEngin if output == nil { return nil, nil } - return &outputLine{ + return &OutputLine{ Stdout: output.GetStdout(), Stderr: output.GetStderr(), }, nil @@ -588,16 +588,16 @@ func shutdown(ctx context.Context, runOptions *ExecutionOptions, terragruntEngin } // common engine output -type outputLine struct { +type OutputLine struct { Stdout string Stderr string } -type outputFn func() (*outputLine, error) +type outputFn func() (*OutputLine, error) -// readEngineOutput reads the output from the engine, since grpc plugins don't have common type, +// ReadEngineOutput reads the output from the engine, since grpc plugins don't have common type, // use lambda function to read bytes from the stream -func readEngineOutput(runOptions *ExecutionOptions, output outputFn) error { +func ReadEngineOutput(runOptions *ExecutionOptions, output outputFn) error { cmdStdout := runOptions.CmdStdout cmdStderr := runOptions.CmdStderr for { @@ -623,7 +623,7 @@ func readEngineOutput(runOptions *ExecutionOptions, output outputFn) error { } // convert metadata map to protobuf map -func convertMetaToProtobuf(meta map[string]interface{}) (map[string]*anypb.Any, error) { +func ConvertMetaToProtobuf(meta map[string]interface{}) (map[string]*anypb.Any, error) { protoMeta := make(map[string]*anypb.Any) if meta == nil { return protoMeta, nil diff --git a/engine/engine_test.go b/engine/engine_test.go index da27b6885..fba1a838d 100644 --- a/engine/engine_test.go +++ b/engine/engine_test.go @@ -1,9 +1,10 @@ -package engine +package engine_test import ( "io" "testing" + "github.com/gruntwork-io/terragrunt/engine" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -11,13 +12,13 @@ import ( func TestIsEngineEnabled(t *testing.T) { t.Setenv("TG_EXPERIMENTAL_ENGINE", "true") - assert.True(t, IsEngineEnabled()) + assert.True(t, engine.IsEngineEnabled()) t.Setenv("TG_EXPERIMENTAL_ENGINE", "false") - assert.False(t, IsEngineEnabled()) + assert.False(t, engine.IsEngineEnabled()) t.Setenv("TG_EXPERIMENTAL_ENGINE", "") - assert.False(t, IsEngineEnabled()) + assert.False(t, engine.IsEngineEnabled()) } func TestConvertMetaToProtobuf(t *testing.T) { @@ -27,7 +28,7 @@ func TestConvertMetaToProtobuf(t *testing.T) { "key2": 42, } - protoMeta, err := convertMetaToProtobuf(meta) + protoMeta, err := engine.ConvertMetaToProtobuf(meta) require.NoError(t, err) assert.NotNil(t, protoMeta) assert.Len(t, protoMeta, 2) @@ -35,23 +36,23 @@ func TestConvertMetaToProtobuf(t *testing.T) { func TestReadEngineOutput(t *testing.T) { t.Parallel() - runOptions := &ExecutionOptions{ + runOptions := &engine.ExecutionOptions{ CmdStdout: io.Discard, CmdStderr: io.Discard, } outputReturned := false - outputFn := func() (*outputLine, error) { + outputFn := func() (*engine.OutputLine, error) { if outputReturned { return nil, nil } outputReturned = true - return &outputLine{ + return &engine.OutputLine{ Stdout: "stdout output", Stderr: "stderr output", }, nil } - err := readEngineOutput(runOptions, outputFn) + err := engine.ReadEngineOutput(runOptions, outputFn) assert.NoError(t, err) } diff --git a/internal/cache/cache_test.go b/internal/cache/cache_test.go index 1b4f2e023..ae76ad984 100644 --- a/internal/cache/cache_test.go +++ b/internal/cache/cache_test.go @@ -1,17 +1,18 @@ -package cache +package cache_test import ( "context" "testing" "time" + "github.com/gruntwork-io/terragrunt/internal/cache" "github.com/stretchr/testify/assert" ) func TestCacheCreation(t *testing.T) { t.Parallel() - cache := NewCache[string]("test") + cache := cache.NewCache[string]("test") assert.NotNil(t, cache.Mutex) assert.NotNil(t, cache.Cache) @@ -23,7 +24,7 @@ func TestStringCacheOperation(t *testing.T) { t.Parallel() ctx := context.Background() - cache := NewCache[string]("test") + cache := cache.NewCache[string]("test") value, found := cache.Get(ctx, "potato") @@ -41,7 +42,7 @@ func TestStringCacheOperation(t *testing.T) { func TestExpiringCacheCreation(t *testing.T) { t.Parallel() - cache := NewExpiringCache[string]("test") + cache := cache.NewExpiringCache[string]("test") assert.NotNil(t, cache.Mutex) assert.NotNil(t, cache.Cache) @@ -53,7 +54,7 @@ func TestExpiringCacheOperation(t *testing.T) { t.Parallel() ctx := context.Background() - cache := NewExpiringCache[string]("test") + cache := cache.NewExpiringCache[string]("test") value, found := cache.Get(ctx, "potato") @@ -72,7 +73,7 @@ func TestExpiringCacheExpiration(t *testing.T) { t.Parallel() ctx := context.Background() - cache := NewExpiringCache[string]("test") + cache := cache.NewExpiringCache[string]("test") cache.Put(ctx, "potato", "carrot", time.Now().Add(-1*time.Second)) value, found := cache.Get(ctx, "potato") diff --git a/pkg/cli/app.go b/pkg/cli/app.go index ea5b928a9..b4e7bc6d1 100644 --- a/pkg/cli/app.go +++ b/pkg/cli/app.go @@ -111,7 +111,7 @@ func (app *App) RunContext(ctx context.Context, arguments []string) (err error) cmd := app.newRootCommand() args := Args(parentCtx.Args().Slice()) - ctx := newContext(parentCtx.Context, app) + ctx := NewContext(parentCtx.Context, app) if app.Autocomplete { if err := app.setupAutocomplete(args); err != nil { diff --git a/pkg/cli/args_test.go b/pkg/cli/args_test.go index c565ce5f4..5315c2cb5 100644 --- a/pkg/cli/args_test.go +++ b/pkg/cli/args_test.go @@ -1,12 +1,13 @@ -package cli +package cli_test import ( "testing" + "github.com/gruntwork-io/terragrunt/pkg/cli" "github.com/stretchr/testify/assert" ) -var mockArgs = Args([]string{"one", "-foo", "two", "--bar", "value"}) +var mockArgs = cli.Args([]string{"one", "-foo", "two", "--bar", "value"}) func TestArgsSlice(t *testing.T) { t.Parallel() @@ -55,7 +56,7 @@ func TestArgsPresent(t *testing.T) { expected := true assert.Equal(t, expected, actual) - mockArgs := Args([]string{}) + mockArgs := cli.Args([]string{}) actual = mockArgs.Present() expected = false assert.Equal(t, expected, actual) @@ -77,11 +78,11 @@ func TestArgsCommandName(t *testing.T) { func TestArgsNormalize(t *testing.T) { t.Parallel() - actual := mockArgs.Normalize(SingleDashFlag).Slice() + actual := mockArgs.Normalize(cli.SingleDashFlag).Slice() expected := []string{"one", "-foo", "two", "-bar", "value"} assert.Equal(t, expected, actual) - actual = mockArgs.Normalize(DoubleDashFlag).Slice() + actual = mockArgs.Normalize(cli.DoubleDashFlag).Slice() expected = []string{"one", "--foo", "two", "--bar", "value"} assert.Equal(t, expected, actual) } diff --git a/pkg/cli/bool_flag_test.go b/pkg/cli/bool_flag_test.go index 65fbf6088..86b556f8a 100644 --- a/pkg/cli/bool_flag_test.go +++ b/pkg/cli/bool_flag_test.go @@ -1,4 +1,4 @@ -package cli +package cli_test import ( "errors" @@ -8,6 +8,7 @@ import ( "strconv" "testing" + "github.com/gruntwork-io/terragrunt/pkg/cli" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -16,70 +17,70 @@ func TestBoolFlagApply(t *testing.T) { t.Parallel() testCases := []struct { - flag BoolFlag + flag cli.BoolFlag args []string envs map[string]string expectedValue bool expectedErr error }{ { - BoolFlag{Name: "foo", EnvVar: "FOO"}, + cli.BoolFlag{Name: "foo", EnvVar: "FOO"}, []string{"--foo"}, map[string]string{"FOO": "false"}, true, nil, }, { - BoolFlag{Name: "foo", EnvVar: "FOO"}, + cli.BoolFlag{Name: "foo", EnvVar: "FOO"}, nil, map[string]string{"FOO": "true"}, true, nil, }, { - BoolFlag{Name: "foo", EnvVar: "FOO"}, + cli.BoolFlag{Name: "foo", EnvVar: "FOO"}, nil, nil, false, nil, }, { - BoolFlag{Name: "foo", EnvVar: "FOO", Destination: mockDestValue(false)}, + cli.BoolFlag{Name: "foo", EnvVar: "FOO", Destination: mockDestValue(false)}, []string{"--foo"}, map[string]string{"FOO": "false"}, true, nil, }, { - BoolFlag{Name: "foo", Destination: mockDestValue(true)}, + cli.BoolFlag{Name: "foo", Destination: mockDestValue(true)}, nil, nil, true, nil, }, { - BoolFlag{Name: "foo", Destination: mockDestValue(true), Negative: true}, + cli.BoolFlag{Name: "foo", Destination: mockDestValue(true), Negative: true}, []string{"--foo"}, nil, false, nil, }, { - BoolFlag{Name: "foo", EnvVar: "FOO", Destination: mockDestValue(true), Negative: true}, + cli.BoolFlag{Name: "foo", EnvVar: "FOO", Destination: mockDestValue(true), Negative: true}, nil, map[string]string{"FOO": "true"}, false, nil, }, { - BoolFlag{Name: "foo", EnvVar: "FOO", Destination: mockDestValue(false), Negative: true}, + cli.BoolFlag{Name: "foo", EnvVar: "FOO", Destination: mockDestValue(false), Negative: true}, nil, map[string]string{"FOO": "false"}, true, nil, }, { - BoolFlag{Name: "foo", EnvVar: "FOO"}, + cli.BoolFlag{Name: "foo", EnvVar: "FOO"}, []string{"--foo", "--foo"}, nil, false, @@ -98,7 +99,7 @@ func TestBoolFlagApply(t *testing.T) { } } -func testBoolFlagApply(t *testing.T, flag *BoolFlag, args []string, envs map[string]string, expectedValue bool, expectedErr error) { +func testBoolFlagApply(t *testing.T, flag *cli.BoolFlag, args []string, envs map[string]string, expectedValue bool, expectedErr error) { var ( actualValue bool destDefined bool diff --git a/pkg/cli/command_test.go b/pkg/cli/command_test.go index 025f62e96..31d220771 100644 --- a/pkg/cli/command_test.go +++ b/pkg/cli/command_test.go @@ -1,4 +1,4 @@ -package cli +package cli_test import ( "context" @@ -7,28 +7,29 @@ import ( "io" "testing" + "github.com/gruntwork-io/terragrunt/pkg/cli" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/urfave/cli/v2" + urfaveCli "github.com/urfave/cli/v2" ) func TestCommandRun(t *testing.T) { t.Parallel() - type TestActionFunc func(expectedOrder int, expectedArgs []string) ActionFunc + type TestActionFunc func(expectedOrder int, expectedArgs []string) cli.ActionFunc type TestCase struct { args []string - command Command + command cli.Command expectedErr error } - testCaseFuncs := []func(action TestActionFunc, skip ActionFunc) TestCase{ - func(action TestActionFunc, skip ActionFunc) TestCase { + testCaseFuncs := []func(action TestActionFunc, skip cli.ActionFunc) TestCase{ + func(action TestActionFunc, skip cli.ActionFunc) TestCase { return TestCase{ []string{"--foo", "--foo", "cmd-bar", "--bar", "one", "-two"}, - Command{ - Flags: Flags{&BoolFlag{Name: "foo"}}, + cli.Command{ + Flags: cli.Flags{&cli.BoolFlag{Name: "foo"}}, Before: skip, Action: skip, After: skip, @@ -37,25 +38,25 @@ func TestCommandRun(t *testing.T) { } }, - func(action TestActionFunc, skip ActionFunc) TestCase { + func(action TestActionFunc, skip cli.ActionFunc) TestCase { return TestCase{ []string{"--foo", "cmd-bar", "--bar", "one", "-two"}, - Command{ - Flags: Flags{&BoolFlag{Name: "foo"}}, + cli.Command{ + Flags: cli.Flags{&cli.BoolFlag{Name: "foo"}}, Before: action(1, nil), Action: skip, After: action(5, nil), - Subcommands: Commands{ - { + Subcommands: cli.Commands{ + &cli.Command{ Name: "cmd-cux", - Flags: Flags{&BoolFlag{Name: "bar"}}, + Flags: cli.Flags{&cli.BoolFlag{Name: "bar"}}, Before: skip, Action: skip, After: skip, }, - { + &cli.Command{ Name: "cmd-bar", - Flags: Flags{&BoolFlag{Name: "bar"}}, + Flags: cli.Flags{&cli.BoolFlag{Name: "bar"}}, Before: action(2, nil), Action: action(3, []string{"one", "-two"}), After: action(4, nil), @@ -65,18 +66,18 @@ func TestCommandRun(t *testing.T) { nil, } }, - func(action TestActionFunc, skip ActionFunc) TestCase { + func(action TestActionFunc, skip cli.ActionFunc) TestCase { return TestCase{ []string{"--foo", "cmd-bar", "--bar", "one", "-two"}, - Command{ - Flags: Flags{&BoolFlag{Name: "foo"}}, + cli.Command{ + Flags: cli.Flags{&cli.BoolFlag{Name: "foo"}}, Before: action(1, nil), Action: skip, After: action(4, nil), - Subcommands: Commands{ - { + Subcommands: cli.Commands{ + &cli.Command{ Name: "cmd-bar", - Flags: Flags{&BoolFlag{Name: "bar"}}, + Flags: cli.Flags{&cli.BoolFlag{Name: "bar"}}, Before: action(2, nil), After: action(3, nil), }, @@ -85,18 +86,18 @@ func TestCommandRun(t *testing.T) { nil, } }, - func(action TestActionFunc, skip ActionFunc) TestCase { + func(action TestActionFunc, skip cli.ActionFunc) TestCase { return TestCase{ []string{"--foo", "--bar", "cmd-bar", "one", "-two"}, - Command{ - Flags: Flags{&BoolFlag{Name: "foo"}}, + cli.Command{ + Flags: cli.Flags{&cli.BoolFlag{Name: "foo"}}, Before: action(1, nil), Action: action(2, []string{"--bar", "cmd-bar", "one", "-two"}), After: action(3, nil), - Subcommands: Commands{ - { + Subcommands: cli.Commands{ + &cli.Command{ Name: "cmd-bar", - Flags: Flags{&BoolFlag{Name: "bar"}}, + Flags: cli.Flags{&cli.BoolFlag{Name: "bar"}}, Before: skip, After: skip, Action: skip, @@ -106,18 +107,18 @@ func TestCommandRun(t *testing.T) { nil, } }, - func(action TestActionFunc, skip ActionFunc) TestCase { + func(action TestActionFunc, skip cli.ActionFunc) TestCase { return TestCase{ []string{"--foo", "cmd-bar", "--bar", "value", "one", "-two"}, - Command{ - Flags: Flags{&BoolFlag{Name: "foo"}}, + cli.Command{ + Flags: cli.Flags{&cli.BoolFlag{Name: "foo"}}, Before: action(1, nil), Action: skip, After: action(5, nil), - Subcommands: Commands{ - { + Subcommands: cli.Commands{ + &cli.Command{ Name: "cmd-bar", - Flags: Flags{&GenericFlag[string]{Name: "bar"}}, + Flags: cli.Flags{&cli.GenericFlag[string]{Name: "bar"}}, Before: action(2, nil), Action: action(3, []string{"one", "-two"}), After: action(4, nil), @@ -127,18 +128,18 @@ func TestCommandRun(t *testing.T) { nil, } }, - func(action TestActionFunc, skip ActionFunc) TestCase { + func(action TestActionFunc, skip cli.ActionFunc) TestCase { return TestCase{ []string{"--foo", "cmd-bar", "--bar", "value", "one", "-two"}, - Command{ - Flags: Flags{&BoolFlag{Name: "foo"}}, + cli.Command{ + Flags: cli.Flags{&cli.BoolFlag{Name: "foo"}}, Before: action(1, nil), Action: action(2, []string{"cmd-bar", "--bar", "value", "one", "-two"}), After: action(3, nil), - Subcommands: Commands{ - { + Subcommands: cli.Commands{ + &cli.Command{ Name: "cmd-bar", - Flags: Flags{&GenericFlag[string]{Name: "bar"}}, + Flags: cli.Flags{&cli.GenericFlag[string]{Name: "bar"}}, SkipRunning: true, Before: skip, Action: skip, @@ -158,8 +159,8 @@ func TestCommandRun(t *testing.T) { t.Parallel() var actualOrder = new(int) - action := func(expectedOrder int, expectedArgs []string) ActionFunc { - return func(ctx *Context) error { + action := func(expectedOrder int, expectedArgs []string) cli.ActionFunc { + return func(ctx *cli.Context) error { (*actualOrder)++ assert.Equal(t, expectedOrder, *actualOrder) @@ -172,15 +173,15 @@ func TestCommandRun(t *testing.T) { } } - skip := func(ctx *Context) error { + skip := func(ctx *cli.Context) error { assert.Fail(t, "this action must be skipped") return nil } testCase := testCaseFn(action, skip) - app := &App{App: &cli.App{Writer: io.Discard}} - ctx := newContext(context.Background(), app) + app := &cli.App{App: &urfaveCli.App{Writer: io.Discard}} + ctx := cli.NewContext(context.Background(), app) err := testCase.command.Run(ctx, testCase.args) if testCase.expectedErr != nil { @@ -197,22 +198,22 @@ func TestCommandHasName(t *testing.T) { t.Parallel() testCases := []struct { - command Command + command cli.Command hasName string expected bool }{ { - Command{Name: "foo"}, + cli.Command{Name: "foo"}, "bar", false, }, { - Command{Name: "foo", Aliases: []string{"bar"}}, + cli.Command{Name: "foo", Aliases: []string{"bar"}}, "bar", true, }, { - Command{Name: "bar"}, + cli.Command{Name: "bar"}, "bar", true, }, @@ -234,15 +235,15 @@ func TestCommandNames(t *testing.T) { t.Parallel() testCases := []struct { - command Command + command cli.Command expected []string }{ { - Command{Name: "foo"}, + cli.Command{Name: "foo"}, []string{"foo"}, }, { - Command{Name: "foo", Aliases: []string{"bar", "baz"}}, + cli.Command{Name: "foo", Aliases: []string{"bar", "baz"}}, []string{"foo", "bar", "baz"}, }, } @@ -263,17 +264,17 @@ func TestCommandSubcommand(t *testing.T) { t.Parallel() testCases := []struct { - command Command + command cli.Command searchCmdName string - expected *Command + expected *cli.Command }{ { - Command{Name: "foo", Subcommands: Commands{{Name: "bar"}, {Name: "baz"}}}, + cli.Command{Name: "foo", Subcommands: cli.Commands{&cli.Command{Name: "bar"}, &cli.Command{Name: "baz"}}}, "baz", - &Command{Name: "baz"}, + &cli.Command{Name: "baz"}, }, { - Command{Name: "foo", Subcommands: Commands{{Name: "bar"}, {Name: "baz"}}}, + cli.Command{Name: "foo", Subcommands: cli.Commands{&cli.Command{Name: "bar"}, &cli.Command{Name: "baz"}}}, "qux", nil, }, @@ -295,16 +296,16 @@ func TestCommandVisibleSubcommand(t *testing.T) { t.Parallel() testCases := []struct { - command Command - expected []*cli.Command + command cli.Command + expected []*urfaveCli.Command }{ { - Command{Name: "foo", Subcommands: Commands{{Name: "bar"}, {Name: "baz", HelpName: "helpBaz"}}}, - []*cli.Command{{Name: "bar", HelpName: "bar"}, {Name: "baz", HelpName: "helpBaz"}}, + cli.Command{Name: "foo", Subcommands: cli.Commands{&cli.Command{Name: "bar"}, &cli.Command{Name: "baz", HelpName: "helpBaz"}}}, + []*urfaveCli.Command{{Name: "bar", HelpName: "bar"}, {Name: "baz", HelpName: "helpBaz"}}, }, { - Command{Name: "foo", Subcommands: Commands{{Name: "bar", Hidden: true}, {Name: "baz"}}}, - []*cli.Command{{Name: "baz", HelpName: "baz"}}, + cli.Command{Name: "foo", Subcommands: cli.Commands{&cli.Command{Name: "bar", Hidden: true}, &cli.Command{Name: "baz"}}}, + []*urfaveCli.Command{{Name: "baz", HelpName: "baz"}}, }, } diff --git a/pkg/cli/context.go b/pkg/cli/context.go index c3ec6246e..4a838339e 100644 --- a/pkg/cli/context.go +++ b/pkg/cli/context.go @@ -13,7 +13,7 @@ type Context struct { shellComplete bool } -func newContext(parentCtx context.Context, app *App) *Context { +func NewContext(parentCtx context.Context, app *App) *Context { return &Context{ Context: parentCtx, App: app, diff --git a/pkg/cli/flag_test.go b/pkg/cli/flag_test.go index 34f315720..291b928a0 100644 --- a/pkg/cli/flag_test.go +++ b/pkg/cli/flag_test.go @@ -1,4 +1,4 @@ -package cli +package cli_test func mockDestValue[T any](val T) *T { return &val diff --git a/pkg/cli/flags_test.go b/pkg/cli/flags_test.go index ab293e6bd..92bfbbe64 100644 --- a/pkg/cli/flags_test.go +++ b/pkg/cli/flags_test.go @@ -1,21 +1,22 @@ -package cli +package cli_test import ( libflag "flag" "io" "testing" + "github.com/gruntwork-io/terragrunt/pkg/cli" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) var ( - mockFlagFoo = &GenericFlag[string]{Name: "foo"} - mockFlagBar = &SliceFlag[string]{Name: "bar"} - mockFlagBaz = &MapFlag[string, string]{Name: "baz"} + mockFlagFoo = &cli.GenericFlag[string]{Name: "foo"} + mockFlagBar = &cli.SliceFlag[string]{Name: "bar"} + mockFlagBaz = &cli.MapFlag[string, string]{Name: "baz"} - newMockFlags = func() Flags { - return Flags{ + newMockFlags = func() cli.Flags { + return cli.Flags{ mockFlagFoo, mockFlagBar, mockFlagBaz, @@ -27,7 +28,7 @@ func TestFalgsGet(t *testing.T) { t.Parallel() actual := newMockFlags().Get("bar") - expected := Flag(mockFlagBar) + expected := cli.Flag(mockFlagBar) assert.Equal(t, expected, actual) actual = newMockFlags().Get("break") @@ -38,7 +39,7 @@ func TestFalgsGet(t *testing.T) { func TestFalgsAdd(t *testing.T) { t.Parallel() - testNewFlag := &GenericFlag[string]{Name: "qux"} + testNewFlag := &cli.GenericFlag[string]{Name: "qux"} actual := newMockFlags() actual.Add(testNewFlag) @@ -51,7 +52,7 @@ func TestFalgsFilter(t *testing.T) { t.Parallel() actual := newMockFlags().Filter([]string{"bar", "baz"}) - expected := Flags{mockFlagBar, mockFlagBaz} + expected := cli.Flags{mockFlagBar, mockFlagBaz} assert.Equal(t, expected, actual) } @@ -60,9 +61,9 @@ func TestFalgsRunActions(t *testing.T) { var actionHasBeenRun bool - mockFlags := Flags{ - &SliceFlag[string]{Name: "bar"}, - &GenericFlag[string]{Name: "foo", Action: func(ctx *Context) error { actionHasBeenRun = true; return nil }}, + mockFlags := cli.Flags{ + &cli.SliceFlag[string]{Name: "bar"}, + &cli.GenericFlag[string]{Name: "foo", Action: func(ctx *cli.Context) error { actionHasBeenRun = true; return nil }}, } flagSet := libflag.NewFlagSet("test-cmd", libflag.ContinueOnError) diff --git a/pkg/cli/generic_flag_test.go b/pkg/cli/generic_flag_test.go index 7708b5215..aebcd2363 100644 --- a/pkg/cli/generic_flag_test.go +++ b/pkg/cli/generic_flag_test.go @@ -1,4 +1,4 @@ -package cli +package cli_test import ( "errors" @@ -7,6 +7,7 @@ import ( "io" "testing" + "github.com/gruntwork-io/terragrunt/pkg/cli" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -15,49 +16,49 @@ func TestGenericFlagStringApply(t *testing.T) { t.Parallel() testCases := []struct { - flag GenericFlag[string] + flag cli.GenericFlag[string] args []string envs map[string]string expectedValue string expectedErr error }{ { - GenericFlag[string]{Name: "foo", EnvVar: "FOO"}, + cli.GenericFlag[string]{Name: "foo", EnvVar: "FOO"}, []string{"--foo", "arg-value"}, map[string]string{"FOO": "env-value"}, "arg-value", nil, }, { - GenericFlag[string]{Name: "foo", EnvVar: "FOO"}, + cli.GenericFlag[string]{Name: "foo", EnvVar: "FOO"}, nil, map[string]string{"FOO": "env-value"}, "env-value", nil, }, { - GenericFlag[string]{Name: "foo", EnvVar: "FOO"}, + cli.GenericFlag[string]{Name: "foo", EnvVar: "FOO"}, nil, nil, "", nil, }, { - GenericFlag[string]{Name: "foo", EnvVar: "FOO", Destination: mockDestValue("default-value")}, + cli.GenericFlag[string]{Name: "foo", EnvVar: "FOO", Destination: mockDestValue("default-value")}, []string{"--foo", "arg-value"}, map[string]string{"FOO": "env-value"}, "arg-value", nil, }, { - GenericFlag[string]{Name: "foo", Destination: mockDestValue("default-value")}, + cli.GenericFlag[string]{Name: "foo", Destination: mockDestValue("default-value")}, nil, nil, "default-value", nil, }, { - GenericFlag[string]{Name: "foo", EnvVar: "FOO"}, + cli.GenericFlag[string]{Name: "foo", EnvVar: "FOO"}, []string{"--foo", "arg-value1", "--foo", "arg-value2"}, nil, "", @@ -80,28 +81,28 @@ func TestGenericFlagIntApply(t *testing.T) { t.Parallel() testCases := []struct { - flag GenericFlag[int] + flag cli.GenericFlag[int] args []string envs map[string]string expectedValue int expectedErr error }{ { - GenericFlag[int]{Name: "foo", EnvVar: "FOO"}, + cli.GenericFlag[int]{Name: "foo", EnvVar: "FOO"}, []string{"--foo", "10"}, map[string]string{"FOO": "20"}, 10, nil, }, { - GenericFlag[int]{Name: "foo", EnvVar: "FOO"}, + cli.GenericFlag[int]{Name: "foo", EnvVar: "FOO"}, []string{}, map[string]string{"FOO": "20"}, 20, nil, }, { - GenericFlag[int]{Name: "foo", Destination: mockDestValue(55)}, + cli.GenericFlag[int]{Name: "foo", Destination: mockDestValue(55)}, nil, nil, 55, @@ -124,28 +125,28 @@ func TestGenericFlagInt64Apply(t *testing.T) { t.Parallel() testCases := []struct { - flag GenericFlag[int64] + flag cli.GenericFlag[int64] args []string envs map[string]string expectedValue int64 expectedErr error }{ { - GenericFlag[int64]{Name: "foo", EnvVar: "FOO"}, + cli.GenericFlag[int64]{Name: "foo", EnvVar: "FOO"}, []string{"--foo", "10"}, map[string]string{"FOO": "20"}, 10, nil, }, { - GenericFlag[int64]{Name: "foo", EnvVar: "FOO"}, + cli.GenericFlag[int64]{Name: "foo", EnvVar: "FOO"}, []string{}, map[string]string{"FOO": "20"}, 20, nil, }, { - GenericFlag[int64]{Name: "foo", Destination: mockDestValue(int64(55))}, + cli.GenericFlag[int64]{Name: "foo", Destination: mockDestValue(int64(55))}, nil, nil, 55, @@ -164,7 +165,7 @@ func TestGenericFlagInt64Apply(t *testing.T) { } } -func testGenericFlagApply[T GenericType](t *testing.T, flag *GenericFlag[T], args []string, envs map[string]string, expectedValue T, expectedErr error) { +func testGenericFlagApply[T cli.GenericType](t *testing.T, flag *cli.GenericFlag[T], args []string, envs map[string]string, expectedValue T, expectedErr error) { var ( actualValue T destDefined bool diff --git a/pkg/cli/map_flag_test.go b/pkg/cli/map_flag_test.go index 014f5077a..4d70548a4 100644 --- a/pkg/cli/map_flag_test.go +++ b/pkg/cli/map_flag_test.go @@ -1,4 +1,4 @@ -package cli +package cli_test import ( libflag "flag" @@ -7,6 +7,7 @@ import ( "testing" "github.com/gruntwork-io/go-commons/collections" + "github.com/gruntwork-io/terragrunt/pkg/cli" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -15,42 +16,42 @@ func TestMapFlagStringStringApply(t *testing.T) { t.Parallel() testCases := []struct { - flag MapFlag[string, string] + flag cli.MapFlag[string, string] args []string envs map[string]string expectedValue map[string]string expectedErr error }{ { - MapFlag[string, string]{Name: "foo", EnvVar: "FOO"}, + cli.MapFlag[string, string]{Name: "foo", EnvVar: "FOO"}, []string{"--foo", "arg1-key=arg1-value", "--foo", "arg2-key = arg2-value"}, map[string]string{"FOO": "env1-key=env1-value,env2-key=env2-value"}, map[string]string{"arg1-key": "arg1-value", "arg2-key": "arg2-value"}, nil, }, { - MapFlag[string, string]{Name: "foo", EnvVar: "FOO"}, + cli.MapFlag[string, string]{Name: "foo", EnvVar: "FOO"}, nil, map[string]string{"FOO": "env1-key=env1-value,env2-key = env2-value"}, map[string]string{"env1-key": "env1-value", "env2-key": "env2-value"}, nil, }, { - MapFlag[string, string]{Name: "foo", EnvVar: "FOO"}, + cli.MapFlag[string, string]{Name: "foo", EnvVar: "FOO"}, nil, nil, map[string]string{}, nil, }, { - MapFlag[string, string]{Name: "foo", EnvVar: "FOO", Destination: mockDestValue(map[string]string{"default1-key": "default1-value", "default2-key": "default2-value"})}, + cli.MapFlag[string, string]{Name: "foo", EnvVar: "FOO", Destination: mockDestValue(map[string]string{"default1-key": "default1-value", "default2-key": "default2-value"})}, []string{"--foo", "arg1-key=arg1-value", "--foo", "arg2-key=arg2-value"}, map[string]string{"FOO": "env1-key=env1-value,env2-key=env2-value"}, map[string]string{"arg1-key": "arg1-value", "arg2-key": "arg2-value"}, nil, }, { - MapFlag[string, string]{Name: "foo", Destination: mockDestValue(map[string]string{"default1-key": "default1-value", "default2-key": "default2-value"})}, + cli.MapFlag[string, string]{Name: "foo", Destination: mockDestValue(map[string]string{"default1-key": "default1-value", "default2-key": "default2-value"})}, nil, nil, map[string]string{"default1-key": "default1-value", "default2-key": "default2-value"}, @@ -73,21 +74,21 @@ func TestMapFlagStringIntApply(t *testing.T) { t.Parallel() testCases := []struct { - flag MapFlag[string, int] + flag cli.MapFlag[string, int] args []string envs map[string]string expectedValue map[string]int expectedErr error }{ { - MapFlag[string, int]{Name: "foo", EnvVar: "FOO"}, + cli.MapFlag[string, int]{Name: "foo", EnvVar: "FOO"}, []string{"--foo", "arg1-key=10", "--foo", "arg2-key=11"}, map[string]string{"FOO": "env1-key=20,env2-key=21"}, map[string]int{"arg1-key": 10, "arg2-key": 11}, nil, }, { - MapFlag[string, int]{Name: "foo", EnvVar: "FOO"}, + cli.MapFlag[string, int]{Name: "foo", EnvVar: "FOO"}, nil, map[string]string{"FOO": "env1-key=20,env2-key=21"}, map[string]int{"env1-key": 20, "env2-key": 21}, @@ -95,14 +96,14 @@ func TestMapFlagStringIntApply(t *testing.T) { }, { - MapFlag[string, int]{Name: "foo", EnvVar: "FOO", Destination: mockDestValue(map[string]int{"default1-key": 50, "default2-key": 51})}, + cli.MapFlag[string, int]{Name: "foo", EnvVar: "FOO", Destination: mockDestValue(map[string]int{"default1-key": 50, "default2-key": 51})}, []string{"--foo", "arg1-key=10", "--foo", "arg2-key=11"}, map[string]string{"FOO": "env1-key=20,env2-key=21"}, map[string]int{"arg1-key": 10, "arg2-key": 11}, nil, }, { - MapFlag[string, int]{Name: "foo", Destination: mockDestValue(map[string]int{"default1-key": 50, "default2-key": 51})}, + cli.MapFlag[string, int]{Name: "foo", Destination: mockDestValue(map[string]int{"default1-key": 50, "default2-key": 51})}, nil, nil, map[string]int{"default1-key": 50, "default2-key": 51}, @@ -121,7 +122,7 @@ func TestMapFlagStringIntApply(t *testing.T) { } } -func testMapFlagApply[K MapFlagKeyType, V MapFlagValueType](t *testing.T, flag *MapFlag[K, V], args []string, envs map[string]string, expectedValue map[K]V, expectedErr error) { +func testMapFlagApply[K cli.MapFlagKeyType, V cli.MapFlagValueType](t *testing.T, flag *cli.MapFlag[K, V], args []string, envs map[string]string, expectedValue map[K]V, expectedErr error) { var ( actualValue = map[K]V{} diff --git a/pkg/cli/slice_flag_test.go b/pkg/cli/slice_flag_test.go index 4d20bf8d0..fd58634de 100644 --- a/pkg/cli/slice_flag_test.go +++ b/pkg/cli/slice_flag_test.go @@ -1,4 +1,4 @@ -package cli +package cli_test import ( libflag "flag" @@ -7,6 +7,7 @@ import ( "strings" "testing" + "github.com/gruntwork-io/terragrunt/pkg/cli" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -15,42 +16,42 @@ func TestSliceFlagStringApply(t *testing.T) { t.Parallel() testCases := []struct { - flag SliceFlag[string] + flag cli.SliceFlag[string] args []string envs map[string]string expectedValue []string expectedErr error }{ { - SliceFlag[string]{Name: "foo", EnvVar: "FOO"}, + cli.SliceFlag[string]{Name: "foo", EnvVar: "FOO"}, []string{"--foo", "arg-value1", "--foo", "arg-value2"}, map[string]string{"FOO": "env-value"}, []string{"arg-value1", "arg-value2"}, nil, }, { - SliceFlag[string]{Name: "foo", EnvVar: "FOO"}, + cli.SliceFlag[string]{Name: "foo", EnvVar: "FOO"}, nil, map[string]string{"FOO": "env-value1,env-value2"}, []string{"env-value1", "env-value2"}, nil, }, { - SliceFlag[string]{Name: "foo", EnvVar: "FOO"}, + cli.SliceFlag[string]{Name: "foo", EnvVar: "FOO"}, nil, nil, nil, nil, }, { - SliceFlag[string]{Name: "foo", EnvVar: "FOO", Destination: mockDestValue([]string{"default-value1", "default-value2"})}, + cli.SliceFlag[string]{Name: "foo", EnvVar: "FOO", Destination: mockDestValue([]string{"default-value1", "default-value2"})}, []string{"--foo", "arg-value1", "--foo", "arg-value2"}, map[string]string{"FOO": "env-value1,env-value2"}, []string{"arg-value1", "arg-value2"}, nil, }, { - SliceFlag[string]{Name: "foo", Destination: mockDestValue([]string{"default-value1", "default-value2"})}, + cli.SliceFlag[string]{Name: "foo", Destination: mockDestValue([]string{"default-value1", "default-value2"})}, nil, nil, []string{"default-value1", "default-value2"}, @@ -73,28 +74,28 @@ func TestSliceFlagIntApply(t *testing.T) { t.Parallel() testCases := []struct { - flag SliceFlag[int] + flag cli.SliceFlag[int] args []string envs map[string]string expectedValue []int expectedErr error }{ { - SliceFlag[int]{Name: "foo", EnvVar: "FOO"}, + cli.SliceFlag[int]{Name: "foo", EnvVar: "FOO"}, []string{"--foo", "10", "--foo", "11"}, map[string]string{"FOO": "20,21"}, []int{10, 11}, nil, }, { - SliceFlag[int]{Name: "foo", EnvVar: "FOO"}, + cli.SliceFlag[int]{Name: "foo", EnvVar: "FOO"}, []string{}, map[string]string{"FOO": "20,21"}, []int{20, 21}, nil, }, { - SliceFlag[int]{Name: "foo", Destination: mockDestValue([]int{50, 51})}, + cli.SliceFlag[int]{Name: "foo", Destination: mockDestValue([]int{50, 51})}, nil, nil, []int{50, 51}, @@ -117,28 +118,28 @@ func TestSliceFlagInt64Apply(t *testing.T) { t.Parallel() testCases := []struct { - flag SliceFlag[int64] + flag cli.SliceFlag[int64] args []string envs map[string]string expectedValue []int64 expectedErr error }{ { - SliceFlag[int64]{Name: "foo", EnvVar: "FOO"}, + cli.SliceFlag[int64]{Name: "foo", EnvVar: "FOO"}, []string{"--foo", "10", "--foo", "11"}, map[string]string{"FOO": "20,21"}, []int64{10, 11}, nil, }, { - SliceFlag[int64]{Name: "foo", EnvVar: "FOO"}, + cli.SliceFlag[int64]{Name: "foo", EnvVar: "FOO"}, []string{}, map[string]string{"FOO": "20,21"}, []int64{20, 21}, nil, }, { - SliceFlag[int64]{Name: "foo", Destination: mockDestValue([]int64{50, 51})}, + cli.SliceFlag[int64]{Name: "foo", Destination: mockDestValue([]int64{50, 51})}, nil, nil, []int64{50, 51}, @@ -157,7 +158,7 @@ func TestSliceFlagInt64Apply(t *testing.T) { } } -func testSliceFlagApply[T SliceFlagType](t *testing.T, flag *SliceFlag[T], args []string, envs map[string]string, expectedValue []T, expectedErr error) { +func testSliceFlagApply[T cli.SliceFlagType](t *testing.T, flag *cli.SliceFlag[T], args []string, envs map[string]string, expectedValue []T, expectedErr error) { var ( actualValue []T diff --git a/pkg/cli/sort_test.go b/pkg/cli/sort_test.go index 0488b727b..8d6e3caaa 100644 --- a/pkg/cli/sort_test.go +++ b/pkg/cli/sort_test.go @@ -1,9 +1,10 @@ -package cli +package cli_test import ( "fmt" "testing" + "github.com/gruntwork-io/terragrunt/pkg/cli" "github.com/stretchr/testify/assert" ) @@ -27,7 +28,7 @@ func TestLexicographicLess(t *testing.T) { t.Run(fmt.Sprintf("testCase-%d", i), func(t *testing.T) { t.Parallel() - actual := LexicographicLess(testCase.i, testCase.j) + actual := cli.LexicographicLess(testCase.i, testCase.j) assert.Equal(t, testCase.expected, actual, testCase) }) } diff --git a/remote/remote_state.go b/remote/remote_state.go index 079fefa03..4f46d7b16 100644 --- a/remote/remote_state.go +++ b/remote/remote_state.go @@ -115,7 +115,7 @@ func (remoteState *RemoteState) NeedsInit(terragruntOptions *options.TerragruntO if initializer, hasInitializer := remoteStateInitializers[remoteState.Backend]; hasInitializer { // Remote state initializer says initialization is necessary return initializer.NeedsInitialization(remoteState, state.Backend, terragruntOptions) - } else if state.IsRemote() && remoteState.differsFrom(state.Backend, terragruntOptions) { + } else if state.IsRemote() && remoteState.DiffersFrom(state.Backend, terragruntOptions) { // If there's no remote state initializer, then just compare the the config values return true, nil } @@ -124,7 +124,7 @@ func (remoteState *RemoteState) NeedsInit(terragruntOptions *options.TerragruntO } // Returns true if this remote state is different than the given remote state that is currently being used by terraform. -func (remoteState *RemoteState) differsFrom(existingBackend *TerraformBackend, terragruntOptions *options.TerragruntOptions) bool { +func (remoteState *RemoteState) DiffersFrom(existingBackend *TerraformBackend, terragruntOptions *options.TerragruntOptions) bool { if existingBackend.Type != remoteState.Backend { terragruntOptions.Logger.Infof("Backend type has changed from %s to %s", existingBackend.Type, remoteState.Backend) return true diff --git a/remote/remote_state_gcs.go b/remote/remote_state_gcs.go index 58711c863..0fec53b38 100644 --- a/remote/remote_state_gcs.go +++ b/remote/remote_state_gcs.go @@ -92,7 +92,7 @@ func (gcsInitializer GCSInitializer) NeedsInitialization(remoteState *RemoteStat } project := remoteState.Config["project"] - if !gcsConfigValuesEqual(remoteState.Config, existingBackend, terragruntOptions) { + if !GCSConfigValuesEqual(remoteState.Config, existingBackend, terragruntOptions) { return true, nil } if project != nil { @@ -120,7 +120,7 @@ func (gcsInitializer GCSInitializer) NeedsInitialization(remoteState *RemoteStat } // Return true if the given config is in any way different than what is configured for the backend -func gcsConfigValuesEqual(config map[string]interface{}, existingBackend *TerraformBackend, terragruntOptions *options.TerragruntOptions) bool { +func GCSConfigValuesEqual(config map[string]interface{}, existingBackend *TerraformBackend, terragruntOptions *options.TerragruntOptions) bool { if existingBackend == nil { return len(config) == 0 } diff --git a/remote/remote_state_gcs_test.go b/remote/remote_state_gcs_test.go index 346ca5667..422bfa5d3 100644 --- a/remote/remote_state_gcs_test.go +++ b/remote/remote_state_gcs_test.go @@ -1,9 +1,10 @@ -package remote +package remote_test import ( "testing" "github.com/gruntwork-io/terragrunt/options" + "github.com/gruntwork-io/terragrunt/remote" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -17,13 +18,13 @@ func TestGCSConfigValuesEqual(t *testing.T) { testCases := []struct { name string config map[string]interface{} - backend *TerraformBackend + backend *remote.TerraformBackend shouldBeEqual bool }{ { "equal-both-empty", map[string]interface{}{}, - &TerraformBackend{Type: "gcs", Config: map[string]interface{}{}}, + &remote.TerraformBackend{Type: "gcs", Config: map[string]interface{}{}}, true, }, { @@ -35,49 +36,49 @@ func TestGCSConfigValuesEqual(t *testing.T) { { "equal-empty-and-nil-backend-config", map[string]interface{}{}, - &TerraformBackend{Type: "gcs"}, + &remote.TerraformBackend{Type: "gcs"}, true, }, { "equal-one-key", map[string]interface{}{"foo": "bar"}, - &TerraformBackend{Type: "gcs", Config: map[string]interface{}{"foo": "bar"}}, + &remote.TerraformBackend{Type: "gcs", Config: map[string]interface{}{"foo": "bar"}}, true, }, { "equal-multiple-keys", map[string]interface{}{"foo": "bar", "baz": []string{"a", "b", "c"}, "blah": 123, "bool": true}, - &TerraformBackend{Type: "gcs", Config: map[string]interface{}{"foo": "bar", "baz": []string{"a", "b", "c"}, "blah": 123, "bool": true}}, + &remote.TerraformBackend{Type: "gcs", Config: map[string]interface{}{"foo": "bar", "baz": []string{"a", "b", "c"}, "blah": 123, "bool": true}}, true, }, { "equal-encrypt-bool-handling", map[string]interface{}{"encrypt": true}, - &TerraformBackend{Type: "gcs", Config: map[string]interface{}{"encrypt": "true"}}, + &remote.TerraformBackend{Type: "gcs", Config: map[string]interface{}{"encrypt": "true"}}, true, }, { "equal-general-bool-handling", map[string]interface{}{"something": true, "encrypt": true}, - &TerraformBackend{Type: "gcs", Config: map[string]interface{}{"something": "true", "encrypt": "true"}}, + &remote.TerraformBackend{Type: "gcs", Config: map[string]interface{}{"something": "true", "encrypt": "true"}}, true, }, { "equal-ignore-gcs-labels", map[string]interface{}{"foo": "bar", "gcs_bucket_labels": []map[string]string{{"foo": "bar"}}}, - &TerraformBackend{Type: "gcs", Config: map[string]interface{}{"foo": "bar"}}, + &remote.TerraformBackend{Type: "gcs", Config: map[string]interface{}{"foo": "bar"}}, true, }, { "unequal-wrong-backend", map[string]interface{}{"foo": "bar"}, - &TerraformBackend{Type: "wrong", Config: map[string]interface{}{"foo": "bar"}}, + &remote.TerraformBackend{Type: "wrong", Config: map[string]interface{}{"foo": "bar"}}, false, }, { "unequal-values", map[string]interface{}{"foo": "bar"}, - &TerraformBackend{Type: "gcs", Config: map[string]interface{}{"foo": "different"}}, + &remote.TerraformBackend{Type: "gcs", Config: map[string]interface{}{"foo": "different"}}, false, }, { @@ -89,19 +90,19 @@ func TestGCSConfigValuesEqual(t *testing.T) { { "unequal-general-bool-handling", map[string]interface{}{"something": true}, - &TerraformBackend{Type: "gcs", Config: map[string]interface{}{"something": "false"}}, + &remote.TerraformBackend{Type: "gcs", Config: map[string]interface{}{"something": "false"}}, false, }, { "equal-null-ignored", map[string]interface{}{"something": "foo"}, - &TerraformBackend{Type: "gcs", Config: map[string]interface{}{"something": "foo", "ignored-because-null": nil}}, + &remote.TerraformBackend{Type: "gcs", Config: map[string]interface{}{"something": "foo", "ignored-because-null": nil}}, true, }, { "terragrunt-only-configs-remain-intact", map[string]interface{}{"something": "foo", "skip_bucket_creation": true}, - &TerraformBackend{Type: "gcs", Config: map[string]interface{}{"something": "foo"}}, + &remote.TerraformBackend{Type: "gcs", Config: map[string]interface{}{"something": "foo"}}, true, }, } @@ -119,7 +120,7 @@ func TestGCSConfigValuesEqual(t *testing.T) { config[key] = value } - actual := gcsConfigValuesEqual(config, testCase.backend, terragruntOptions) + actual := remote.GCSConfigValuesEqual(config, testCase.backend, terragruntOptions) assert.Equal(t, testCase.shouldBeEqual, actual) // Ensure the config remains unchanged by the comparison diff --git a/remote/remote_state_s3.go b/remote/remote_state_s3.go index 924914d19..32f8a2e5b 100644 --- a/remote/remote_state_s3.go +++ b/remote/remote_state_s3.go @@ -39,7 +39,7 @@ const ( * access logs, in case it has to create them. */ type ExtendedRemoteStateConfigS3 struct { - remoteStateConfigS3 RemoteStateConfigS3 + RemoteStateConfigS3 RemoteStateConfigS3 `mapstructure:",squash"` S3BucketTags map[string]string `mapstructure:"s3_bucket_tags"` DynamotableTags map[string]string `mapstructure:"dynamodb_table_tags"` @@ -119,23 +119,23 @@ type RemoteStateConfigS3 struct { // Builds a session config for AWS related requests from the RemoteStateConfigS3 configuration func (c *ExtendedRemoteStateConfigS3) GetAwsSessionConfig() *aws_helper.AwsSessionConfig { return &aws_helper.AwsSessionConfig{ - Region: c.remoteStateConfigS3.Region, - CustomS3Endpoint: c.remoteStateConfigS3.Endpoint, - CustomDynamoDBEndpoint: c.remoteStateConfigS3.DynamoDBEndpoint, - Profile: c.remoteStateConfigS3.Profile, - RoleArn: c.remoteStateConfigS3.GetSessionRoleArn(), - ExternalID: c.remoteStateConfigS3.GetExternalId(), - SessionName: c.remoteStateConfigS3.GetSessionName(), - CredsFilename: c.remoteStateConfigS3.CredsFilename, - S3ForcePathStyle: c.remoteStateConfigS3.S3ForcePathStyle, + Region: c.RemoteStateConfigS3.Region, + CustomS3Endpoint: c.RemoteStateConfigS3.Endpoint, + CustomDynamoDBEndpoint: c.RemoteStateConfigS3.DynamoDBEndpoint, + Profile: c.RemoteStateConfigS3.Profile, + RoleArn: c.RemoteStateConfigS3.GetSessionRoleArn(), + ExternalID: c.RemoteStateConfigS3.GetExternalId(), + SessionName: c.RemoteStateConfigS3.GetSessionName(), + CredsFilename: c.RemoteStateConfigS3.CredsFilename, + S3ForcePathStyle: c.RemoteStateConfigS3.S3ForcePathStyle, DisableComputeChecksums: c.DisableAWSClientChecksums, } } // Builds AWS S3 logging input struct from the configuration. -func (c *ExtendedRemoteStateConfigS3) createS3LoggingInput() s3.PutBucketLoggingInput { +func (c *ExtendedRemoteStateConfigS3) CreateS3LoggingInput() s3.PutBucketLoggingInput { loggingInput := s3.PutBucketLoggingInput{ - Bucket: aws.String(c.remoteStateConfigS3.Bucket), + Bucket: aws.String(c.RemoteStateConfigS3.Bucket), BucketLoggingStatus: &s3.BucketLoggingStatus{ LoggingEnabled: &s3.LoggingEnabled{ TargetBucket: aws.String(c.AccessLoggingBucketName), @@ -222,7 +222,7 @@ func (s3Initializer S3Initializer) NeedsInitialization(remoteState *RemoteState, delete(remoteState.Config, "lock_table") } - if !configValuesEqual(remoteState.Config, existingBackend, terragruntOptions) { + if !ConfigValuesEqual(remoteState.Config, existingBackend, terragruntOptions) { return true, nil } @@ -230,7 +230,7 @@ func (s3Initializer S3Initializer) NeedsInitialization(remoteState *RemoteState, if err != nil { return false, err } - s3Config := s3ConfigExtended.remoteStateConfigS3 + s3Config := s3ConfigExtended.RemoteStateConfigS3 sessionConfig := s3ConfigExtended.GetAwsSessionConfig() @@ -269,7 +269,7 @@ func (s3Initializer S3Initializer) NeedsInitialization(remoteState *RemoteState, } // Return true if the given config is in any way different than what is configured for the backend -func configValuesEqual(config map[string]interface{}, existingBackend *TerraformBackend, terragruntOptions *options.TerragruntOptions) bool { +func ConfigValuesEqual(config map[string]interface{}, existingBackend *TerraformBackend, terragruntOptions *options.TerragruntOptions) bool { if existingBackend == nil { return len(config) == 0 } @@ -335,11 +335,11 @@ func (s3Initializer S3Initializer) Initialize(ctx context.Context, remoteState * return errors.WithStackTrace(err) } - if err := validateS3Config(s3ConfigExtended); err != nil { + if err := ValidateS3Config(s3ConfigExtended); err != nil { return errors.WithStackTrace(err) } - var s3Config = s3ConfigExtended.remoteStateConfigS3 + var s3Config = s3ConfigExtended.RemoteStateConfigS3 cacheKey := s3Initializer.buildInitializerCacheKey(&s3Config) if initialized, hit := initializedRemoteStateCache.Get(ctx, cacheKey); initialized && hit { @@ -423,7 +423,7 @@ func (s3Initializer S3Initializer) GetTerraformInitArgs(config map[string]interf if key == assumeRoleKey { if mapVal, ok := val.(map[string]interface{}); ok { - filteredConfig[key] = wrapMapToSingleLineHcl(mapVal) + filteredConfig[key] = WrapMapToSingleLineHcl(mapVal) continue } } @@ -452,14 +452,14 @@ func ParseExtendedS3Config(config map[string]interface{}) (*ExtendedRemoteStateC extendedConfig.AccessLoggingTargetPrefix = DefaultS3BucketAccessLoggingTargetPrefix } - extendedConfig.remoteStateConfigS3 = s3Config + extendedConfig.RemoteStateConfigS3 = s3Config return &extendedConfig, nil } // Validate all the parameters of the given S3 remote state configuration -func validateS3Config(extendedConfig *ExtendedRemoteStateConfigS3) error { - var config = extendedConfig.remoteStateConfigS3 +func ValidateS3Config(extendedConfig *ExtendedRemoteStateConfigS3) error { + var config = extendedConfig.RemoteStateConfigS3 if config.Region == "" { return errors.WithStackTrace(MissingRequiredS3RemoteStateConfig("region")) @@ -479,14 +479,14 @@ func validateS3Config(extendedConfig *ExtendedRemoteStateConfigS3) error { // If the bucket specified in the given config doesn't already exist, prompt the user to create it, and if the user // confirms, create the bucket and enable versioning for it. func createS3BucketIfNecessary(ctx context.Context, s3Client *s3.S3, config *ExtendedRemoteStateConfigS3, terragruntOptions *options.TerragruntOptions) error { - if DoesS3BucketExist(s3Client, &config.remoteStateConfigS3.Bucket) { + if DoesS3BucketExist(s3Client, &config.RemoteStateConfigS3.Bucket) { return nil } if terragruntOptions.FailIfBucketCreationRequired { - return BucketCreationNotAllowed(config.remoteStateConfigS3.Bucket) + return BucketCreationNotAllowed(config.RemoteStateConfigS3.Bucket) } - prompt := fmt.Sprintf("Remote state S3 bucket %s does not exist or you don't have permissions to access it. Would you like Terragrunt to create it?", config.remoteStateConfigS3.Bucket) + prompt := fmt.Sprintf("Remote state S3 bucket %s does not exist or you don't have permissions to access it. Would you like Terragrunt to create it?", config.RemoteStateConfigS3.Bucket) shouldCreateBucket, err := shell.PromptUserForYesNo(prompt, terragruntOptions) if err != nil { return err @@ -499,7 +499,7 @@ func createS3BucketIfNecessary(ctx context.Context, s3Client *s3.S3, config *Ext // the S3 bucket, we do so in a retry loop with a sleep between retries that will hopefully work around the // eventual consistency issues. Each S3 operation should be idempotent, so redoing steps that have already // been performed should be a no-op. - description := "Create S3 bucket with retry " + config.remoteStateConfigS3.Bucket + description := "Create S3 bucket with retry " + config.RemoteStateConfigS3.Bucket return util.DoWithRetry(ctx, description, s3MaxRetries, s3SleepBetweenRetries, logrus.DebugLevel, func(ctx context.Context) error { err := CreateS3BucketWithVersioningSSEncryptionAndAccessLogging(s3Client, config, terragruntOptions) @@ -518,11 +518,11 @@ func createS3BucketIfNecessary(ctx context.Context, s3Client *s3.S3, config *Ext } func updateS3BucketIfNecessary(s3Client *s3.S3, config *ExtendedRemoteStateConfigS3, terragruntOptions *options.TerragruntOptions) error { - if !DoesS3BucketExist(s3Client, &config.remoteStateConfigS3.Bucket) { + if !DoesS3BucketExist(s3Client, &config.RemoteStateConfigS3.Bucket) { if terragruntOptions.FailIfBucketCreationRequired { - return BucketCreationNotAllowed(config.remoteStateConfigS3.Bucket) + return BucketCreationNotAllowed(config.RemoteStateConfigS3.Bucket) } - return errors.WithStackTrace(fmt.Errorf("remote state S3 bucket %s does not exist or you don't have permissions to access it", config.remoteStateConfigS3.Bucket)) + return errors.WithStackTrace(fmt.Errorf("remote state S3 bucket %s does not exist or you don't have permissions to access it", config.RemoteStateConfigS3.Bucket)) } needUpdate, bucketUpdatesRequired, err := checkIfS3BucketNeedsUpdate(s3Client, config, terragruntOptions) @@ -535,7 +535,7 @@ func updateS3BucketIfNecessary(s3Client *s3.S3, config *ExtendedRemoteStateConfi return nil } - prompt := fmt.Sprintf("Remote state S3 bucket %s is out of date. Would you like Terragrunt to update it?", config.remoteStateConfigS3.Bucket) + prompt := fmt.Sprintf("Remote state S3 bucket %s is out of date. Would you like Terragrunt to update it?", config.RemoteStateConfigS3.Bucket) shouldUpdateBucket, err := shell.PromptUserForYesNo(prompt, terragruntOptions) if err != nil { return err @@ -547,34 +547,34 @@ func updateS3BucketIfNecessary(s3Client *s3.S3, config *ExtendedRemoteStateConfi if bucketUpdatesRequired.Versioning { if config.SkipBucketVersioning { - terragruntOptions.Logger.Debugf("Versioning is disabled for the remote state S3 bucket %s using 'skip_bucket_versioning' config.", config.remoteStateConfigS3.Bucket) - } else if err := EnableVersioningForS3Bucket(s3Client, &config.remoteStateConfigS3, terragruntOptions); err != nil { + terragruntOptions.Logger.Debugf("Versioning is disabled for the remote state S3 bucket %s using 'skip_bucket_versioning' config.", config.RemoteStateConfigS3.Bucket) + } else if err := EnableVersioningForS3Bucket(s3Client, &config.RemoteStateConfigS3, terragruntOptions); err != nil { return err } } if bucketUpdatesRequired.SSEEncryption { - msg := fmt.Sprintf("Encryption is not enabled on the S3 remote state bucket %s. Terraform state files may contain secrets, so we STRONGLY recommend enabling encryption!", config.remoteStateConfigS3.Bucket) + msg := fmt.Sprintf("Encryption is not enabled on the S3 remote state bucket %s. Terraform state files may contain secrets, so we STRONGLY recommend enabling encryption!", config.RemoteStateConfigS3.Bucket) if config.SkipBucketSSEncryption { terragruntOptions.Logger.Debug(msg) - terragruntOptions.Logger.Debugf("Server-Side Encryption enabling is disabled for the remote state AWS S3 bucket %s using 'skip_bucket_ssencryption' config.", config.remoteStateConfigS3.Bucket) + terragruntOptions.Logger.Debugf("Server-Side Encryption enabling is disabled for the remote state AWS S3 bucket %s using 'skip_bucket_ssencryption' config.", config.RemoteStateConfigS3.Bucket) return nil } else { terragruntOptions.Logger.Warn(msg) } - terragruntOptions.Logger.Infof("Enabling Server-Side Encryption for the remote state AWS S3 bucket %s.", config.remoteStateConfigS3.Bucket) - if err := EnableSSEForS3BucketWide(s3Client, config.remoteStateConfigS3.Bucket, fetchEncryptionAlgorithm(config), config, terragruntOptions); err != nil { - terragruntOptions.Logger.Errorf("Failed to enable Server-Side Encryption for the remote state AWS S3 bucket %s: %v", config.remoteStateConfigS3.Bucket, err) + terragruntOptions.Logger.Infof("Enabling Server-Side Encryption for the remote state AWS S3 bucket %s.", config.RemoteStateConfigS3.Bucket) + if err := EnableSSEForS3BucketWide(s3Client, config.RemoteStateConfigS3.Bucket, fetchEncryptionAlgorithm(config), config, terragruntOptions); err != nil { + terragruntOptions.Logger.Errorf("Failed to enable Server-Side Encryption for the remote state AWS S3 bucket %s: %v", config.RemoteStateConfigS3.Bucket, err) return err } - terragruntOptions.Logger.Infof("Successfully enabled Server-Side Encryption for the remote state AWS S3 bucket %s.", config.remoteStateConfigS3.Bucket) + terragruntOptions.Logger.Infof("Successfully enabled Server-Side Encryption for the remote state AWS S3 bucket %s.", config.RemoteStateConfigS3.Bucket) } if bucketUpdatesRequired.RootAccess { if config.SkipBucketRootAccess { - terragruntOptions.Logger.Debugf("Root access is disabled for the remote state S3 bucket %s using 'skip_bucket_root_access' config.", config.remoteStateConfigS3.Bucket) + terragruntOptions.Logger.Debugf("Root access is disabled for the remote state S3 bucket %s using 'skip_bucket_root_access' config.", config.RemoteStateConfigS3.Bucket) } else if err := EnableRootAccesstoS3Bucket(s3Client, config, terragruntOptions); err != nil { return err } @@ -582,15 +582,15 @@ func updateS3BucketIfNecessary(s3Client *s3.S3, config *ExtendedRemoteStateConfi if bucketUpdatesRequired.EnforcedTLS { if config.SkipBucketEnforcedTLS { - terragruntOptions.Logger.Debugf("Enforced TLS is disabled for the remote state AWS S3 bucket %s using 'skip_bucket_enforced_tls' config.", config.remoteStateConfigS3.Bucket) - } else if err := EnableEnforcedTLSAccesstoS3Bucket(s3Client, config.remoteStateConfigS3.Bucket, config, terragruntOptions); err != nil { + terragruntOptions.Logger.Debugf("Enforced TLS is disabled for the remote state AWS S3 bucket %s using 'skip_bucket_enforced_tls' config.", config.RemoteStateConfigS3.Bucket) + } else if err := EnableEnforcedTLSAccesstoS3Bucket(s3Client, config.RemoteStateConfigS3.Bucket, config, terragruntOptions); err != nil { return err } } if bucketUpdatesRequired.AccessLogging { if config.SkipBucketAccessLogging { - terragruntOptions.Logger.Debugf("Access logging is disabled for the remote state AWS S3 bucket %s using 'skip_bucket_access_logging' config.", config.remoteStateConfigS3.Bucket) + terragruntOptions.Logger.Debugf("Access logging is disabled for the remote state AWS S3 bucket %s using 'skip_bucket_access_logging' config.", config.RemoteStateConfigS3.Bucket) } else { if config.AccessLoggingBucketName != "" { if err := configureAccessLogBucket(terragruntOptions, s3Client, config); err != nil { @@ -598,15 +598,15 @@ func updateS3BucketIfNecessary(s3Client *s3.S3, config *ExtendedRemoteStateConfi return nil //nolint:nilerr } } else { - terragruntOptions.Logger.Debugf("Access Logging is disabled for the remote state AWS S3 bucket %s", config.remoteStateConfigS3.Bucket) + terragruntOptions.Logger.Debugf("Access Logging is disabled for the remote state AWS S3 bucket %s", config.RemoteStateConfigS3.Bucket) } } } if bucketUpdatesRequired.PublicAccess { if config.SkipBucketPublicAccessBlocking { - terragruntOptions.Logger.Debugf("Public access blocking is disabled for the remote state AWS S3 bucket %s using 'skip_bucket_public_access_blocking' config.", config.remoteStateConfigS3.Bucket) - } else if err := EnablePublicAccessBlockingForS3Bucket(s3Client, config.remoteStateConfigS3.Bucket, terragruntOptions); err != nil { + terragruntOptions.Logger.Debugf("Public access blocking is disabled for the remote state AWS S3 bucket %s using 'skip_bucket_public_access_blocking' config.", config.RemoteStateConfigS3.Bucket) + } else if err := EnablePublicAccessBlockingForS3Bucket(s3Client, config.RemoteStateConfigS3.Bucket, terragruntOptions); err != nil { return err } } @@ -616,10 +616,10 @@ func updateS3BucketIfNecessary(s3Client *s3.S3, config *ExtendedRemoteStateConfi // configureAccessLogBucket - configure access log bucket. func configureAccessLogBucket(terragruntOptions *options.TerragruntOptions, s3Client *s3.S3, config *ExtendedRemoteStateConfigS3) error { - terragruntOptions.Logger.Debugf("Enabling bucket-wide Access Logging on AWS S3 bucket %s - using as TargetBucket %s", config.remoteStateConfigS3.Bucket, config.AccessLoggingBucketName) + terragruntOptions.Logger.Debugf("Enabling bucket-wide Access Logging on AWS S3 bucket %s - using as TargetBucket %s", config.RemoteStateConfigS3.Bucket, config.AccessLoggingBucketName) if err := CreateLogsS3BucketIfNecessary(s3Client, aws.String(config.AccessLoggingBucketName), terragruntOptions); err != nil { - terragruntOptions.Logger.Errorf("Could not create logs bucket %s for AWS S3 bucket %s\n%s", config.AccessLoggingBucketName, config.remoteStateConfigS3.Bucket, err.Error()) + terragruntOptions.Logger.Errorf("Could not create logs bucket %s for AWS S3 bucket %s\n%s", config.AccessLoggingBucketName, config.RemoteStateConfigS3.Bucket, err.Error()) return errors.WithStackTrace(err) } @@ -631,7 +631,7 @@ func configureAccessLogBucket(terragruntOptions *options.TerragruntOptions, s3Cl } if err := EnableAccessLoggingForS3BucketWide(s3Client, config, terragruntOptions); err != nil { - terragruntOptions.Logger.Errorf("Could not enable access logging on %s\n%s", config.remoteStateConfigS3.Bucket, err.Error()) + terragruntOptions.Logger.Errorf("Could not enable access logging on %s\n%s", config.RemoteStateConfigS3.Bucket, err.Error()) return errors.WithStackTrace(err) } @@ -665,7 +665,7 @@ func checkIfS3BucketNeedsUpdate(s3Client *s3.S3, config *ExtendedRemoteStateConf var configBucket S3BucketUpdatesRequired if !config.SkipBucketVersioning { - enabled, err := checkIfVersioningEnabled(s3Client, &config.remoteStateConfigS3, terragruntOptions) + enabled, err := checkIfVersioningEnabled(s3Client, &config.RemoteStateConfigS3, terragruntOptions) if err != nil { return false, configBucket, err } @@ -689,7 +689,7 @@ func checkIfS3BucketNeedsUpdate(s3Client *s3.S3, config *ExtendedRemoteStateConf } if !config.SkipBucketRootAccess { - enabled, err := checkIfBucketRootAccess(s3Client, &config.remoteStateConfigS3, terragruntOptions) + enabled, err := checkIfBucketRootAccess(s3Client, &config.RemoteStateConfigS3, terragruntOptions) if err != nil { return false, configBucket, err } @@ -701,7 +701,7 @@ func checkIfS3BucketNeedsUpdate(s3Client *s3.S3, config *ExtendedRemoteStateConf } if !config.SkipBucketEnforcedTLS { - enabled, err := checkIfBucketEnforcedTLS(s3Client, &config.remoteStateConfigS3, terragruntOptions) + enabled, err := checkIfBucketEnforcedTLS(s3Client, &config.RemoteStateConfigS3, terragruntOptions) if err != nil { return false, configBucket, err } @@ -725,7 +725,7 @@ func checkIfS3BucketNeedsUpdate(s3Client *s3.S3, config *ExtendedRemoteStateConf } if !config.SkipBucketPublicAccessBlocking { - enabled, err := checkIfS3PublicAccessBlockingEnabled(s3Client, &config.remoteStateConfigS3, terragruntOptions) + enabled, err := checkIfS3PublicAccessBlockingEnabled(s3Client, &config.RemoteStateConfigS3, terragruntOptions) if err != nil { return false, configBucket, err } @@ -737,7 +737,7 @@ func checkIfS3BucketNeedsUpdate(s3Client *s3.S3, config *ExtendedRemoteStateConf // show update message if any of the above configs are not set if len(needUpdate) > 0 { - terragruntOptions.Logger.Warnf("The remote state S3 bucket %s needs to be updated:", config.remoteStateConfigS3.Bucket) + terragruntOptions.Logger.Warnf("The remote state S3 bucket %s needs to be updated:", config.RemoteStateConfigS3.Bucket) for _, update := range needUpdate { terragruntOptions.Logger.Warnf(" - %s", update) } @@ -769,42 +769,42 @@ func checkIfVersioningEnabled(s3Client *s3.S3, config *RemoteStateConfigS3, terr // Create the given S3 bucket and enable versioning for it func CreateS3BucketWithVersioningSSEncryptionAndAccessLogging(s3Client *s3.S3, config *ExtendedRemoteStateConfigS3, terragruntOptions *options.TerragruntOptions) error { - terragruntOptions.Logger.Debugf("Create S3 bucket %s with versioning, SSE encryption, and access logging.", config.remoteStateConfigS3.Bucket) + terragruntOptions.Logger.Debugf("Create S3 bucket %s with versioning, SSE encryption, and access logging.", config.RemoteStateConfigS3.Bucket) - err := CreateS3Bucket(s3Client, aws.String(config.remoteStateConfigS3.Bucket), terragruntOptions) + err := CreateS3Bucket(s3Client, aws.String(config.RemoteStateConfigS3.Bucket), terragruntOptions) if err != nil { - if accessError := checkBucketAccess(s3Client, aws.String(config.remoteStateConfigS3.Bucket), aws.String(config.remoteStateConfigS3.Key)); accessError != nil { + if accessError := checkBucketAccess(s3Client, aws.String(config.RemoteStateConfigS3.Bucket), aws.String(config.RemoteStateConfigS3.Key)); accessError != nil { return accessError } if isBucketAlreadyOwnedByYouError(err) { - terragruntOptions.Logger.Debugf("Looks like you're already creating bucket %s at the same time. Will not attempt to create it again.", config.remoteStateConfigS3.Bucket) - return WaitUntilS3BucketExists(s3Client, &config.remoteStateConfigS3, terragruntOptions) + terragruntOptions.Logger.Debugf("Looks like you're already creating bucket %s at the same time. Will not attempt to create it again.", config.RemoteStateConfigS3.Bucket) + return WaitUntilS3BucketExists(s3Client, &config.RemoteStateConfigS3, terragruntOptions) } return err } - if err := WaitUntilS3BucketExists(s3Client, &config.remoteStateConfigS3, terragruntOptions); err != nil { + if err := WaitUntilS3BucketExists(s3Client, &config.RemoteStateConfigS3, terragruntOptions); err != nil { return err } if config.SkipBucketRootAccess { - terragruntOptions.Logger.Debugf("Root access is disabled for the remote state S3 bucket %s using 'skip_bucket_root_access' config.", config.remoteStateConfigS3.Bucket) + terragruntOptions.Logger.Debugf("Root access is disabled for the remote state S3 bucket %s using 'skip_bucket_root_access' config.", config.RemoteStateConfigS3.Bucket) } else if err := EnableRootAccesstoS3Bucket(s3Client, config, terragruntOptions); err != nil { return err } if config.SkipBucketEnforcedTLS { - terragruntOptions.Logger.Debugf("TLS enforcement is disabled for the remote state S3 bucket %s using 'skip_bucket_enforced_tls' config.", config.remoteStateConfigS3.Bucket) - } else if err := EnableEnforcedTLSAccesstoS3Bucket(s3Client, config.remoteStateConfigS3.Bucket, config, terragruntOptions); err != nil { + terragruntOptions.Logger.Debugf("TLS enforcement is disabled for the remote state S3 bucket %s using 'skip_bucket_enforced_tls' config.", config.RemoteStateConfigS3.Bucket) + } else if err := EnableEnforcedTLSAccesstoS3Bucket(s3Client, config.RemoteStateConfigS3.Bucket, config, terragruntOptions); err != nil { return err } if config.SkipBucketPublicAccessBlocking { - terragruntOptions.Logger.Debugf("Public access blocking is disabled for the remote state AWS S3 bucket %s using 'skip_bucket_public_access_blocking' config.", config.remoteStateConfigS3.Bucket) - } else if err := EnablePublicAccessBlockingForS3Bucket(s3Client, config.remoteStateConfigS3.Bucket, terragruntOptions); err != nil { + terragruntOptions.Logger.Debugf("Public access blocking is disabled for the remote state AWS S3 bucket %s using 'skip_bucket_public_access_blocking' config.", config.RemoteStateConfigS3.Bucket) + } else if err := EnablePublicAccessBlockingForS3Bucket(s3Client, config.RemoteStateConfigS3.Bucket, terragruntOptions); err != nil { return err } @@ -813,19 +813,19 @@ func CreateS3BucketWithVersioningSSEncryptionAndAccessLogging(s3Client *s3.S3, c } if config.SkipBucketVersioning { - terragruntOptions.Logger.Debugf("Versioning is disabled for the remote state S3 bucket %s using 'skip_bucket_versioning' config.", config.remoteStateConfigS3.Bucket) - } else if err := EnableVersioningForS3Bucket(s3Client, &config.remoteStateConfigS3, terragruntOptions); err != nil { + terragruntOptions.Logger.Debugf("Versioning is disabled for the remote state S3 bucket %s using 'skip_bucket_versioning' config.", config.RemoteStateConfigS3.Bucket) + } else if err := EnableVersioningForS3Bucket(s3Client, &config.RemoteStateConfigS3, terragruntOptions); err != nil { return err } if config.SkipBucketSSEncryption { - terragruntOptions.Logger.Debugf("Server-Side Encryption is disabled for the remote state AWS S3 bucket %s using 'skip_bucket_ssencryption' config.", config.remoteStateConfigS3.Bucket) - } else if err := EnableSSEForS3BucketWide(s3Client, config.remoteStateConfigS3.Bucket, fetchEncryptionAlgorithm(config), config, terragruntOptions); err != nil { + terragruntOptions.Logger.Debugf("Server-Side Encryption is disabled for the remote state AWS S3 bucket %s using 'skip_bucket_ssencryption' config.", config.RemoteStateConfigS3.Bucket) + } else if err := EnableSSEForS3BucketWide(s3Client, config.RemoteStateConfigS3.Bucket, fetchEncryptionAlgorithm(config), config, terragruntOptions); err != nil { return err } if config.SkipBucketAccessLogging { - terragruntOptions.Logger.Warnf("Terragrunt configuration option 'skip_bucket_accesslogging' is now deprecated. Access logging for the state bucket %s is disabled by default. To enable access logging for bucket %s, please provide property `accesslogging_bucket_name` in the terragrunt config file. For more details, please refer to the Terragrunt documentation.", config.remoteStateConfigS3.Bucket, config.remoteStateConfigS3.Bucket) + terragruntOptions.Logger.Warnf("Terragrunt configuration option 'skip_bucket_accesslogging' is now deprecated. Access logging for the state bucket %s is disabled by default. To enable access logging for bucket %s, please provide property `accesslogging_bucket_name` in the terragrunt config file. For more details, please refer to the Terragrunt documentation.", config.RemoteStateConfigS3.Bucket, config.RemoteStateConfigS3.Bucket) } if config.AccessLoggingBucketName != "" { @@ -834,7 +834,7 @@ func CreateS3BucketWithVersioningSSEncryptionAndAccessLogging(s3Client *s3.S3, c return nil //nolint:nilerr } } else { - terragruntOptions.Logger.Debugf("Access Logging is disabled for the remote state AWS S3 bucket %s", config.remoteStateConfigS3.Bucket) + terragruntOptions.Logger.Debugf("Access Logging is disabled for the remote state AWS S3 bucket %s", config.RemoteStateConfigS3.Bucket) } if err := TagS3BucketAccessLogging(s3Client, config, terragruntOptions); err != nil { @@ -893,7 +893,7 @@ func TagS3BucketAccessLogging(s3Client *s3.S3, config *ExtendedRemoteStateConfig func TagS3Bucket(s3Client *s3.S3, config *ExtendedRemoteStateConfigS3, terragruntOptions *options.TerragruntOptions) error { if config.S3BucketTags == nil || len(config.S3BucketTags) == 0 { - terragruntOptions.Logger.Debugf("No tags specified for bucket %s.", config.remoteStateConfigS3.Bucket) + terragruntOptions.Logger.Debugf("No tags specified for bucket %s.", config.RemoteStateConfigS3.Bucket) return nil } @@ -903,7 +903,7 @@ func TagS3Bucket(s3Client *s3.S3, config *ExtendedRemoteStateConfigS3, terragrun terragruntOptions.Logger.Debugf("Tagging S3 bucket with %s", config.S3BucketTags) putBucketTaggingInput := s3.PutBucketTaggingInput{ - Bucket: aws.String(config.remoteStateConfigS3.Bucket), + Bucket: aws.String(config.RemoteStateConfigS3.Bucket), Tagging: &s3.Tagging{ TagSet: tagsConverted, }, @@ -981,7 +981,7 @@ func isBucketCreationErrorRetriable(err error) bool { // Add a policy to allow root access to the bucket func EnableRootAccesstoS3Bucket(s3Client *s3.S3, config *ExtendedRemoteStateConfigS3, terragruntOptions *options.TerragruntOptions) error { - bucket := config.remoteStateConfigS3.Bucket + bucket := config.RemoteStateConfigS3.Bucket terragruntOptions.Logger.Debugf("Enabling root access to S3 bucket %s", bucket) accountID, err := aws_helper.GetAWSAccountID(config.GetAwsSessionConfig(), terragruntOptions) @@ -1249,7 +1249,7 @@ func EnableSSEForS3BucketWide(s3Client *s3.S3, bucketName string, algorithm stri if algorithm == s3.ServerSideEncryptionAwsKms && config.BucketSSEKMSKeyID != "" { defEnc.KMSMasterKeyID = aws.String(config.BucketSSEKMSKeyID) } else if algorithm == s3.ServerSideEncryptionAwsKms { - kmsKeyID := fmt.Sprintf("arn:%s:kms:%s:%s:alias/aws/s3", partition, config.remoteStateConfigS3.Region, accountID) + kmsKeyID := fmt.Sprintf("arn:%s:kms:%s:%s:alias/aws/s3", partition, config.RemoteStateConfigS3.Region, accountID) defEnc.KMSMasterKeyID = aws.String(kmsKeyID) } @@ -1277,13 +1277,13 @@ func fetchEncryptionAlgorithm(config *ExtendedRemoteStateConfigS3) string { } func checkIfSSEForS3Enabled(s3Client *s3.S3, config *ExtendedRemoteStateConfigS3, terragruntOptions *options.TerragruntOptions) (bool, error) { - terragruntOptions.Logger.Debugf("Checking if SSE is enabled for AWS S3 bucket %s", config.remoteStateConfigS3.Bucket) + terragruntOptions.Logger.Debugf("Checking if SSE is enabled for AWS S3 bucket %s", config.RemoteStateConfigS3.Bucket) - input := &s3.GetBucketEncryptionInput{Bucket: aws.String(config.remoteStateConfigS3.Bucket)} + input := &s3.GetBucketEncryptionInput{Bucket: aws.String(config.RemoteStateConfigS3.Bucket)} output, err := s3Client.GetBucketEncryption(input) if err != nil { - terragruntOptions.Logger.Debugf("Error checking if SSE is enabled for AWS S3 bucket %s: %s", config.remoteStateConfigS3.Bucket, err.Error()) - return false, errors.WithStackTraceAndPrefix(err, "Error checking if SSE is enabled for AWS S3 bucket %s", config.remoteStateConfigS3.Bucket) + terragruntOptions.Logger.Debugf("Error checking if SSE is enabled for AWS S3 bucket %s: %s", config.RemoteStateConfigS3.Bucket, err.Error()) + return false, errors.WithStackTraceAndPrefix(err, "Error checking if SSE is enabled for AWS S3 bucket %s", config.RemoteStateConfigS3.Bucket) } if output.ServerSideEncryptionConfiguration == nil { @@ -1307,21 +1307,21 @@ func checkIfSSEForS3Enabled(s3Client *s3.S3, config *ExtendedRemoteStateConfigS3 // Enable bucket-wide Access Logging for the AWS S3 bucket specified in the given config func EnableAccessLoggingForS3BucketWide(s3Client *s3.S3, config *ExtendedRemoteStateConfigS3, terragruntOptions *options.TerragruntOptions) error { - bucket := config.remoteStateConfigS3.Bucket + bucket := config.RemoteStateConfigS3.Bucket logsBucket := config.AccessLoggingBucketName logsBucketPrefix := config.AccessLoggingTargetPrefix if !config.SkipAccessLoggingBucketAcl { if err := configureBucketAccessLoggingAcl(s3Client, aws.String(logsBucket), terragruntOptions); err != nil { - return errors.WithStackTraceAndPrefix(err, "Error configuring bucket access logging ACL on S3 bucket %s", config.remoteStateConfigS3.Bucket) + return errors.WithStackTraceAndPrefix(err, "Error configuring bucket access logging ACL on S3 bucket %s", config.RemoteStateConfigS3.Bucket) } } - loggingInput := config.createS3LoggingInput() + loggingInput := config.CreateS3LoggingInput() terragruntOptions.Logger.Debugf("Putting bucket logging on S3 bucket %s with TargetBucket %s and TargetPrefix %s\n%s", bucket, logsBucket, logsBucketPrefix, loggingInput) if _, err := s3Client.PutBucketLogging(&loggingInput); err != nil { - return errors.WithStackTraceAndPrefix(err, "Error enabling bucket-wide Access Logging on AWS S3 bucket %s", config.remoteStateConfigS3.Bucket) + return errors.WithStackTraceAndPrefix(err, "Error enabling bucket-wide Access Logging on AWS S3 bucket %s", config.RemoteStateConfigS3.Bucket) } terragruntOptions.Logger.Debugf("Enabled bucket-wide Access Logging on AWS S3 bucket %s", bucket) @@ -1329,20 +1329,20 @@ func EnableAccessLoggingForS3BucketWide(s3Client *s3.S3, config *ExtendedRemoteS } func checkS3AccessLoggingConfiguration(s3Client *s3.S3, config *ExtendedRemoteStateConfigS3, terragruntOptions *options.TerragruntOptions) (bool, error) { - terragruntOptions.Logger.Debugf("Checking if Access Logging is enabled for AWS S3 bucket %s", config.remoteStateConfigS3.Bucket) + terragruntOptions.Logger.Debugf("Checking if Access Logging is enabled for AWS S3 bucket %s", config.RemoteStateConfigS3.Bucket) - input := &s3.GetBucketLoggingInput{Bucket: aws.String(config.remoteStateConfigS3.Bucket)} + input := &s3.GetBucketLoggingInput{Bucket: aws.String(config.RemoteStateConfigS3.Bucket)} output, err := s3Client.GetBucketLogging(input) if err != nil { - terragruntOptions.Logger.Debugf("Error checking if Access Logging is enabled for AWS S3 bucket %s: %s", config.remoteStateConfigS3.Bucket, err.Error()) - return false, errors.WithStackTraceAndPrefix(err, "Error checking if Access Logging is enabled for AWS S3 bucket %s", config.remoteStateConfigS3.Bucket) + terragruntOptions.Logger.Debugf("Error checking if Access Logging is enabled for AWS S3 bucket %s: %s", config.RemoteStateConfigS3.Bucket, err.Error()) + return false, errors.WithStackTraceAndPrefix(err, "Error checking if Access Logging is enabled for AWS S3 bucket %s", config.RemoteStateConfigS3.Bucket) } if output.LoggingEnabled == nil { return false, nil } - loggingInput := config.createS3LoggingInput() + loggingInput := config.CreateS3LoggingInput() if !reflect.DeepEqual(output.LoggingEnabled, loggingInput.BucketLoggingStatus.LoggingEnabled) { return false, nil @@ -1395,10 +1395,10 @@ func checkIfS3PublicAccessBlockingEnabled(s3Client *s3.S3, config *RemoteStateCo return false, errors.WithStackTraceAndPrefix(err, "Error checking if S3 bucket %s is configured to block public access", config.Bucket) } - return validatePublicAccessBlock(output) + return ValidatePublicAccessBlock(output) } -func validatePublicAccessBlock(output *s3.GetPublicAccessBlockOutput) (bool, error) { +func ValidatePublicAccessBlock(output *s3.GetPublicAccessBlockOutput) (bool, error) { if output.PublicAccessBlockConfiguration == nil { return false, nil } @@ -1504,7 +1504,7 @@ func checkBucketAccess(s3Client *s3.S3, bucket *string, key *string) error { // Create a table for locks in DynamoDB if the user has configured a lock table and the table doesn't already exist func createLockTableIfNecessary(extendedS3Config *ExtendedRemoteStateConfigS3, tags map[string]string, terragruntOptions *options.TerragruntOptions) error { - if extendedS3Config.remoteStateConfigS3.GetLockTableName() == "" { + if extendedS3Config.RemoteStateConfigS3.GetLockTableName() == "" { return nil } @@ -1513,7 +1513,7 @@ func createLockTableIfNecessary(extendedS3Config *ExtendedRemoteStateConfigS3, t return err } - return dynamodb.CreateLockTableIfNecessary(extendedS3Config.remoteStateConfigS3.GetLockTableName(), tags, dynamodbClient, terragruntOptions) + return dynamodb.CreateLockTableIfNecessary(extendedS3Config.RemoteStateConfigS3.GetLockTableName(), tags, dynamodbClient, terragruntOptions) } // Update a table for locks in DynamoDB if the user has configured a lock table and the table's server-side encryption isn't turned on diff --git a/remote/remote_state_s3_test.go b/remote/remote_state_s3_test.go index c00992dd8..b596a62cd 100644 --- a/remote/remote_state_s3_test.go +++ b/remote/remote_state_s3_test.go @@ -1,4 +1,4 @@ -package remote +package remote_test import ( "bytes" @@ -11,6 +11,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/gruntwork-io/terragrunt/aws_helper" "github.com/gruntwork-io/terragrunt/options" + "github.com/gruntwork-io/terragrunt/remote" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -35,7 +36,7 @@ func TestCreateS3LoggingInput(t *testing.T) { BucketLoggingStatus: &s3.BucketLoggingStatus{ LoggingEnabled: &s3.LoggingEnabled{ TargetBucket: aws.String("logging-bucket"), - TargetPrefix: aws.String(DefaultS3BucketAccessLoggingTargetPrefix), + TargetPrefix: aws.String(remote.DefaultS3BucketAccessLoggingTargetPrefix), }, }, }, @@ -108,8 +109,8 @@ func TestCreateS3LoggingInput(t *testing.T) { t.Run(testCase.name, func(t *testing.T) { t.Parallel() - extendedS3Config, _ := ParseExtendedS3Config(testCase.config) - createdLoggingInput := extendedS3Config.createS3LoggingInput() + extendedS3Config, _ := remote.ParseExtendedS3Config(testCase.config) + createdLoggingInput := extendedS3Config.CreateS3LoggingInput() actual := reflect.DeepEqual(createdLoggingInput, testCase.loggingInput) if !assert.Equal(t, testCase.shouldBeEqual, actual) { t.Errorf("s3.PutBucketLoggingInput mismatch:\ncreated: %+v\nexpected: %+v", createdLoggingInput, testCase.loggingInput) @@ -124,16 +125,16 @@ func TestConfigValuesEqual(t *testing.T) { terragruntOptions, err := options.NewTerragruntOptionsForTest("remote_state_test") require.NoError(t, err, "Unexpected error creating NewTerragruntOptionsForTest: %v", err) - testCases := []struct { + tc := []struct { name string config map[string]interface{} - backend *TerraformBackend + backend *remote.TerraformBackend shouldBeEqual bool }{ { "equal-both-empty", map[string]interface{}{}, - &TerraformBackend{Type: "s3", Config: map[string]interface{}{}}, + &remote.TerraformBackend{Type: "s3", Config: map[string]interface{}{}}, true, }, { @@ -145,43 +146,43 @@ func TestConfigValuesEqual(t *testing.T) { { "equal-empty-and-nil-backend-config", map[string]interface{}{}, - &TerraformBackend{Type: "s3"}, + &remote.TerraformBackend{Type: "s3"}, true, }, { "equal-one-key", map[string]interface{}{"foo": "bar"}, - &TerraformBackend{Type: "s3", Config: map[string]interface{}{"foo": "bar"}}, + &remote.TerraformBackend{Type: "s3", Config: map[string]interface{}{"foo": "bar"}}, true, }, { "equal-multiple-keys", map[string]interface{}{"foo": "bar", "baz": []string{"a", "b", "c"}, "blah": 123, "bool": true}, - &TerraformBackend{Type: "s3", Config: map[string]interface{}{"foo": "bar", "baz": []string{"a", "b", "c"}, "blah": 123, "bool": true}}, + &remote.TerraformBackend{Type: "s3", Config: map[string]interface{}{"foo": "bar", "baz": []string{"a", "b", "c"}, "blah": 123, "bool": true}}, true, }, { "equal-encrypt-bool-handling", map[string]interface{}{"encrypt": true}, - &TerraformBackend{Type: "s3", Config: map[string]interface{}{"encrypt": "true"}}, + &remote.TerraformBackend{Type: "s3", Config: map[string]interface{}{"encrypt": "true"}}, true, }, { "equal-general-bool-handling", map[string]interface{}{"something": true, "encrypt": true}, - &TerraformBackend{Type: "s3", Config: map[string]interface{}{"something": "true", "encrypt": "true"}}, + &remote.TerraformBackend{Type: "s3", Config: map[string]interface{}{"something": "true", "encrypt": "true"}}, true, }, { "equal-ignore-s3-tags", map[string]interface{}{"foo": "bar", "s3_bucket_tags": []map[string]string{{"foo": "bar"}}}, - &TerraformBackend{Type: "s3", Config: map[string]interface{}{"foo": "bar"}}, + &remote.TerraformBackend{Type: "s3", Config: map[string]interface{}{"foo": "bar"}}, true, }, { "equal-ignore-dynamodb-tags", map[string]interface{}{"dynamodb_table_tags": []map[string]string{{"foo": "bar"}}}, - &TerraformBackend{Type: "s3", Config: map[string]interface{}{}}, + &remote.TerraformBackend{Type: "s3", Config: map[string]interface{}{}}, true, }, { @@ -195,19 +196,19 @@ func TestConfigValuesEqual(t *testing.T) { "skip_accesslogging_bucket_public_access_blocking": false, "skip_accesslogging_bucket_ssencryption": false, }, - &TerraformBackend{Type: "s3", Config: map[string]interface{}{}}, + &remote.TerraformBackend{Type: "s3", Config: map[string]interface{}{}}, true, }, { "unequal-wrong-backend", map[string]interface{}{"foo": "bar"}, - &TerraformBackend{Type: "wrong", Config: map[string]interface{}{"foo": "bar"}}, + &remote.TerraformBackend{Type: "wrong", Config: map[string]interface{}{"foo": "bar"}}, false, }, { "unequal-values", map[string]interface{}{"foo": "bar"}, - &TerraformBackend{Type: "s3", Config: map[string]interface{}{"foo": "different"}}, + &remote.TerraformBackend{Type: "s3", Config: map[string]interface{}{"foo": "different"}}, false, }, { @@ -219,25 +220,25 @@ func TestConfigValuesEqual(t *testing.T) { { "unequal-general-bool-handling", map[string]interface{}{"something": true}, - &TerraformBackend{Type: "s3", Config: map[string]interface{}{"something": "false"}}, + &remote.TerraformBackend{Type: "s3", Config: map[string]interface{}{"something": "false"}}, false, }, { "equal-null-ignored", map[string]interface{}{"something": "foo"}, - &TerraformBackend{Type: "s3", Config: map[string]interface{}{"something": "foo", "ignored-because-null": nil}}, + &remote.TerraformBackend{Type: "s3", Config: map[string]interface{}{"something": "foo", "ignored-because-null": nil}}, true, }, } - for _, testCase := range testCases { - // Save the testCase in local scope so all the t.Run calls don't end up with the last item in the list - testCase := testCase + for _, tt := range tc { + // Save the tt in local scope so all the t.Run calls don't end up with the last item in the list + tt := tt - t.Run(testCase.name, func(t *testing.T) { + t.Run(tt.name, func(t *testing.T) { t.Parallel() - actual := configValuesEqual(testCase.config, testCase.backend, terragruntOptions) - assert.Equal(t, testCase.shouldBeEqual, actual) + actual := remote.ConfigValuesEqual(tt.config, tt.backend, terragruntOptions) + assert.Equal(t, tt.shouldBeEqual, actual) }) } } @@ -278,10 +279,10 @@ func TestForcePathStyleClientSession(t *testing.T) { t.Run(testCase.name, func(t *testing.T) { t.Parallel() - s3ConfigExtended, err := ParseExtendedS3Config(testCase.config) + s3ConfigExtended, err := remote.ParseExtendedS3Config(testCase.config) require.NoError(t, err, "Unexpected error parsing config for test: %v", err) - s3Client, err := CreateS3Client(s3ConfigExtended.GetAwsSessionConfig(), terragruntOptions) + s3Client, err := remote.CreateS3Client(s3ConfigExtended.GetAwsSessionConfig(), terragruntOptions) require.NoError(t, err, "Unexpected error creating client for test: %v", err) actual := aws.BoolValue(s3Client.Config.S3ForcePathStyle) @@ -319,17 +320,17 @@ func TestGetAwsSessionConfig(t *testing.T) { t.Run(testCase.name, func(t *testing.T) { t.Parallel() - s3ConfigExtended, err := ParseExtendedS3Config(testCase.config) + s3ConfigExtended, err := remote.ParseExtendedS3Config(testCase.config) require.NoError(t, err, "Unexpected error parsing config for test: %v", err) expected := &aws_helper.AwsSessionConfig{ - Region: s3ConfigExtended.remoteStateConfigS3.Region, - CustomS3Endpoint: s3ConfigExtended.remoteStateConfigS3.Endpoint, - CustomDynamoDBEndpoint: s3ConfigExtended.remoteStateConfigS3.DynamoDBEndpoint, - Profile: s3ConfigExtended.remoteStateConfigS3.Profile, - RoleArn: s3ConfigExtended.remoteStateConfigS3.RoleArn, - CredsFilename: s3ConfigExtended.remoteStateConfigS3.CredsFilename, - S3ForcePathStyle: s3ConfigExtended.remoteStateConfigS3.S3ForcePathStyle, + Region: s3ConfigExtended.RemoteStateConfigS3.Region, + CustomS3Endpoint: s3ConfigExtended.RemoteStateConfigS3.Endpoint, + CustomDynamoDBEndpoint: s3ConfigExtended.RemoteStateConfigS3.DynamoDBEndpoint, + Profile: s3ConfigExtended.RemoteStateConfigS3.Profile, + RoleArn: s3ConfigExtended.RemoteStateConfigS3.RoleArn, + CredsFilename: s3ConfigExtended.RemoteStateConfigS3.CredsFilename, + S3ForcePathStyle: s3ConfigExtended.RemoteStateConfigS3.S3ForcePathStyle, DisableComputeChecksums: s3ConfigExtended.DisableAWSClientChecksums, } @@ -361,13 +362,13 @@ func TestGetAwsSessionConfigWithAssumeRole(t *testing.T) { t.Parallel() config := map[string]interface{}{"assume_role": testCase.config} - s3ConfigExtended, err := ParseExtendedS3Config(config) + s3ConfigExtended, err := remote.ParseExtendedS3Config(config) require.NoError(t, err, "Unexpected error parsing config for test: %v", err) expected := &aws_helper.AwsSessionConfig{ - RoleArn: s3ConfigExtended.remoteStateConfigS3.AssumeRole.RoleArn, - ExternalID: s3ConfigExtended.remoteStateConfigS3.AssumeRole.ExternalID, - SessionName: s3ConfigExtended.remoteStateConfigS3.AssumeRole.SessionName, + RoleArn: s3ConfigExtended.RemoteStateConfigS3.AssumeRole.RoleArn, + ExternalID: s3ConfigExtended.RemoteStateConfigS3.AssumeRole.ExternalID, + SessionName: s3ConfigExtended.RemoteStateConfigS3.AssumeRole.SessionName, } actual := s3ConfigExtended.GetAwsSessionConfig() @@ -379,7 +380,7 @@ func TestGetAwsSessionConfigWithAssumeRole(t *testing.T) { func TestGetTerraformInitArgs(t *testing.T) { t.Parallel() - initializer := S3Initializer{} + initializer := remote.S3Initializer{} testCases := []struct { name string @@ -566,7 +567,7 @@ func TestNegativePublicAccessResponse(t *testing.T) { t.Run(testCase.name, func(t *testing.T) { t.Parallel() - response, err := validatePublicAccessBlock(testCase.response) + response, err := remote.ValidatePublicAccessBlock(testCase.response) require.NoError(t, err) assert.False(t, response) }) @@ -577,44 +578,46 @@ func TestValidateS3Config(t *testing.T) { t.Parallel() testCases := []struct { name string - extendedConfig *ExtendedRemoteStateConfigS3 + extendedConfig *remote.ExtendedRemoteStateConfigS3 expectedErr error expectedOutput string }{ { name: "no-region", - extendedConfig: &ExtendedRemoteStateConfigS3{}, - expectedErr: MissingRequiredS3RemoteStateConfig("region"), + extendedConfig: &remote.ExtendedRemoteStateConfigS3{}, + expectedErr: remote.MissingRequiredS3RemoteStateConfig("region"), }, { name: "no-bucket", - extendedConfig: &ExtendedRemoteStateConfigS3{ - remoteStateConfigS3: RemoteStateConfigS3{ + extendedConfig: &remote.ExtendedRemoteStateConfigS3{ + RemoteStateConfigS3: remote.RemoteStateConfigS3{ Region: "us-west-2", }, }, - expectedErr: MissingRequiredS3RemoteStateConfig("bucket"), + expectedErr: remote.MissingRequiredS3RemoteStateConfig("bucket"), }, { name: "no-key", - extendedConfig: &ExtendedRemoteStateConfigS3{ - remoteStateConfigS3: RemoteStateConfigS3{ + extendedConfig: &remote.ExtendedRemoteStateConfigS3{ + RemoteStateConfigS3: remote.RemoteStateConfigS3{ Region: "us-west-2", Bucket: "state-bucket", }, }, - expectedErr: MissingRequiredS3RemoteStateConfig("key"), + expectedErr: remote.MissingRequiredS3RemoteStateConfig("key"), }, } for _, testCase := range testCases { testCase := testCase t.Run(testCase.name, func(t *testing.T) { + t.Parallel() + buf := &bytes.Buffer{} logger := logrus.New() logger.SetLevel(logrus.DebugLevel) logger.SetOutput(buf) - err := validateS3Config(testCase.extendedConfig) + err := remote.ValidateS3Config(testCase.extendedConfig) if err != nil { require.ErrorIs(t, err, testCase.expectedErr) } diff --git a/remote/remote_state_test.go b/remote/remote_state_test.go index 61795c94c..4510eefd0 100644 --- a/remote/remote_state_test.go +++ b/remote/remote_state_test.go @@ -1,10 +1,11 @@ -package remote +package remote_test import ( "strings" "testing" "github.com/gruntwork-io/terragrunt/options" + "github.com/gruntwork-io/terragrunt/remote" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -15,7 +16,7 @@ import ( func TestToTerraformInitArgs(t *testing.T) { t.Parallel() - remoteState := RemoteState{ + remoteState := remote.RemoteState{ Backend: "s3", Config: map[string]interface{}{ "encrypt": true, @@ -53,7 +54,7 @@ func TestToTerraformInitArgs(t *testing.T) { func TestToTerraformInitArgsForGCS(t *testing.T) { t.Parallel() - remoteState := RemoteState{ + remoteState := remote.RemoteState{ Backend: "gcs", Config: map[string]interface{}{ "project": "my-project-123456", @@ -81,7 +82,7 @@ func TestToTerraformInitArgsForGCS(t *testing.T) { func TestToTerraformInitArgsUnknownBackend(t *testing.T) { t.Parallel() - remoteState := RemoteState{ + remoteState := remote.RemoteState{ Backend: "s4", Config: map[string]interface{}{ "encrypt": true, @@ -98,7 +99,7 @@ func TestToTerraformInitArgsUnknownBackend(t *testing.T) { func TestToTerraformInitArgsInitDisabled(t *testing.T) { t.Parallel() - remoteState := RemoteState{ + remoteState := remote.RemoteState{ Backend: "s3", DisableInit: true, Config: map[string]interface{}{ @@ -115,7 +116,7 @@ func TestToTerraformInitArgsInitDisabled(t *testing.T) { func TestToTerraformInitArgsNoBackendConfigs(t *testing.T) { t.Parallel() - remoteStates := []RemoteState{ + remoteStates := []remote.RemoteState{ {Backend: "s3"}, {Backend: "gcs"}, } @@ -134,97 +135,97 @@ func TestDiffersFrom(t *testing.T) { testCases := []struct { name string - existingBackend TerraformBackend - stateFromConfig RemoteState + existingBackend remote.TerraformBackend + stateFromConfig remote.RemoteState shouldOverride bool }{ - {"both empty", TerraformBackend{}, RemoteState{}, false}, - {"same backend type value", TerraformBackend{Type: "s3"}, RemoteState{Backend: "s3"}, false}, - {"different backend type values", TerraformBackend{Type: "s3"}, RemoteState{Backend: "atlas"}, true}, + {"both empty", remote.TerraformBackend{}, remote.RemoteState{}, false}, + {"same backend type value", remote.TerraformBackend{Type: "s3"}, remote.RemoteState{Backend: "s3"}, false}, + {"different backend type values", remote.TerraformBackend{Type: "s3"}, remote.RemoteState{Backend: "atlas"}, true}, { "identical S3 configs", - TerraformBackend{ + remote.TerraformBackend{ Type: "s3", Config: map[string]interface{}{"bucket": "foo", "key": "bar", "region": "us-east-1"}, }, - RemoteState{ + remote.RemoteState{ Backend: "s3", Config: map[string]interface{}{"bucket": "foo", "key": "bar", "region": "us-east-1"}, }, false, }, { "identical GCS configs", - TerraformBackend{ + remote.TerraformBackend{ Type: "gcs", Config: map[string]interface{}{"project": "foo-123456", "location": "europe-west3", "bucket": "foo", "prefix": "bar"}, }, - RemoteState{ + remote.RemoteState{ Backend: "gcs", Config: map[string]interface{}{"project": "foo-123456", "location": "europe-west3", "bucket": "foo", "prefix": "bar"}, }, false, }, { "different s3 bucket values", - TerraformBackend{ + remote.TerraformBackend{ Type: "s3", Config: map[string]interface{}{"bucket": "foo", "key": "bar", "region": "us-east-1"}, }, - RemoteState{ + remote.RemoteState{ Backend: "s3", Config: map[string]interface{}{"bucket": "different", "key": "bar", "region": "us-east-1"}, }, true, }, { "different gcs bucket values", - TerraformBackend{ + remote.TerraformBackend{ Type: "gcs", Config: map[string]interface{}{"project": "foo-123456", "location": "europe-west3", "bucket": "foo", "prefix": "bar"}, }, - RemoteState{ + remote.RemoteState{ Backend: "gcs", Config: map[string]interface{}{"project": "foo-123456", "location": "europe-west3", "bucket": "different", "prefix": "bar"}, }, true, }, { "different s3 key values", - TerraformBackend{ + remote.TerraformBackend{ Type: "s3", Config: map[string]interface{}{"bucket": "foo", "key": "bar", "region": "us-east-1"}, }, - RemoteState{ + remote.RemoteState{ Backend: "s3", Config: map[string]interface{}{"bucket": "foo", "key": "different", "region": "us-east-1"}, }, true, }, { "different gcs prefix values", - TerraformBackend{ + remote.TerraformBackend{ Type: "gcs", Config: map[string]interface{}{"project": "foo-123456", "location": "europe-west3", "bucket": "foo", "prefix": "bar"}, }, - RemoteState{ + remote.RemoteState{ Backend: "gcs", Config: map[string]interface{}{"project": "foo-123456", "location": "europe-west3", "bucket": "foo", "prefix": "different"}, }, true, }, { "different s3 region values", - TerraformBackend{ + remote.TerraformBackend{ Type: "s3", Config: map[string]interface{}{"bucket": "foo", "key": "bar", "region": "us-east-1"}, }, - RemoteState{ + remote.RemoteState{ Backend: "s3", Config: map[string]interface{}{"bucket": "foo", "key": "bar", "region": "different"}, }, true, }, { "different gcs location values", - TerraformBackend{ + remote.TerraformBackend{ Type: "gcs", Config: map[string]interface{}{"project": "foo-123456", "location": "europe-west3", "bucket": "foo", "prefix": "bar"}, }, - RemoteState{ + remote.RemoteState{ Backend: "gcs", Config: map[string]interface{}{"project": "foo-123456", "location": "different", "bucket": "foo", "prefix": "bar"}, }, @@ -232,11 +233,11 @@ func TestDiffersFrom(t *testing.T) { }, { "different boolean values and boolean conversion", - TerraformBackend{ + remote.TerraformBackend{ Type: "s3", Config: map[string]interface{}{"something": "true"}, }, - RemoteState{ + remote.RemoteState{ Backend: "s3", Config: map[string]interface{}{"something": false}, }, @@ -244,11 +245,11 @@ func TestDiffersFrom(t *testing.T) { }, { "different gcs boolean values and boolean conversion", - TerraformBackend{ + remote.TerraformBackend{ Type: "gcs", Config: map[string]interface{}{"something": "true"}, }, - RemoteState{ + remote.RemoteState{ Backend: "gcs", Config: map[string]interface{}{"something": false}, }, @@ -256,11 +257,11 @@ func TestDiffersFrom(t *testing.T) { }, { "null values ignored", - TerraformBackend{ + remote.TerraformBackend{ Type: "s3", Config: map[string]interface{}{"something": "foo", "set-to-nil-should-be-ignored": nil}, }, - RemoteState{ + remote.RemoteState{ Backend: "s3", Config: map[string]interface{}{"something": "foo"}, }, @@ -268,11 +269,11 @@ func TestDiffersFrom(t *testing.T) { }, { "gcs null values ignored", - TerraformBackend{ + remote.TerraformBackend{ Type: "gcs", Config: map[string]interface{}{"something": "foo", "set-to-nil-should-be-ignored": nil}, }, - RemoteState{ + remote.RemoteState{ Backend: "gcs", Config: map[string]interface{}{"something": "foo"}, }, @@ -286,7 +287,7 @@ func TestDiffersFrom(t *testing.T) { t.Run(testCase.name, func(t *testing.T) { t.Parallel() - shouldOverride := testCase.stateFromConfig.differsFrom(&testCase.existingBackend, terragruntOptions) + shouldOverride := testCase.stateFromConfig.DiffersFrom(&testCase.existingBackend, terragruntOptions) assert.Equal(t, testCase.shouldOverride, shouldOverride, "Expect differsFrom to return %t but got %t for existingRemoteState %v and remoteStateFromTerragruntConfig %v", testCase.shouldOverride, shouldOverride, testCase.existingBackend, testCase.stateFromConfig) }) } diff --git a/remote/terraform_config.go b/remote/terraform_config.go index 81310fe8b..ee3d395a6 100644 --- a/remote/terraform_config.go +++ b/remote/terraform_config.go @@ -6,8 +6,8 @@ import ( "strings" ) -// wrapMapToSingleLineHcl - This is a workaround to convert a map[string]interface{} to a single line HCL string. -func wrapMapToSingleLineHcl(m map[string]interface{}) string { +// WrapMapToSingleLineHcl - This is a workaround to convert a map[string]interface{} to a single line HCL string. +func WrapMapToSingleLineHcl(m map[string]interface{}) string { var attributes = make([]string, 0, len(m)) for key, value := range m { attributes = append(attributes, fmt.Sprintf(`%s=%s`, key, formatHclValue(value))) @@ -23,7 +23,7 @@ func formatHclValue(value interface{}) string { escapedValue := strings.ReplaceAll(v, `"`, `\"`) return fmt.Sprintf(`"%s"`, escapedValue) case map[string]interface{}: - return wrapMapToSingleLineHcl(v) + return WrapMapToSingleLineHcl(v) default: return fmt.Sprintf(`%v`, v) } diff --git a/remote/terraform_config_test.go b/remote/terraform_config_test.go index 9f04547bf..b9b228112 100644 --- a/remote/terraform_config_test.go +++ b/remote/terraform_config_test.go @@ -1,9 +1,15 @@ -package remote +package remote_test -import "testing" +import ( + "testing" + + "github.com/gruntwork-io/terragrunt/remote" +) func TestWrapMapToSingleLineHcl(t *testing.T) { - tests := []struct { + t.Parallel() + + tc := []struct { name string input map[string]interface{} expected string @@ -20,9 +26,13 @@ func TestWrapMapToSingleLineHcl(t *testing.T) { }, } - for _, tt := range tests { + for _, tt := range tc { + tt := tt + t.Run(tt.name, func(t *testing.T) { - result := wrapMapToSingleLineHcl(tt.input) + t.Parallel() + + result := remote.WrapMapToSingleLineHcl(tt.input) if result != tt.expected { t.Errorf("Expected %s, but got %s", tt.expected, result) } diff --git a/remote/terraform_state_file.go b/remote/terraform_state_file.go index b5ca991a1..49ece2d12 100644 --- a/remote/terraform_state_file.go +++ b/remote/terraform_state_file.go @@ -77,7 +77,7 @@ func ParseTerraformStateFile(path string) (*TerraformState, error) { return nil, errors.WithStackTrace(CantParseTerraformStateFileError{Path: path, UnderlyingErr: err}) } - state, err := parseTerraformState(bytes) + state, err := ParseTerraformState(bytes) if err != nil { return nil, errors.WithStackTrace(CantParseTerraformStateFileError{Path: path, UnderlyingErr: err}) @@ -86,8 +86,8 @@ func ParseTerraformStateFile(path string) (*TerraformState, error) { return state, nil } -// parseTerraformState parses the Terraform state file data from the provided byte slice. -func parseTerraformState(terraformStateData []byte) (*TerraformState, error) { +// ParseTerraformState parses the Terraform state file data from the provided byte slice. +func ParseTerraformState(terraformStateData []byte) (*TerraformState, error) { terraformState := &TerraformState{} if len(terraformStateData) == 0 { diff --git a/remote/terraform_state_file_test.go b/remote/terraform_state_file_test.go index 2900acb55..f3fabf529 100644 --- a/remote/terraform_state_file_test.go +++ b/remote/terraform_state_file_test.go @@ -1,4 +1,4 @@ -package remote +package remote_test import ( "encoding/json" @@ -6,6 +6,7 @@ import ( "errors" + "github.com/gruntwork-io/terragrunt/remote" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -30,11 +31,11 @@ func TestParseTerraformStateLocal(t *testing.T) { } ` - expectedTerraformState := &TerraformState{ + expectedTerraformState := &remote.TerraformState{ Version: 1, Serial: 0, Backend: nil, - Modules: []TerraformStateModule{ + Modules: []remote.TerraformStateModule{ { Path: []string{"root"}, Outputs: map[string]interface{}{}, @@ -43,7 +44,7 @@ func TestParseTerraformStateLocal(t *testing.T) { }, } - actualTerraformState, err := parseTerraformState([]byte(stateFile)) + actualTerraformState, err := remote.ParseTerraformState([]byte(stateFile)) require.NoError(t, err) assert.Equal(t, expectedTerraformState, actualTerraformState) @@ -79,10 +80,10 @@ func TestParseTerraformStateRemote(t *testing.T) { } ` - expectedTerraformState := &TerraformState{ + expectedTerraformState := &remote.TerraformState{ Version: 5, Serial: 12, - Backend: &TerraformBackend{ + Backend: &remote.TerraformBackend{ Type: "s3", Config: map[string]interface{}{ "bucket": "bucket", @@ -91,7 +92,7 @@ func TestParseTerraformStateRemote(t *testing.T) { "region": "us-east-1", }, }, - Modules: []TerraformStateModule{ + Modules: []remote.TerraformStateModule{ { Path: []string{"root"}, Outputs: map[string]interface{}{}, @@ -100,7 +101,7 @@ func TestParseTerraformStateRemote(t *testing.T) { }, } - actualTerraformState, err := parseTerraformState([]byte(stateFile)) + actualTerraformState, err := remote.ParseTerraformState([]byte(stateFile)) require.NoError(t, err) assert.Equal(t, expectedTerraformState, actualTerraformState) @@ -209,10 +210,10 @@ func TestParseTerraformStateRemoteFull(t *testing.T) { ` - expectedTerraformState := &TerraformState{ + expectedTerraformState := &remote.TerraformState{ Version: 1, Serial: 51, - Backend: &TerraformBackend{ + Backend: &remote.TerraformBackend{ Type: "s3", Config: map[string]interface{}{ "bucket": "bucket", @@ -221,7 +222,7 @@ func TestParseTerraformStateRemoteFull(t *testing.T) { "region": "us-east-1", }, }, - Modules: []TerraformStateModule{ + Modules: []remote.TerraformStateModule{ { Path: []string{"root"}, Outputs: map[string]interface{}{ @@ -287,7 +288,7 @@ func TestParseTerraformStateRemoteFull(t *testing.T) { }, } - actualTerraformState, err := parseTerraformState([]byte(stateFile)) + actualTerraformState, err := remote.ParseTerraformState([]byte(stateFile)) require.NoError(t, err) assert.Equal(t, expectedTerraformState, actualTerraformState) @@ -299,9 +300,9 @@ func TestParseTerraformStateEmpty(t *testing.T) { stateFile := `{}` - expectedTerraformState := &TerraformState{} + expectedTerraformState := &remote.TerraformState{} - actualTerraformState, err := parseTerraformState([]byte(stateFile)) + actualTerraformState, err := remote.ParseTerraformState([]byte(stateFile)) require.NoError(t, err) assert.Equal(t, expectedTerraformState, actualTerraformState) @@ -313,7 +314,7 @@ func TestParseTerraformStateInvalid(t *testing.T) { stateFile := `not-valid-json` - actualTerraformState, err := parseTerraformState([]byte(stateFile)) + actualTerraformState, err := remote.ParseTerraformState([]byte(stateFile)) assert.Nil(t, actualTerraformState) require.Error(t, err) diff --git a/shell/error_explainer_test.go b/shell/error_explainer_test.go index 7c49108a1..ce48f7f08 100644 --- a/shell/error_explainer_test.go +++ b/shell/error_explainer_test.go @@ -1,9 +1,10 @@ -package shell +package shell_test import ( "errors" "testing" + "github.com/gruntwork-io/terragrunt/shell" "github.com/gruntwork-io/terragrunt/util" "github.com/hashicorp/go-multierror" @@ -40,14 +41,17 @@ func TestExplainError(t *testing.T) { } for _, tt := range testCases { + tt := tt t.Run(tt.errorOutput, func(t *testing.T) { + t.Parallel() + err := multierror.Append(&multierror.Error{}, util.ProcessExecutionError{ Err: errors.New(""), StdOut: "", Stderr: tt.errorOutput, }) - explanation := ExplainError(err) + explanation := shell.ExplainError(err) assert.Contains(t, explanation, tt.explanation) }) diff --git a/shell/run_shell_cmd.go b/shell/run_shell_cmd.go index 1eb4362b6..c02bc5e23 100644 --- a/shell/run_shell_cmd.go +++ b/shell/run_shell_cmd.go @@ -356,11 +356,11 @@ func GitLastReleaseTag(ctx context.Context, opts *options.TerragruntOptions, git if len(tags) == 0 { return "", nil } - return lastReleaseTag(tags), nil + return LastReleaseTag(tags), nil } -// lastReleaseTag - return last release tag from passed tags slice. -func lastReleaseTag(tags []string) string { +// LastReleaseTag - return last release tag from passed tags slice. +func LastReleaseTag(tags []string) string { semverTags := extractSemVerTags(tags) if len(semverTags) == 0 { return "" diff --git a/shell/run_shell_cmd_output_test.go b/shell/run_shell_cmd_output_test.go index d522a6478..b97d861f4 100644 --- a/shell/run_shell_cmd_output_test.go +++ b/shell/run_shell_cmd_output_test.go @@ -1,7 +1,7 @@ //go:build linux || darwin // +build linux darwin -package shell +package shell_test import ( "bytes" @@ -10,6 +10,7 @@ import ( "sync" "testing" + "github.com/gruntwork-io/terragrunt/shell" "github.com/gruntwork-io/terragrunt/util" "github.com/stretchr/testify/assert" @@ -50,6 +51,8 @@ func testCommandOutputOrder(t *testing.T, withPtty bool, fullOutput []string, st } func TestCommandOutputPrefix(t *testing.T) { + t.Parallel() + prefix := "PREFIX> " prefixedOutput := []string{} for _, line := range FULL_OUTPUT { @@ -79,7 +82,7 @@ func testCommandOutput(t *testing.T, withOptions func(*options.TerragruntOptions withOptions(terragruntOptions) - out, err := RunShellCommandWithOutput(context.Background(), terragruntOptions, "", !allocateStdout, false, "../testdata/test_outputs.sh", "same") + out, err := shell.RunShellCommandWithOutput(context.Background(), terragruntOptions, "", !allocateStdout, false, "../testdata/test_outputs.sh", "same") assert.NotNil(t, out, "Should get output") require.NoError(t, err, "Should have no error") diff --git a/shell/run_shell_cmd_test.go b/shell/run_shell_cmd_test.go index d1ace0266..a0468ae7d 100644 --- a/shell/run_shell_cmd_test.go +++ b/shell/run_shell_cmd_test.go @@ -1,4 +1,4 @@ -package shell +package shell_test import ( "bytes" @@ -7,6 +7,7 @@ import ( "testing" "github.com/gruntwork-io/terragrunt/internal/cache" + "github.com/gruntwork-io/terragrunt/shell" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -19,11 +20,11 @@ func TestRunShellCommand(t *testing.T) { terragruntOptions, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err, "Unexpected error creating NewTerragruntOptionsForTest: %v", err) - cmd := RunShellCommand(context.Background(), terragruntOptions, "terraform", "--version") + cmd := shell.RunShellCommand(context.Background(), terragruntOptions, "terraform", "--version") require.NoError(t, cmd) - cmd = RunShellCommand(context.Background(), terragruntOptions, "terraform", "not-a-real-command") - assert.Error(t, cmd) + cmd = shell.RunShellCommand(context.Background(), terragruntOptions, "terraform", "not-a-real-command") + require.Error(t, cmd) } func TestRunShellOutputToStderrAndStdout(t *testing.T) { @@ -38,7 +39,7 @@ func TestRunShellOutputToStderrAndStdout(t *testing.T) { terragruntOptions.Writer = stdout terragruntOptions.ErrWriter = stderr - cmd := RunShellCommand(context.Background(), terragruntOptions, "terraform", "--version") + cmd := shell.RunShellCommand(context.Background(), terragruntOptions, "terraform", "--version") require.NoError(t, cmd) assert.True(t, strings.Contains(stdout.String(), "Terraform"), "Output directed to stdout") @@ -51,7 +52,7 @@ func TestRunShellOutputToStderrAndStdout(t *testing.T) { terragruntOptions.Writer = stderr terragruntOptions.ErrWriter = stderr - cmd = RunShellCommand(context.Background(), terragruntOptions, "terraform", "--version") + cmd = shell.RunShellCommand(context.Background(), terragruntOptions, "terraform", "--version") require.NoError(t, cmd) assert.True(t, strings.Contains(stderr.String(), "Terraform"), "Output directed to stderr") @@ -69,7 +70,7 @@ func TestLastReleaseTag(t *testing.T) { "refs/tags/v20.1.2", "refs/tags/v0.5.1", } - lastTag := lastReleaseTag(tags) + lastTag := shell.LastReleaseTag(tags) assert.NotEmpty(t, lastTag) assert.Equal(t, "v20.1.2", lastTag) } @@ -77,16 +78,16 @@ func TestLastReleaseTag(t *testing.T) { func TestGitLevelTopDirCaching(t *testing.T) { t.Parallel() ctx := context.Background() - ctx = ContextWithTerraformCommandHook(ctx, nil) - c := cache.ContextCache[string](ctx, RunCmdCacheContextKey) + ctx = shell.ContextWithTerraformCommandHook(ctx, nil) + c := cache.ContextCache[string](ctx, shell.RunCmdCacheContextKey) assert.NotNil(t, c) assert.Empty(t, len(c.Cache)) terragruntOptions, err := options.NewTerragruntOptionsForTest("") require.NoError(t, err) path := "." - path1, err := GitTopLevelDir(ctx, terragruntOptions, path) + path1, err := shell.GitTopLevelDir(ctx, terragruntOptions, path) require.NoError(t, err) - path2, err := GitTopLevelDir(ctx, terragruntOptions, path) + path2, err := shell.GitTopLevelDir(ctx, terragruntOptions, path) require.NoError(t, err) assert.Equal(t, path1, path2) assert.Len(t, c.Cache, 1) diff --git a/shell/run_shell_cmd_unix_test.go b/shell/run_shell_cmd_unix_test.go index 54194c8d5..a697067c7 100644 --- a/shell/run_shell_cmd_unix_test.go +++ b/shell/run_shell_cmd_unix_test.go @@ -1,7 +1,7 @@ //go:build linux || darwin // +build linux darwin -package shell +package shell_test import ( "context" @@ -14,6 +14,7 @@ import ( "testing" "time" + "github.com/gruntwork-io/terragrunt/shell" "github.com/gruntwork-io/terragrunt/util" "github.com/gruntwork-io/terragrunt/options" @@ -59,7 +60,7 @@ func TestNewSignalsForwarderWaitUnix(t *testing.T) { cmdChannel := make(chan error) runChannel := make(chan error) - signalChannel := NewSignalsForwarder(InterruptSignals, cmd, terragruntOptions.Logger, cmdChannel) + signalChannel := shell.NewSignalsForwarder(shell.InterruptSignals, cmd, terragruntOptions.Logger, cmdChannel) defer signalChannel.Close() go func() { @@ -93,7 +94,7 @@ func TestNewSignalsForwarderMultipleUnix(t *testing.T) { cmdChannel := make(chan error) runChannel := make(chan error) - signalChannel := NewSignalsForwarder(InterruptSignals, cmd, terragruntOptions.Logger, cmdChannel) + signalChannel := shell.NewSignalsForwarder(shell.InterruptSignals, cmd, terragruntOptions.Logger, cmdChannel) defer signalChannel.Close() go func() { @@ -136,7 +137,7 @@ func TestRunShellCommandWithOutputInterrupt(t *testing.T) { expectedWait := 5 go func() { - _, err := RunShellCommandWithOutput(context.Background(), terragruntOptions, "", false, false, "../testdata/test_sigint_wait.sh", strconv.Itoa(expectedWait)) + _, err := shell.RunShellCommandWithOutput(context.Background(), terragruntOptions, "", false, false, "../testdata/test_sigint_wait.sh", strconv.Itoa(expectedWait)) errCh <- err }() diff --git a/telemetry/metrics.go b/telemetry/metrics.go index 318d59b94..a63bf0d36 100644 --- a/telemetry/metrics.go +++ b/telemetry/metrics.go @@ -43,7 +43,7 @@ func Time(ctx context.Context, name string, attrs map[string]interface{}, fn fun } metricAttrs := mapToAttributes(attrs) - histogram, err := meter.Int64Histogram(cleanMetricName(name + "_duration")) + histogram, err := meter.Int64Histogram(CleanMetricName(name + "_duration")) if err != nil { return errors.WithStack(err) } @@ -65,7 +65,7 @@ func Count(ctx context.Context, name string, value int64) { if ctx == nil || metricExporter == nil { return } - counter, err := meter.Int64Counter(cleanMetricName(name + "_count")) + counter, err := meter.Int64Counter(CleanMetricName(name + "_count")) if err != nil { return } @@ -74,7 +74,7 @@ func Count(ctx context.Context, name string, value int64) { // configureMetricsCollection - configure the metrics collection func configureMetricsCollection(ctx context.Context, opts *TelemetryOptions) error { - exporter, err := newMetricsExporter(ctx, opts) + exporter, err := NewMetricsExporter(ctx, opts) if err != nil { return errors.WithStack(err) } @@ -93,8 +93,8 @@ func configureMetricsCollection(ctx context.Context, opts *TelemetryOptions) err return nil } -// newMetricsExporter - create a new exporter based on the telemetry options. -func newMetricsExporter(ctx context.Context, opts *TelemetryOptions) (metric.Exporter, error) { +// NewMetricsExporter - create a new exporter based on the telemetry options. +func NewMetricsExporter(ctx context.Context, opts *TelemetryOptions) (metric.Exporter, error) { exporterType := metricsExporterType(env.GetString(opts.Vars["TERRAGRUNT_TELEMETRY_METRIC_EXPORTER"], string(noneMetricsExporterType))) insecure := env.GetBool(opts.GetValue("TERRAGRUNT_TELEMETRY_METRIC_EXPORTER_INSECURE_ENDPOINT", "TERRAGRUNT_TELEMERTY_METRIC_EXPORTER_INSECURE_ENDPOINT"), false) @@ -142,8 +142,8 @@ func newMetricsProvider(opts *TelemetryOptions, exp metric.Exporter) (*metric.Me return meterProvider, nil } -// cleanMetricName - clean metric name from invalid characters. -func cleanMetricName(metricName string) string { +// CleanMetricName - clean metric name from invalid characters. +func CleanMetricName(metricName string) string { cleanedName := metricNameCleanPattern.ReplaceAllString(metricName, "_") cleanedName = multipleUnderscoresPattern.ReplaceAllString(cleanedName, "_") return strings.Trim(cleanedName, "_") diff --git a/telemetry/metrics_test.go b/telemetry/metrics_test.go index f033aa78d..e7ad8d502 100644 --- a/telemetry/metrics_test.go +++ b/telemetry/metrics_test.go @@ -1,4 +1,4 @@ -package telemetry +package telemetry_test import ( "context" @@ -8,6 +8,7 @@ import ( "go.opentelemetry.io/otel/exporters/stdout/stdoutmetric" + "github.com/gruntwork-io/terragrunt/telemetry" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc" @@ -15,6 +16,8 @@ import ( ) func TestNewMetricsExporter(t *testing.T) { + t.Parallel() + ctx := context.Background() stdout, err := stdoutmetric.New() @@ -57,7 +60,7 @@ func TestNewMetricsExporter(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() - opts := &TelemetryOptions{ + opts := &telemetry.TelemetryOptions{ Vars: map[string]string{ "TERRAGRUNT_TELEMETRY_METRIC_EXPORTER": tt.exporterType, "TERRAGRUNT_TELEMETRY_METRIC_EXPORTER_INSECURE_ENDPOINT": strconv.FormatBool(tt.insecure), @@ -65,7 +68,7 @@ func TestNewMetricsExporter(t *testing.T) { Writer: io.Discard, } - exporter, err := newMetricsExporter(ctx, opts) + exporter, err := telemetry.NewMetricsExporter(ctx, opts) require.NoError(t, err) if tt.expectNil { @@ -78,6 +81,8 @@ func TestNewMetricsExporter(t *testing.T) { } func TestCleanMetricName(t *testing.T) { + t.Parallel() + testCases := []struct { name string input string @@ -124,7 +129,7 @@ func TestCleanMetricName(t *testing.T) { tc := tc t.Run(tc.name, func(t *testing.T) { t.Parallel() - result := cleanMetricName(tc.input) + result := telemetry.CleanMetricName(tc.input) assert.Equal(t, tc.expected, result) }) } diff --git a/telemetry/traces.go b/telemetry/traces.go index c85fc18f2..b83d28414 100644 --- a/telemetry/traces.go +++ b/telemetry/traces.go @@ -51,7 +51,7 @@ func Trace(ctx context.Context, name string, attrs map[string]interface{}, fn fu // configureTraceCollection - configure the traces collection func configureTraceCollection(ctx context.Context, opts *TelemetryOptions) error { - exp, err := newTraceExporter(ctx, opts) + exp, err := NewTraceExporter(ctx, opts) if err != nil { return errors.WithStack(err) } @@ -122,8 +122,8 @@ func newTraceProvider(opts *TelemetryOptions, exp sdktrace.SpanExporter) (*sdktr ), nil } -// newTraceExporter - create a new exporter based on the telemetry options. -func newTraceExporter(ctx context.Context, opts *TelemetryOptions) (sdktrace.SpanExporter, error) { +// NewTraceExporter - create a new exporter based on the telemetry options. +func NewTraceExporter(ctx context.Context, opts *TelemetryOptions) (sdktrace.SpanExporter, error) { exporterType := traceExporterType(env.GetString(opts.Vars["TERRAGRUNT_TELEMETRY_TRACE_EXPORTER"], string(noneTraceExporterType))) insecure := env.GetBool(opts.GetValue("TERRAGRUNT_TELEMETRY_TRACE_EXPORTER_INSECURE_ENDPOINT", "TERRAGRUNT_TELEMERTY_TRACE_EXPORTER_INSECURE_ENDPOINT"), false) diff --git a/telemetry/traces_test.go b/telemetry/traces_test.go index 9b16fa0c1..2d0fcb8ec 100644 --- a/telemetry/traces_test.go +++ b/telemetry/traces_test.go @@ -1,10 +1,11 @@ -package telemetry +package telemetry_test import ( "context" "io" "testing" + "github.com/gruntwork-io/terragrunt/telemetry" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc" @@ -13,6 +14,8 @@ import ( ) func TestNewTraceExporter(t *testing.T) { + t.Parallel() + ctx := context.Background() http, err := otlptracehttp.New(ctx) @@ -26,13 +29,13 @@ func TestNewTraceExporter(t *testing.T) { tests := []struct { name string - telemetryOptions *TelemetryOptions + telemetryOptions *telemetry.TelemetryOptions expectedType interface{} expectError bool }{ { name: "HTTP Trace Exporter", - telemetryOptions: &TelemetryOptions{ + telemetryOptions: &telemetry.TelemetryOptions{ Vars: map[string]string{ "TERRAGRUNT_TELEMETRY_TRACE_EXPORTER": "otlpHttp", }, @@ -43,7 +46,7 @@ func TestNewTraceExporter(t *testing.T) { }, { name: "Custom HTTP endpoint", - telemetryOptions: &TelemetryOptions{ + telemetryOptions: &telemetry.TelemetryOptions{ Vars: map[string]string{ "TERRAGRUNT_TELEMETRY_TRACE_EXPORTER": "http", "TERRAGRUNT_TELEMETRY_TRACE_EXPORTER_HTTP_ENDPOINT": "http://localhost:4317", @@ -55,7 +58,7 @@ func TestNewTraceExporter(t *testing.T) { }, { name: "Custom HTTP endpoint without endpoint", - telemetryOptions: &TelemetryOptions{ + telemetryOptions: &telemetry.TelemetryOptions{ Vars: map[string]string{ "TERRAGRUNT_TELEMETRY_TRACE_EXPORTER": "http", }, @@ -66,7 +69,7 @@ func TestNewTraceExporter(t *testing.T) { }, { name: "Grpc Trace Exporter", - telemetryOptions: &TelemetryOptions{ + telemetryOptions: &telemetry.TelemetryOptions{ Vars: map[string]string{ "TERRAGRUNT_TELEMETRY_TRACE_EXPORTER": "otlpGrpc", }, @@ -77,7 +80,7 @@ func TestNewTraceExporter(t *testing.T) { }, { name: "Console Trace Exporter", - telemetryOptions: &TelemetryOptions{ + telemetryOptions: &telemetry.TelemetryOptions{ Vars: map[string]string{ "TERRAGRUNT_TELEMETRY_TRACE_EXPORTER": "console", }, @@ -92,7 +95,7 @@ func TestNewTraceExporter(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() - exporter, err := newTraceExporter(ctx, tt.telemetryOptions) + exporter, err := telemetry.NewTraceExporter(ctx, tt.telemetryOptions) if tt.expectError { require.Error(t, err) diff --git a/terraform/cache/models/provider_test.go b/terraform/cache/models/provider_test.go index 3b994b4b2..8dc13ab3a 100644 --- a/terraform/cache/models/provider_test.go +++ b/terraform/cache/models/provider_test.go @@ -1,10 +1,11 @@ -package models +package models_test import ( "fmt" "net/url" "testing" + "github.com/gruntwork-io/terragrunt/terraform/cache/models" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -12,19 +13,19 @@ import ( func TestResolveRelativeReferences(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { baseURL string - body ResponseBody - expectedResolved ResponseBody + body models.ResponseBody + expectedResolved models.ResponseBody }{ { "https://releases.hashicorp.com/terraform-provider-local/2.5.1", - ResponseBody{ + models.ResponseBody{ DownloadURL: "terraform-provider-local_2.5.1_darwin_amd64.zip", SHA256SumsURL: "terraform-provider-local_2.5.1_SHA256SUMS", SHA256SumsSignatureURL: "terraform-provider-local_2.5.1_SHA256SUMS.72D7468F.sig", }, - ResponseBody{ + models.ResponseBody{ DownloadURL: "https://releases.hashicorp.com/terraform-provider-local/2.5.1/terraform-provider-local_2.5.1_darwin_amd64.zip", SHA256SumsURL: "https://releases.hashicorp.com/terraform-provider-local/2.5.1/terraform-provider-local_2.5.1_SHA256SUMS", SHA256SumsSignatureURL: "https://releases.hashicorp.com/terraform-provider-local/2.5.1/terraform-provider-local_2.5.1_SHA256SUMS.72D7468F.sig", @@ -32,12 +33,12 @@ func TestResolveRelativeReferences(t *testing.T) { }, { "https://somehost.com", - ResponseBody{ + models.ResponseBody{ DownloadURL: "https://releases.hashicorp.com/terraform-provider-local/2.5.1/terraform-provider-local_2.5.1_darwin_amd64.zip", SHA256SumsURL: "https://releases.hashicorp.com/terraform-provider-local/2.5.1/terraform-provider-local_2.5.1_SHA256SUMS", SHA256SumsSignatureURL: "https://releases.hashicorp.com/terraform-provider-local/2.5.1/terraform-provider-local_2.5.1_SHA256SUMS.72D7468F.sig", }, - ResponseBody{ + models.ResponseBody{ DownloadURL: "https://releases.hashicorp.com/terraform-provider-local/2.5.1/terraform-provider-local_2.5.1_darwin_amd64.zip", SHA256SumsURL: "https://releases.hashicorp.com/terraform-provider-local/2.5.1/terraform-provider-local_2.5.1_SHA256SUMS", SHA256SumsSignatureURL: "https://releases.hashicorp.com/terraform-provider-local/2.5.1/terraform-provider-local_2.5.1_SHA256SUMS.72D7468F.sig", @@ -45,17 +46,17 @@ func TestResolveRelativeReferences(t *testing.T) { }, } - for i, testCase := range testCases { - testCase := testCase + for i, tt := range tc { + tt := tt t.Run(fmt.Sprintf("testCase-%d", i), func(t *testing.T) { t.Parallel() - baseURL, err := url.Parse(testCase.baseURL) + baseURL, err := url.Parse(tt.baseURL) require.NoError(t, err) - actualResolved := testCase.body.ResolveRelativeReferences(baseURL) - assert.Equal(t, testCase.expectedResolved, *actualResolved) + actualResolved := tt.body.ResolveRelativeReferences(baseURL) + assert.Equal(t, tt.expectedResolved, *actualResolved) }) } } diff --git a/terraform/cliconfig/config_test.go b/terraform/cliconfig/config_test.go index 9fd9c6b80..f0c12a078 100644 --- a/terraform/cliconfig/config_test.go +++ b/terraform/cliconfig/config_test.go @@ -1,4 +1,4 @@ -package cliconfig +package cliconfig_test import ( "fmt" @@ -6,6 +6,7 @@ import ( "path/filepath" "testing" + "github.com/gruntwork-io/terragrunt/terraform/cliconfig" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -22,21 +23,21 @@ func TestConfig(t *testing.T) { require.NoError(t, err) testCases := []struct { - providerInstallationMethods []ProviderInstallationMethod - hosts []ConfigHost - config Config + providerInstallationMethods []cliconfig.ProviderInstallationMethod + hosts []cliconfig.ConfigHost + config cliconfig.Config expectedHCL string }{ { - providerInstallationMethods: []ProviderInstallationMethod{ - NewProviderInstallationFilesystemMirror(tempCacheDir, include, exclude), - NewProviderInstallationNetworkMirror("https://network-mirror.io/providers/", include, exclude), - NewProviderInstallationDirect(include, exclude), + providerInstallationMethods: []cliconfig.ProviderInstallationMethod{ + cliconfig.NewProviderInstallationFilesystemMirror(tempCacheDir, include, exclude), + cliconfig.NewProviderInstallationNetworkMirror("https://network-mirror.io/providers/", include, exclude), + cliconfig.NewProviderInstallationDirect(include, exclude), }, - hosts: []ConfigHost{ + hosts: []cliconfig.ConfigHost{ {"registry.terraform.io", map[string]string{"providers.v1": "http://localhost:5758/v1/providers/registry.terraform.io/"}}, }, - config: Config{ + config: cliconfig.Config{ DisableCheckpoint: true, PluginCacheDir: "path/to/plugin/cache/dir1", }, @@ -70,7 +71,7 @@ provider_installation { `, }, { - config: Config{ + config: cliconfig.Config{ DisableCheckpoint: false, PluginCacheDir: tempCacheDir, }, diff --git a/terraform/getproviders/hash_test.go b/terraform/getproviders/hash_test.go index c4958af66..33a07674e 100644 --- a/terraform/getproviders/hash_test.go +++ b/terraform/getproviders/hash_test.go @@ -1,10 +1,11 @@ -package getproviders +package getproviders_test import ( "fmt" "os" "testing" + "github.com/gruntwork-io/terragrunt/terraform/getproviders" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -23,9 +24,9 @@ func createFakeZipArchive(t *testing.T, content []byte) string { func TestPackageHashLegacyZipSHA(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { path string - expectedHash Hash + expectedHash getproviders.Hash }{ { createFakeZipArchive(t, []byte("1234567890")), @@ -37,16 +38,16 @@ func TestPackageHashLegacyZipSHA(t *testing.T) { }, } - for i, testCase := range testCases { - testCase := testCase + for i, tt := range tc { + tt := tt t.Run(fmt.Sprintf("testCase-%d", i), func(t *testing.T) { t.Parallel() - hash, err := PackageHashLegacyZipSHA(testCase.path) + hash, err := getproviders.PackageHashLegacyZipSHA(tt.path) require.NoError(t, err) - assert.Equal(t, testCase.expectedHash, hash) + assert.Equal(t, tt.expectedHash, hash) }) } } diff --git a/terraform/getproviders/package_authentication.go b/terraform/getproviders/package_authentication.go index 4300632e0..77c692afe 100644 --- a/terraform/getproviders/package_authentication.go +++ b/terraform/getproviders/package_authentication.go @@ -21,10 +21,10 @@ import ( ) const ( - verifiedChecksum PackageAuthenticationResult = iota - officialProvider - partnerProvider - communityProvider + VERIFIED_CHECKSUM PackageAuthenticationResult = iota + OFFICIAL_PROVIDER + PARTNER_PROVIDER + COMMUNITY_PROVIDER ) // PackageAuthenticationResult is returned from a PackageAuthentication implementation which implements Stringer. @@ -49,17 +49,17 @@ func (result *PackageAuthenticationResult) String() string { // SignedByHashiCorp returns whether the package was authenticated as signed by HashiCorp. func (result PackageAuthenticationResult) SignedByHashiCorp() bool { - return result == officialProvider + return result == OFFICIAL_PROVIDER } // SignedByAnyParty returns whether the package was authenticated as signed by either HashiCorp or by a third-party. func (result PackageAuthenticationResult) SignedByAnyParty() bool { - return result == officialProvider || result == partnerProvider || result == communityProvider + return result == OFFICIAL_PROVIDER || result == PARTNER_PROVIDER || result == COMMUNITY_PROVIDER } // ThirdPartySigned returns whether the package was authenticated as signed by a party other than HashiCorp. func (result PackageAuthenticationResult) ThirdPartySigned() bool { - return result == partnerProvider || result == communityProvider + return result == PARTNER_PROVIDER || result == COMMUNITY_PROVIDER } // PackageAuthentication implementation is responsible for authenticating that a package is what its distributor intended to distribute and that it has not been tampered with. @@ -136,7 +136,7 @@ func (auth archiveHashAuthentication) Authenticate(path string) (*PackageAuthent return nil, errors.Errorf("archive has incorrect checksum %s (expected %s)", gotHash, wantHash) } - return NewPackageAuthenticationResult(verifiedChecksum), nil + return NewPackageAuthenticationResult(VERIFIED_CHECKSUM), nil } func (a archiveHashAuthentication) AcceptableHashes() []Hash { @@ -210,7 +210,7 @@ func (auth signatureAuthentication) Authenticate(location string) (*PackageAuthe } if err := auth.checkDetachedSignature(hashicorpKeyring, bytes.NewReader(auth.Document), bytes.NewReader(auth.Signature), nil); err == nil { - return NewPackageAuthenticationResult(officialProvider), nil + return NewPackageAuthenticationResult(OFFICIAL_PROVIDER), nil } // If the signing key has a trust signature, attempt to verify it with the HashiCorp partners public key. @@ -234,11 +234,11 @@ func (auth signatureAuthentication) Authenticate(location string) (*PackageAuthe return nil, errors.Errorf("error verifying trust signature: %s", err) } - return NewPackageAuthenticationResult(partnerProvider), nil + return NewPackageAuthenticationResult(PARTNER_PROVIDER), nil } // We have a valid signature, but it's not from the HashiCorp key, and it also isn't a trusted partner. This is a community provider. - return NewPackageAuthenticationResult(communityProvider), nil + return NewPackageAuthenticationResult(COMMUNITY_PROVIDER), nil } func (auth signatureAuthentication) checkDetachedSignature(keyring openpgp.KeyRing, signed, signature io.Reader, config *packet.Config) error { diff --git a/terraform/getproviders/package_authentication_test.go b/terraform/getproviders/package_authentication_test.go index 0930c1802..078ebfa3f 100644 --- a/terraform/getproviders/package_authentication_test.go +++ b/terraform/getproviders/package_authentication_test.go @@ -1,4 +1,4 @@ -package getproviders +package getproviders_test import ( "crypto/sha256" @@ -7,6 +7,7 @@ import ( "fmt" "testing" + "github.com/gruntwork-io/terragrunt/terraform/getproviders" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -15,7 +16,7 @@ func TestPackageAuthenticationResult(t *testing.T) { t.Parallel() testCases := []struct { - result *PackageAuthenticationResult + result *getproviders.PackageAuthenticationResult expected string }{ { @@ -23,19 +24,19 @@ func TestPackageAuthenticationResult(t *testing.T) { "unauthenticated", }, { - NewPackageAuthenticationResult(verifiedChecksum), + getproviders.NewPackageAuthenticationResult(getproviders.VERIFIED_CHECKSUM), "verified checksum", }, { - NewPackageAuthenticationResult(officialProvider), + getproviders.NewPackageAuthenticationResult(getproviders.OFFICIAL_PROVIDER), "signed by HashiCorp", }, { - NewPackageAuthenticationResult(partnerProvider), + getproviders.NewPackageAuthenticationResult(getproviders.PARTNER_PROVIDER), "signed by a HashiCorp partner", }, { - NewPackageAuthenticationResult(communityProvider), + getproviders.NewPackageAuthenticationResult(getproviders.COMMUNITY_PROVIDER), "self-signed", }, } @@ -57,7 +58,7 @@ func TestArchiveChecksumAuthentication(t *testing.T) { testCases := []struct { path string wantSHA256Sum [sha256.Size]byte - expectedResult *PackageAuthenticationResult + expectedResult *getproviders.PackageAuthenticationResult expectedErr error }{ { @@ -68,7 +69,7 @@ func TestArchiveChecksumAuthentication(t *testing.T) { 0x78, 0x1c, 0xb8, 0xc3, 0xb2, 0x59, 0x01, 0xdd, 0x5a, 0x79, 0x2a, 0xde, 0x97, 0x11, 0xf5, 0x01, }, - NewPackageAuthenticationResult(verifiedChecksum), + getproviders.NewPackageAuthenticationResult(getproviders.VERIFIED_CHECKSUM), nil, }, { @@ -108,7 +109,7 @@ func TestArchiveChecksumAuthentication(t *testing.T) { t.Run(fmt.Sprintf("testCase-%d", i), func(t *testing.T) { t.Parallel() - auth := NewArchiveChecksumAuthentication(testCase.wantSHA256Sum) + auth := getproviders.NewArchiveChecksumAuthentication(testCase.wantSHA256Sum) actualResult, actualErr := auth.Authenticate(testCase.path) if testCase.expectedErr != nil { require.EqualError(t, actualErr, testCase.expectedErr.Error()) @@ -186,7 +187,7 @@ func TestNewMatchingChecksumAuthentication(t *testing.T) { t.Run(fmt.Sprintf("testCase-%d", i), func(t *testing.T) { t.Parallel() - auth := NewMatchingChecksumAuthentication(testCase.document, testCase.filename, testCase.wantSHA256Sum) + auth := getproviders.NewMatchingChecksumAuthentication(testCase.document, testCase.filename, testCase.wantSHA256Sum) _, actualErr := auth.Authenticate(testCase.path) if testCase.expectedErr != nil { @@ -204,7 +205,7 @@ func TestSignatureAuthentication(t *testing.T) { testCases := []struct { shasums string - expectedHashes []Hash + expectedHashes []getproviders.Hash }{ { `7d7e888fdd28abfe00894f9055209b9eec785153641de98e6852aa071008d4ee terraform_0.14.0-alpha20200923_darwin_amd64.zip @@ -219,7 +220,7 @@ def1b73849bec0dc57a04405847921bf9206c75b52ae9de195476facb26bd85e terraform_0.14 48f1826ec31d6f104e46cc2022b41f30cd1019ef48eaec9697654ef9ec37a879 terraform_0.14.0-alpha20200923_solaris_amd64.zip 17e0b496022bc4e4137be15e96d2b051c8acd6e14cb48d9b13b262330464f6cc terraform_0.14.0-alpha20200923_windows_386.zip 2696c86228f491bc5425561c45904c9ce39b1c676b1e17734cb2ee6b578c4bcd terraform_0.14.0-alpha20200923_windows_amd64.zip`, - []Hash{ + []getproviders.Hash{ "zh:7d7e888fdd28abfe00894f9055209b9eec785153641de98e6852aa071008d4ee", "zh:f8b6cf9ade087c17826d49d89cef21261cdc22bd27065bbc5b27d7dbf7fbbf6c", "zh:a5ba9945606bb7bfb821ba303957eeb40dd9ee4e706ba8da1eaf7cbeb0356e63", @@ -242,8 +243,8 @@ def1b73849bec0dc57a04405847921bf9206c75b52ae9de195476facb26bd85e terraform_0.14 t.Run(fmt.Sprintf("testCase-%d", i), func(t *testing.T) { t.Parallel() - auth := NewSignatureAuthentication([]byte(testCase.shasums), nil, nil) - authWithHashes, ok := auth.(PackageAuthenticationHashes) + auth := getproviders.NewSignatureAuthentication([]byte(testCase.shasums), nil, nil) + authWithHashes, ok := auth.(getproviders.PackageAuthenticationHashes) require.True(t, ok) actualHash := authWithHashes.AcceptableHashes() @@ -260,15 +261,15 @@ func TestSignatureAuthenticate(t *testing.T) { document []byte signature string keys map[string]string - expectedResult *PackageAuthenticationResult + expectedResult *getproviders.PackageAuthenticationResult expectedErr error }{ { "testdata/my-package.zip", []byte(testProviderShaSums), testHashicorpSignatureGoodBase64, - map[string]string{HashicorpPublicKey: ""}, - NewPackageAuthenticationResult(officialProvider), + map[string]string{getproviders.HashicorpPublicKey: ""}, + getproviders.NewPackageAuthenticationResult(getproviders.OFFICIAL_PROVIDER), nil, }, { @@ -291,7 +292,7 @@ func TestSignatureAuthenticate(t *testing.T) { "testdata/my-package.zip", []byte("example shasums data"), testAuthorSignatureGoodBase64, - map[string]string{HashicorpPublicKey: ""}, + map[string]string{getproviders.HashicorpPublicKey: ""}, nil, errors.New("authentication signature from unknown issuer"), }, @@ -322,7 +323,7 @@ func TestSignatureAuthenticate(t *testing.T) { signature, err := base64.StdEncoding.DecodeString(testCase.signature) require.NoError(t, err) - auth := NewSignatureAuthentication(testCase.document, signature, testCase.keys) + auth := getproviders.NewSignatureAuthentication(testCase.document, signature, testCase.keys) actualResult, actualErr := auth.Authenticate(testCase.path) if testCase.expectedErr != nil { diff --git a/terraform/getter.go b/terraform/getter.go index 8ff6685db..b00ca92cb 100644 --- a/terraform/getter.go +++ b/terraform/getter.go @@ -134,22 +134,22 @@ func (tfrGetter *RegistryGetter) Get(dstPath string, srcURL *url.URL) error { } version := versionList[0] - moduleRegistryBasePath, err := getModuleRegistryURLBasePath(ctx, registryDomain) + moduleRegistryBasePath, err := GetModuleRegistryURLBasePath(ctx, registryDomain) if err != nil { return err } - moduleURL, err := buildRequestUrl(registryDomain, moduleRegistryBasePath, modulePath, version) + moduleURL, err := BuildRequestUrl(registryDomain, moduleRegistryBasePath, modulePath, version) if err != nil { return err } - terraformGet, err := getTerraformGetHeader(ctx, *moduleURL) + terraformGet, err := GetTerraformGetHeader(ctx, *moduleURL) if err != nil { return err } - downloadURL, err := getDownloadURLFromHeader(*moduleURL, terraformGet) + downloadURL, err := GetDownloadURLFromHeader(*moduleURL, terraformGet) if err != nil { return err } @@ -235,11 +235,11 @@ func (tfrGetter *RegistryGetter) getSubdir(_ context.Context, dstPath, sourceURL return util.CopyFolderContentsWithFilter(sourcePath, dstPath, manifestFname, func(path string) bool { return true }) } -// getModuleRegistryURLBasePath uses the service discovery protocol +// GetModuleRegistryURLBasePath uses the service discovery protocol // (https://www.terraform.io/docs/internals/remote-service-discovery.html) // to figure out where the modules are stored. This will return the base // path where the modules can be accessed -func getModuleRegistryURLBasePath(ctx context.Context, domain string) (string, error) { +func GetModuleRegistryURLBasePath(ctx context.Context, domain string) (string, error) { sdURL := url.URL{ Scheme: "https", Host: domain, @@ -258,9 +258,9 @@ func getModuleRegistryURLBasePath(ctx context.Context, domain string) (string, e return respJSON.ModulesPath, nil } -// getTerraformGetHeader makes an http GET call to the given registry URL and return the contents of location json +// GetTerraformGetHeader makes an http GET call to the given registry URL and return the contents of location json // body or the header X-Terraform-Get. This function will return an error if the response does not contain the header. -func getTerraformGetHeader(ctx context.Context, url url.URL) (string, error) { +func GetTerraformGetHeader(ctx context.Context, url url.URL) (string, error) { body, header, err := httpGETAndGetResponse(ctx, url) if err != nil { details := "error receiving HTTP data" @@ -291,9 +291,9 @@ func getTerraformGetHeader(ctx context.Context, url url.URL) (string, error) { return terraformGet, nil } -// getDownloadURLFromHeader checks if the content of the X-Terraform-GET header contains the base url +// GetDownloadURLFromHeader checks if the content of the X-Terraform-GET header contains the base url // and prepends it if not -func getDownloadURLFromHeader(moduleURL url.URL, terraformGet string) (string, error) { +func GetDownloadURLFromHeader(moduleURL url.URL, terraformGet string) (string, error) { // If url from X-Terrafrom-Get Header seems to be a relative url, // append scheme and host from url used for getting the download url // because third-party registry implementations may not "know" their own absolute URLs if @@ -344,8 +344,8 @@ func httpGETAndGetResponse(ctx context.Context, getURL url.URL) ([]byte, *http.H return bodyData, &resp.Header, errors.WithStackTrace(err) } -// buildRequestUrl - create url to download module using moduleRegistryBasePath -func buildRequestUrl(registryDomain string, moduleRegistryBasePath string, modulePath string, version string) (*url.URL, error) { +// BuildRequestUrl - create url to download module using moduleRegistryBasePath +func BuildRequestUrl(registryDomain string, moduleRegistryBasePath string, modulePath string, version string) (*url.URL, error) { moduleRegistryBasePath = strings.TrimSuffix(moduleRegistryBasePath, "/") modulePath = strings.TrimSuffix(modulePath, "/") modulePath = strings.TrimPrefix(modulePath, "/") diff --git a/terraform/getter_test.go b/terraform/getter_test.go index 72edd3d40..e9a64a159 100644 --- a/terraform/getter_test.go +++ b/terraform/getter_test.go @@ -1,4 +1,4 @@ -package terraform +package terraform_test import ( "context" @@ -7,6 +7,7 @@ import ( "path/filepath" "testing" + "github.com/gruntwork-io/terragrunt/terraform" "github.com/gruntwork-io/terratest/modules/files" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -15,7 +16,7 @@ import ( func TestGetModuleRegistryURLBasePath(t *testing.T) { t.Parallel() - basePath, err := getModuleRegistryURLBasePath(context.Background(), "registry.terraform.io") + basePath, err := terraform.GetModuleRegistryURLBasePath(context.Background(), "registry.terraform.io") require.NoError(t, err) assert.Equal(t, "/v1/modules/", basePath) } @@ -28,7 +29,7 @@ func TestGetTerraformHeader(t *testing.T) { Host: "registry.terraform.io", Path: "/v1/modules/terraform-aws-modules/vpc/aws/3.3.0/download", } - terraformGetHeader, err := getTerraformGetHeader(context.Background(), testModuleURL) + terraformGetHeader, err := terraform.GetTerraformGetHeader(context.Background(), testModuleURL) require.NoError(t, err) assert.Contains(t, terraformGetHeader, "github.com/terraform-aws-modules/terraform-aws-vpc") } @@ -36,7 +37,7 @@ func TestGetTerraformHeader(t *testing.T) { func TestGetDownloadURLFromHeader(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { name string moduleURL url.URL terraformGet string @@ -89,11 +90,15 @@ func TestGetDownloadURLFromHeader(t *testing.T) { }, } - for _, testCase := range testCases { - t.Run(testCase.name, func(t *testing.T) { - downloadURL, err := getDownloadURLFromHeader(testCase.moduleURL, testCase.terraformGet) + for _, tt := range tc { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + downloadURL, err := terraform.GetDownloadURLFromHeader(tt.moduleURL, tt.terraformGet) require.NoError(t, err) - assert.Equal(t, testCase.expectedResult, downloadURL) + assert.Equal(t, tt.expectedResult, downloadURL) }) } } @@ -112,7 +117,7 @@ func TestTFRGetterRootDir(t *testing.T) { moduleDestPath := filepath.Join(dstPath, "terraform-aws-vpc") assert.False(t, files.FileExists(filepath.Join(moduleDestPath, "main.tf"))) - tfrGetter := new(RegistryGetter) + tfrGetter := new(terraform.RegistryGetter) require.NoError(t, tfrGetter.Get(moduleDestPath, testModuleURL)) assert.True(t, files.FileExists(filepath.Join(moduleDestPath, "main.tf"))) } @@ -131,21 +136,21 @@ func TestTFRGetterSubModule(t *testing.T) { moduleDestPath := filepath.Join(dstPath, "terraform-aws-vpc") assert.False(t, files.FileExists(filepath.Join(moduleDestPath, "main.tf"))) - tfrGetter := new(RegistryGetter) + tfrGetter := new(terraform.RegistryGetter) require.NoError(t, tfrGetter.Get(moduleDestPath, testModuleURL)) assert.True(t, files.FileExists(filepath.Join(moduleDestPath, "main.tf"))) } func TestBuildRequestUrlFullPath(t *testing.T) { t.Parallel() - requestUrl, err := buildRequestUrl("gruntwork.io", "https://gruntwork.io/registry/modules/v1/", "/tfr-project/terraform-aws-tfr", "6.6.6") + requestUrl, err := terraform.BuildRequestUrl("gruntwork.io", "https://gruntwork.io/registry/modules/v1/", "/tfr-project/terraform-aws-tfr", "6.6.6") require.NoError(t, err) assert.Equal(t, "https://gruntwork.io/registry/modules/v1/tfr-project/terraform-aws-tfr/6.6.6/download", requestUrl.String()) } func TestBuildRequestUrlRelativePath(t *testing.T) { t.Parallel() - requestUrl, err := buildRequestUrl("gruntwork.io", "/registry/modules/v1", "/tfr-project/terraform-aws-tfr", "6.6.6") + requestUrl, err := terraform.BuildRequestUrl("gruntwork.io", "/registry/modules/v1", "/tfr-project/terraform-aws-tfr", "6.6.6") require.NoError(t, err) assert.Equal(t, "https://gruntwork.io/registry/modules/v1/tfr-project/terraform-aws-tfr/6.6.6/download", requestUrl.String()) diff --git a/terraform/source_test.go b/terraform/source_test.go index 70caa0152..270a6e80d 100644 --- a/terraform/source_test.go +++ b/terraform/source_test.go @@ -1,4 +1,4 @@ -package terraform +package terraform_test import ( "fmt" @@ -10,6 +10,7 @@ import ( "github.com/stretchr/testify/require" "github.com/gruntwork-io/terragrunt/options" + "github.com/gruntwork-io/terragrunt/terraform" ) func TestSplitSourceUrl(t *testing.T) { @@ -52,7 +53,7 @@ func TestSplitSourceUrl(t *testing.T) { terragruntOptions, err := options.NewTerragruntOptionsForTest("testing") require.NoError(t, err) - actualRootRepo, actualModulePath, err := SplitSourceUrl(sourceUrl, terragruntOptions.Logger) + actualRootRepo, actualModulePath, err := terraform.SplitSourceUrl(sourceUrl, terragruntOptions.Logger) require.NoError(t, err) assert.Equal(t, testCase.expectedSo, actualRootRepo.String()) @@ -88,7 +89,7 @@ func TestToSourceUrl(t *testing.T) { t.Run(fmt.Sprintf("testCase-%d", i), func(t *testing.T) { t.Parallel() - actualSourceURL, err := ToSourceUrl(testCase.sourceURL, os.TempDir()) + actualSourceURL, err := terraform.ToSourceUrl(testCase.sourceURL, os.TempDir()) require.NoError(t, err) assert.Equal(t, testCase.expectedSourceURL, actualSourceURL.String()) }) @@ -102,11 +103,11 @@ func TestRegressionSupportForGitRemoteCodecommit(t *testing.T) { require.NoError(t, err) source := "git::codecommit::ap-northeast-1://my_app_modules//my-app/modules/main-module" - sourceURL, err := ToSourceUrl(source, ".") + sourceURL, err := terraform.ToSourceUrl(source, ".") require.NoError(t, err) require.Equal(t, "git::codecommit::ap-northeast-1", sourceURL.Scheme) - actualRootRepo, actualModulePath, err := SplitSourceUrl(sourceURL, terragruntOptions.Logger) + actualRootRepo, actualModulePath, err := terraform.SplitSourceUrl(sourceURL, terragruntOptions.Logger) require.NoError(t, err) require.Equal(t, "git::codecommit::ap-northeast-1://my_app_modules", actualRootRepo.String()) diff --git a/test/cliconfig.go b/test/cliconfig.go index 48129ad2a..9ac2d29ed 100644 --- a/test/cliconfig.go +++ b/test/cliconfig.go @@ -1,5 +1,5 @@ // common integration test functions -package test +package integration_test import ( "html/template" diff --git a/test/integration_catalog_test.go b/test/integration_catalog_test.go index 104449d85..371f14dd8 100644 --- a/test/integration_catalog_test.go +++ b/test/integration_catalog_test.go @@ -1,4 +1,4 @@ -package test +package integration_test import ( "context" diff --git a/test/integration_common_test.go b/test/integration_common_test.go index c77fc5bf3..bab722b28 100644 --- a/test/integration_common_test.go +++ b/test/integration_common_test.go @@ -1,5 +1,5 @@ // common integration test functions -package test +package integration_test import ( "archive/zip" diff --git a/test/integration_debug_test.go b/test/integration_debug_test.go index 9db1e80dc..c36df6db6 100644 --- a/test/integration_debug_test.go +++ b/test/integration_debug_test.go @@ -1,4 +1,4 @@ -package test +package integration_test import ( "bytes" diff --git a/test/integration_download_test.go b/test/integration_download_test.go index e4bc2aaae..a3dbb5a4c 100644 --- a/test/integration_download_test.go +++ b/test/integration_download_test.go @@ -1,4 +1,4 @@ -package test +package integration_test import ( "bytes" diff --git a/test/integration_engine_test.go b/test/integration_engine_test.go index 12b962389..7fe0d85f5 100644 --- a/test/integration_engine_test.go +++ b/test/integration_engine_test.go @@ -1,6 +1,6 @@ //go:build engine -package test +package integration_test import ( "fmt" diff --git a/test/integration_include_test.go b/test/integration_include_test.go index 3459efe4f..5ebd12b95 100644 --- a/test/integration_include_test.go +++ b/test/integration_include_test.go @@ -1,4 +1,4 @@ -package test +package integration_test import ( "bytes" @@ -33,19 +33,21 @@ func TestTerragruntWorksWithIncludeLocals(t *testing.T) { files, err := os.ReadDir(includeExposeFixturePath) require.NoError(t, err) - testCases := []string{} + tc := []string{} for _, finfo := range files { if finfo.IsDir() { - testCases = append(testCases, finfo.Name()) + tc = append(tc, finfo.Name()) } } - for _, testCase := range testCases { + for _, tt := range tc { // Capture range variable to avoid it changing across parallel test runs - testCase := testCase + tt := tt - t.Run(filepath.Base(testCase), func(t *testing.T) { - childPath := filepath.Join(includeExposeFixturePath, testCase, includeChildFixturePath) + t.Run(filepath.Base(tt), func(t *testing.T) { + t.Parallel() + + childPath := filepath.Join(includeExposeFixturePath, tt, includeChildFixturePath) cleanupTerraformFolder(t, childPath) runTerragrunt(t, "terragrunt run-all apply -auto-approve --terragrunt-include-external-dependencies --terragrunt-non-interactive --terragrunt-log-level debug --terragrunt-working-dir "+childPath) diff --git a/test/integration_local_dev_test.go b/test/integration_local_dev_test.go index d5a4616fa..58598420e 100644 --- a/test/integration_local_dev_test.go +++ b/test/integration_local_dev_test.go @@ -1,4 +1,4 @@ -package test +package integration_test import ( "bytes" diff --git a/test/integration_registry_test.go b/test/integration_registry_test.go index d6bcdba62..012432f1e 100644 --- a/test/integration_registry_test.go +++ b/test/integration_registry_test.go @@ -1,4 +1,4 @@ -package test +package integration_test import ( "bytes" diff --git a/test/integration_s3_encryption_test.go b/test/integration_s3_encryption_test.go index 9e23499f0..cf51363f2 100644 --- a/test/integration_s3_encryption_test.go +++ b/test/integration_s3_encryption_test.go @@ -1,4 +1,4 @@ -package test +package integration_test import ( "fmt" diff --git a/test/integration_scaffold_test.go b/test/integration_scaffold_test.go index f4173a711..33772afd8 100644 --- a/test/integration_scaffold_test.go +++ b/test/integration_scaffold_test.go @@ -1,4 +1,4 @@ -package test +package integration_test import ( "fmt" diff --git a/test/integration_serial_test.go b/test/integration_serial_test.go index e534e3487..56812fabb 100644 --- a/test/integration_serial_test.go +++ b/test/integration_serial_test.go @@ -1,4 +1,5 @@ -package test +//nolint:paralleltest +package integration_test import ( "bytes" diff --git a/test/integration_test.go b/test/integration_test.go index 5f82cda48..efc147d1d 100644 --- a/test/integration_test.go +++ b/test/integration_test.go @@ -1,4 +1,4 @@ -package test +package integration_test import ( "bytes" @@ -222,7 +222,7 @@ func TestTerragruntExcludesFile(t *testing.T) { tmpEnvPath := copyEnvironment(t, TEST_FIXTURE_EXCLUDES_FILE, ".terragrunt-excludes") rootPath := util.JoinPath(tmpEnvPath, TEST_FIXTURE_EXCLUDES_FILE) - testCases := []struct { + tc := []struct { flags string expectedOutput []string }{ @@ -236,19 +236,21 @@ func TestTerragruntExcludesFile(t *testing.T) { }, } - for i, testCase := range testCases { - testCase := testCase + for i, tt := range tc { + tt := tt + + t.Run(fmt.Sprintf("tt-%d", i), func(t *testing.T) { + t.Parallel() - t.Run(fmt.Sprintf("testCase-%d", i), func(t *testing.T) { cleanupTerraformFolder(t, TEST_FIXTURE_EXCLUDES_FILE) - runTerragrunt(t, fmt.Sprintf("terragrunt run-all apply -auto-approve --terragrunt-non-interactive --terragrunt-working-dir %s %s", rootPath, testCase.flags)) + runTerragrunt(t, fmt.Sprintf("terragrunt run-all apply -auto-approve --terragrunt-non-interactive --terragrunt-working-dir %s %s", rootPath, tt.flags)) - stdout, _, err := runTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt run-all output --terragrunt-non-interactive --terragrunt-working-dir %s %s", rootPath, testCase.flags)) + stdout, _, err := runTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt run-all output --terragrunt-non-interactive --terragrunt-working-dir %s %s", rootPath, tt.flags)) require.NoError(t, err) actualOutput := strings.Split(strings.TrimSpace(stdout), "\n") - assert.ElementsMatch(t, testCase.expectedOutput, actualOutput) + assert.ElementsMatch(t, tt.expectedOutput, actualOutput) }) } } @@ -361,6 +363,8 @@ func TestHclvalidateDiagnostic(t *testing.T) { } func TestHclvalidateInvalidConfigPath(t *testing.T) { + t.Parallel() + cleanupTerraformFolder(t, TEST_FIXTURE_HCLVALIDATE) tmpEnvPath := copyEnvironment(t, TEST_FIXTURE_HCLVALIDATE) rootPath := util.JoinPath(tmpEnvPath, TEST_FIXTURE_HCLVALIDATE) @@ -1108,6 +1112,7 @@ func TestTerragruntWorksWithNonDefaultConfigNames(t *testing.T) { } func TestTerragruntReportsTerraformErrorsWithPlanAll(t *testing.T) { + t.Parallel() cleanupTerraformFolder(t, TEST_FIXTURE_FAILED_TERRAFORM) tmpEnvPath := copyEnvironment(t, TEST_FIXTURE_FAILED_TERRAFORM) @@ -1346,7 +1351,7 @@ func testRemoteFixtureParallelism(t *testing.T, parallelism int, numberOfModules return stdout, testStart, nil } -func TestTerragruntStackCommands(t *testing.T) { +func TestTerragruntStackCommands(t *testing.T) { //nolint paralleltest // It seems that disabling parallel test execution helps avoid the CircleCi error: “NoSuchBucket Policy: The bucket policy does not exist.” // t.Parallel() @@ -1574,14 +1579,14 @@ func TestAutoRetryConfigurableRetries(t *testing.T) { func TestAutoRetryConfigurableRetriesErrors(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { fixture string errorMessage string }{ {TEST_FIXTURE_AUTO_RETRY_CONFIGURABLE_RETRIES_ERROR_1, "Cannot have less than 1 max retry"}, {TEST_FIXTURE_AUTO_RETRY_CONFIGURABLE_RETRIES_ERROR_2, "Cannot sleep for less than 0 seconds"}, } - for _, tc := range testCases { + for _, tc := range tc { tc := tc t.Run(tc.fixture, func(t *testing.T) { t.Parallel() @@ -1636,7 +1641,7 @@ func TestAwsProviderPatch(t *testing.T) { func TestTerraformCommandCliArgs(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { command []string expected string expectedErr error @@ -1673,8 +1678,8 @@ func TestTerraformCommandCliArgs(t *testing.T) { }, } - for _, testCase := range testCases { - cmd := fmt.Sprintf("terragrunt %s --terragrunt-non-interactive --terragrunt-log-level debug --terragrunt-working-dir %s", strings.Join(testCase.command, " "), TEST_FIXTURE_EXTRA_ARGS_PATH) + for _, tt := range tc { + cmd := fmt.Sprintf("terragrunt %s --terragrunt-non-interactive --terragrunt-log-level debug --terragrunt-working-dir %s", strings.Join(tt.command, " "), TEST_FIXTURE_EXTRA_ARGS_PATH) var ( stdout bytes.Buffer @@ -1682,13 +1687,13 @@ func TestTerraformCommandCliArgs(t *testing.T) { ) err := runTerragruntCommand(t, cmd, &stdout, &stderr) - if testCase.expectedErr != nil { - require.ErrorIs(t, err, testCase.expectedErr) + if tt.expectedErr != nil { + require.ErrorIs(t, err, tt.expectedErr) } output := stdout.String() errOutput := stderr.String() - assert.True(t, strings.Contains(errOutput, testCase.expected) || strings.Contains(output, testCase.expected)) + assert.True(t, strings.Contains(errOutput, tt.expected) || strings.Contains(output, tt.expected)) } } @@ -1697,7 +1702,7 @@ func TestTerraformCommandCliArgs(t *testing.T) { func TestTerraformSubcommandCliArgs(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { command []string expected string }{ @@ -1719,8 +1724,8 @@ func TestTerraformSubcommandCliArgs(t *testing.T) { }, } - for _, testCase := range testCases { - cmd := fmt.Sprintf("terragrunt %s --terragrunt-non-interactive --terragrunt-log-level debug --terragrunt-working-dir %s", strings.Join(testCase.command, " "), TEST_FIXTURE_EXTRA_ARGS_PATH) + for _, tt := range tc { + cmd := fmt.Sprintf("terragrunt %s --terragrunt-non-interactive --terragrunt-log-level debug --terragrunt-working-dir %s", strings.Join(tt.command, " "), TEST_FIXTURE_EXTRA_ARGS_PATH) var ( stdout bytes.Buffer @@ -1732,7 +1737,7 @@ func TestTerraformSubcommandCliArgs(t *testing.T) { } output := stdout.String() errOutput := stderr.String() - assert.True(t, strings.Contains(errOutput, testCase.expected) || strings.Contains(output, testCase.expected)) + assert.True(t, strings.Contains(errOutput, tt.expected) || strings.Contains(output, tt.expected)) } } @@ -2273,6 +2278,8 @@ func TestYamlDecodeRegressions(t *testing.T) { // If output optimization is working, we should still get the same correct output even though the state of the upmost // module has been destroyed. func TestDependencyOutputOptimization(t *testing.T) { + t.Parallel() + expectOutputLogs := []string{ `Running command: ` + wrappedBinary() + ` init -get=false prefix=\[.*fixture-get-output/nested-optimization/dep\]`, } @@ -2280,6 +2287,8 @@ func TestDependencyOutputOptimization(t *testing.T) { } func TestDependencyOutputOptimizationSkipInit(t *testing.T) { + t.Parallel() + expectOutputLogs := []string{ `Detected module .*nested-optimization/dep/terragrunt.hcl is already init-ed. Retrieving outputs directly from working directory. prefix=\[.*fixture-get-output/nested-optimization/dep\]`, } @@ -2287,6 +2296,8 @@ func TestDependencyOutputOptimizationSkipInit(t *testing.T) { } func TestDependencyOutputOptimizationNoGenerate(t *testing.T) { + t.Parallel() + expectOutputLogs := []string{ `Running command: ` + wrappedBinary() + ` init -get=false prefix=\[.*fixture-get-output/nested-optimization-nogen/dep\]`, } @@ -2294,8 +2305,6 @@ func TestDependencyOutputOptimizationNoGenerate(t *testing.T) { } func dependencyOutputOptimizationTest(t *testing.T, moduleName string, forceInit bool, expectedOutputLogs []string) { - t.Parallel() - expectedOutput := `They said, "No, The answer is 42"` generatedUniqueId := uniqueId() @@ -3071,22 +3080,22 @@ func TestDependencyOutputCycleHandling(t *testing.T) { cleanupTerraformFolder(t, TEST_FIXTURE_GET_OUTPUT) - testCases := []string{ + tc := []string{ "aa", "aba", "abca", "abcda", } - for _, testCase := range testCases { + for _, tt := range tc { // Capture range variable into forloop so that the binding is consistent across runs. - testCase := testCase + tt := tt - t.Run(testCase, func(t *testing.T) { + t.Run(tt, func(t *testing.T) { t.Parallel() tmpEnvPath := copyEnvironment(t, TEST_FIXTURE_GET_OUTPUT) - rootPath := util.JoinPath(tmpEnvPath, TEST_FIXTURE_GET_OUTPUT, "cycle", testCase) + rootPath := util.JoinPath(tmpEnvPath, TEST_FIXTURE_GET_OUTPUT, "cycle", tt) fooPath := util.JoinPath(rootPath, "foo") planStdout := bytes.Buffer{} @@ -3135,7 +3144,7 @@ func TestDependencyOutputSameOutputConcurrencyRegression(t *testing.T) { // Use func to isolate each test run to a single s3 bucket that is deleted. We run the test multiple times // because the underlying error we are trying to test against is nondeterministic, and thus may not always work // the first time. - testCase := func() { + tt := func() { cleanupTerraformFolder(t, TEST_FIXTURE_GET_OUTPUT) tmpEnvPath := copyEnvironment(t, TEST_FIXTURE_GET_OUTPUT) rootPath := util.JoinPath(tmpEnvPath, TEST_FIXTURE_GET_OUTPUT, "regression-906") @@ -3161,7 +3170,7 @@ func TestDependencyOutputSameOutputConcurrencyRegression(t *testing.T) { } for i := 0; i < 3; i++ { - testCase() + tt() // We need to bust the output cache that stores the dependency outputs so that the second run pulls the outputs. // This is only a problem during testing, where the process is shared across terragrunt runs. config.ClearOutputCache() @@ -4219,7 +4228,9 @@ func TestTerragruntIncludeParentHclFile(t *testing.T) { } func TestTerragruntVersionConstraints(t *testing.T) { - testCases := []struct { + t.Parallel() + + tc := []struct { name string terragruntVersion string terragruntConstraint string @@ -4257,24 +4268,25 @@ func TestTerragruntVersionConstraints(t *testing.T) { }, } - for _, testCase := range testCases { - testCase := testCase + for _, tt := range tc { + tt := tt - t.Run(testCase.name, func(t *testing.T) { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() tmpEnvPath := copyEnvironment(t, TEST_FIXTURE_READ_CONFIG) rootPath := filepath.Join(tmpEnvPath, TEST_FIXTURE_READ_CONFIG, "with_constraints") - tmpTerragruntConfigPath := createTmpTerragruntConfigContent(t, testCase.terragruntConstraint, config.DefaultTerragruntConfigPath) + tmpTerragruntConfigPath := createTmpTerragruntConfigContent(t, tt.terragruntConstraint, config.DefaultTerragruntConfigPath) stdout := bytes.Buffer{} stderr := bytes.Buffer{} - err := runTerragruntVersionCommand(t, testCase.terragruntVersion, fmt.Sprintf("terragrunt apply -auto-approve --terragrunt-non-interactive --terragrunt-config %s --terragrunt-working-dir %s", tmpTerragruntConfigPath, rootPath), &stdout, &stderr) + err := runTerragruntVersionCommand(t, tt.terragruntVersion, fmt.Sprintf("terragrunt apply -auto-approve --terragrunt-non-interactive --terragrunt-config %s --terragrunt-working-dir %s", tmpTerragruntConfigPath, rootPath), &stdout, &stderr) logBufferContentsLineByLine(t, stdout, "stdout") logBufferContentsLineByLine(t, stderr, "stderr") - if testCase.shouldSucceed { + if tt.shouldSucceed { require.NoError(t, err) } else { require.Error(t, err) @@ -4366,6 +4378,8 @@ func TestIamRolesLoadingFromDifferentModules(t *testing.T) { } func TestTerragruntVersionConstraintsPartialParse(t *testing.T) { + t.Parallel() + fixturePath := "fixture-partial-parse/terragrunt-version-constraint" cleanupTerragruntFolder(t, fixturePath) @@ -4384,6 +4398,8 @@ func TestTerragruntVersionConstraintsPartialParse(t *testing.T) { } func TestLogFailedLocalsEvaluation(t *testing.T) { + t.Parallel() + var ( stdout bytes.Buffer stderr bytes.Buffer @@ -4400,6 +4416,8 @@ func TestLogFailedLocalsEvaluation(t *testing.T) { } func TestLogFailingDependencies(t *testing.T) { + t.Parallel() + var ( stdout bytes.Buffer stderr bytes.Buffer @@ -5205,6 +5223,7 @@ func TestTerragruntInitRunCmd(t *testing.T) { } func TestShowWarningWithDependentModulesBeforeDestroy(t *testing.T) { + t.Parallel() rootPath := copyEnvironment(t, TEST_FIXTURE_DESTROY_WARNING) @@ -5236,7 +5255,7 @@ func TestShowWarningWithDependentModulesBeforeDestroy(t *testing.T) { assert.Equal(t, 1, strings.Count(output, appV2Path)) } -func TestTerragruntOutputFromRemoteState(t *testing.T) { +func TestTerragruntOutputFromRemoteState(t *testing.T) { //nolint: paralleltest // NOTE: We can't run this test in parallel because there are other tests that also call `config.ClearOutputCache()`, but this function uses a global variable and sometimes it throws an unexpected error: // "fixture-output-from-remote-state/env1/app2/terragrunt.hcl:23,38-48: Unsupported attribute; This object does not have an attribute named "app3_text"." // t.Parallel() @@ -5567,6 +5586,8 @@ func TestOutputModuleGroups(t *testing.T) { tt := tt t.Run(name, func(t *testing.T) { + t.Parallel() + var ( stdout bytes.Buffer stderr bytes.Buffer @@ -6938,7 +6959,7 @@ func TestTerragruntUpdatePolicy(t *testing.T) { func TestTerragruntDestroyGraph(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { path string expectedModules []string notExpectedModules []string @@ -6965,22 +6986,24 @@ func TestTerragruntDestroyGraph(t *testing.T) { }, } - for _, testCase := range testCases { - testCase := testCase + for _, tt := range tc { + tt := tt + + t.Run(tt.path, func(t *testing.T) { + t.Parallel() - t.Run(testCase.path, func(t *testing.T) { tmpEnvPath := prepareGraphFixture(t) - tmpModulePath := util.JoinPath(tmpEnvPath, TEST_FIXTURE_GRAPH, testCase.path) + tmpModulePath := util.JoinPath(tmpEnvPath, TEST_FIXTURE_GRAPH, tt.path) stdout, stderr, err := runTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt graph destroy --terragrunt-non-interactive --terragrunt-working-dir %s --terragrunt-graph-root %s", tmpModulePath, tmpEnvPath)) require.NoError(t, err) output := fmt.Sprintf("%v\n%v\n", stdout, stderr) - for _, module := range testCase.expectedModules { + for _, module := range tt.expectedModules { assert.Containsf(t, output, "/"+module+"\n", "Expected module %s to be in output", module) } - for _, module := range testCase.notExpectedModules { + for _, module := range tt.notExpectedModules { assert.NotContainsf(t, output, "Module "+tmpModulePath+"/"+module+"\n", "Expected module %s must not to be in output", module) } }) @@ -6990,7 +7013,7 @@ func TestTerragruntDestroyGraph(t *testing.T) { func TestTerragruntApplyGraph(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { path string expectedModules []string notExpectedModules []string @@ -7012,22 +7035,24 @@ func TestTerragruntApplyGraph(t *testing.T) { }, } - for _, testCase := range testCases { - testCase := testCase + for _, tt := range tc { + tt := tt + + t.Run(tt.path, func(t *testing.T) { + t.Parallel() - t.Run(testCase.path, func(t *testing.T) { tmpEnvPath := prepareGraphFixture(t) - tmpModulePath := util.JoinPath(tmpEnvPath, TEST_FIXTURE_GRAPH, testCase.path) + tmpModulePath := util.JoinPath(tmpEnvPath, TEST_FIXTURE_GRAPH, tt.path) stdout, stderr, err := runTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt graph apply --terragrunt-non-interactive --terragrunt-working-dir %s --terragrunt-graph-root %s", tmpModulePath, tmpEnvPath)) require.NoError(t, err) output := fmt.Sprintf("%v\n%v\n", stdout, stderr) - for _, module := range testCase.expectedModules { + for _, module := range tt.expectedModules { assert.Containsf(t, output, "/"+module+"\n", "Expected module %s to be in output", module) } - for _, module := range testCase.notExpectedModules { + for _, module := range tt.notExpectedModules { assert.NotContainsf(t, output, "Module "+tmpModulePath+"/"+module+"\n", "Expected module %s must not to be in output", module) } }) diff --git a/test/integration_tflint_test.go b/test/integration_tflint_test.go index 704b3154b..9dee4adbe 100644 --- a/test/integration_tflint_test.go +++ b/test/integration_tflint_test.go @@ -1,7 +1,7 @@ //go:build tflint // +build tflint -package test +package integration_test import ( "bytes" diff --git a/test/integration_unix_test.go b/test/integration_unix_test.go index 811745936..c5e00064f 100644 --- a/test/integration_unix_test.go +++ b/test/integration_unix_test.go @@ -1,7 +1,7 @@ //go:build linux || darwin // +build linux darwin -package test +package integration_test import ( "testing" diff --git a/test/integration_windows_test.go b/test/integration_windows_test.go index 50e5779b0..6af4e9c04 100644 --- a/test/integration_windows_test.go +++ b/test/integration_windows_test.go @@ -1,7 +1,7 @@ //go:build windows // +build windows -package test +package integration_test import ( "bytes" diff --git a/tflint/tflint.go b/tflint/tflint.go index ea054d721..2334e9f4f 100644 --- a/tflint/tflint.go +++ b/tflint/tflint.go @@ -43,7 +43,7 @@ func RunTflintWithOpts(ctx context.Context, opts *options.TerragruntOptions, con opts.Logger.Debugf("Using .tflint.hcl file in %s", configFile) - variables, err := inputsToTflintVar(config.Inputs) + variables, err := InputsToTflintVar(config.Inputs) if err != nil { return err } @@ -140,8 +140,8 @@ func tflintConfigFilePath(arguments []string) string { return "" } -// inputsToTflintVar converts the inputs map to a list of tflint variables. -func inputsToTflintVar(inputs map[string]interface{}) ([]string, error) { +// InputsToTflintVar converts the inputs map to a list of tflint variables. +func InputsToTflintVar(inputs map[string]interface{}) ([]string, error) { variables := make([]string, 0, len(inputs)) for key, value := range inputs { varValue, err := util.AsTerraformEnvVarJsonValue(value) diff --git a/tflint/tflint_test.go b/tflint/tflint_test.go index 9dd3b6e88..11413c400 100644 --- a/tflint/tflint_test.go +++ b/tflint/tflint_test.go @@ -1,8 +1,9 @@ -package tflint +package tflint_test import ( "testing" + "github.com/gruntwork-io/terragrunt/tflint" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -10,32 +11,43 @@ import ( func TestInputsToTflintVar(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { + name string inputs map[string]interface{} expected []string }{ { + "strings", map[string]interface{}{"region": "eu-central-1", "instance_count": 3}, []string{"--var=region=eu-central-1", "--var=instance_count=3"}, }, { + "strings and arrays", map[string]interface{}{"cidr_blocks": []string{"10.0.0.0/16"}}, []string{"--var=cidr_blocks=[\"10.0.0.0/16\"]"}, }, { + "boolean", map[string]interface{}{"create_resource": true}, []string{"--var=create_resource=true"}, }, { + "with white spaces", // With white spaces, the string is still validated by tflint. map[string]interface{}{"region": " eu-central-1 "}, []string{"--var=region= eu-central-1 "}, }, } - for _, testCase := range testCases { - actual, err := inputsToTflintVar(testCase.inputs) - require.NoError(t, err) - assert.ElementsMatch(t, testCase.expected, actual) + for _, tt := range tc { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + actual, err := tflint.InputsToTflintVar(tt.inputs) + require.NoError(t, err) + assert.ElementsMatch(t, tt.expected, actual) + }) } } diff --git a/util/collections_test.go b/util/collections_test.go index 46eea03e0..b19dedc56 100644 --- a/util/collections_test.go +++ b/util/collections_test.go @@ -1,8 +1,10 @@ -package util +package util_test import ( + "strconv" "testing" + "github.com/gruntwork-io/terragrunt/util" "github.com/stretchr/testify/assert" ) @@ -15,7 +17,7 @@ func TestMatchesAny(t *testing.T) { "Error configuring the backend \"s3\": RequestError: send request failed\ncaused by: Post https://sts.amazonaws.com/: net/http: TLS handshake timeout", } - testCases := []struct { + tc := []struct { list []string element string expected bool @@ -31,16 +33,22 @@ func TestMatchesAny(t *testing.T) { {[]string{"(?s).*Error configuring the backend.*TLS handshake timeout.*"}, realWorldErrorMessages[2], true}, } - for _, testCase := range testCases { - actual := MatchesAny(testCase.list, testCase.element) - assert.Equal(t, testCase.expected, actual, "For list %v and element %s", testCase.list, testCase.element) + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + + actual := util.MatchesAny(tt.list, tt.element) + assert.Equal(t, tt.expected, actual, "For list %v and element %s", tt.list, tt.element) + }) } } func TestListContainsElement(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { list []string element string expected bool @@ -53,16 +61,22 @@ func TestListContainsElement(t *testing.T) { {[]string{"bar", "foo", "baz"}, "", false}, } - for _, testCase := range testCases { - actual := ListContainsElement(testCase.list, testCase.element) - assert.Equal(t, testCase.expected, actual, "For list %v and element %s", testCase.list, testCase.element) + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + + actual := util.ListContainsElement(tt.list, tt.element) + assert.Equal(t, tt.expected, actual, "For list %v and element %s", tt.list, tt.element) + }) } } func TestListEquals(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { a []string b []string expected bool @@ -77,16 +91,22 @@ func TestListEquals(t *testing.T) { {[]string{""}, []string{""}, true}, {[]string{"foo", "bar"}, []string{"foo", "bar"}, true}, } - for _, testCase := range testCases { - actual := ListEquals(testCase.a, testCase.b) - assert.Equal(t, testCase.expected, actual, "For list %v and list %v", testCase.a, testCase.b) + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + + actual := util.ListEquals(tt.a, tt.b) + assert.Equal(t, tt.expected, actual, "For list %v and list %v", tt.a, tt.b) + }) } } func TestListContainsSublist(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { list []string sublist []string expected bool @@ -114,16 +134,22 @@ func TestListContainsSublist(t *testing.T) { {[]string{"zim", "gee", "foo", "bar"}, []string{"gee", "foo", "bar"}, true}, } - for _, testCase := range testCases { - actual := ListContainsSublist(testCase.list, testCase.sublist) - assert.Equal(t, testCase.expected, actual, "For list %v and sublist %v", testCase.list, testCase.sublist) + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + + actual := util.ListContainsSublist(tt.list, tt.sublist) + assert.Equal(t, tt.expected, actual, "For list %v and sublist %v", tt.list, tt.sublist) + }) } } func TestListHasPrefix(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { list []string prefix []string expected bool @@ -141,16 +167,22 @@ func TestListHasPrefix(t *testing.T) { {[]string{"foo", "bar"}, []string{"foo", "bar"}, true}, {[]string{"foo", "bar", "biz"}, []string{"foo", "bar"}, true}, } - for _, testCase := range testCases { - actual := ListHasPrefix(testCase.list, testCase.prefix) - assert.Equal(t, testCase.expected, actual, "For list %v and prefix %v", testCase.list, testCase.prefix) + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + + actual := util.ListHasPrefix(tt.list, tt.prefix) + assert.Equal(t, tt.expected, actual, "For list %v and prefix %v", tt.list, tt.prefix) + }) } } func TestRemoveElementFromList(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { list []string element string expected []string @@ -164,16 +196,22 @@ func TestRemoveElementFromList(t *testing.T) { {[]string{"bar", "foo", "baz"}, "", []string{"bar", "foo", "baz"}}, } - for _, testCase := range testCases { - actual := RemoveElementFromList(testCase.list, testCase.element) - assert.Equal(t, testCase.expected, actual, "For list %v and element %s", testCase.list, testCase.element) + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + + actual := util.RemoveElementFromList(tt.list, tt.element) + assert.Equal(t, tt.expected, actual, "For list %v and element %s", tt.list, tt.element) + }) } } func TestRemoveDuplicatesFromList(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { list []string expected []string reverse bool @@ -187,20 +225,26 @@ func TestRemoveDuplicatesFromList(t *testing.T) { {[]string{"foo", "bar", "foobar", "foo", "bar"}, []string{"foobar", "foo", "bar"}, true}, } - for _, testCase := range testCases { - f := RemoveDuplicatesFromList[[]string] - if testCase.reverse { - f = RemoveDuplicatesFromListKeepLast[[]string] - } - assert.Equal(t, testCase.expected, f(testCase.list), "For list %v", testCase.list) - t.Logf("%v passed", testCase.list) + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + + f := util.RemoveDuplicatesFromList[[]string] + if tt.reverse { + f = util.RemoveDuplicatesFromListKeepLast[[]string] + } + assert.Equal(t, tt.expected, f(tt.list), "For list %v", tt.list) + t.Logf("%v passed", tt.list) + }) } } func TestCommaSeparatedStrings(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { list []string expected string }{ @@ -209,16 +253,22 @@ func TestCommaSeparatedStrings(t *testing.T) { {[]string{"foo", "bar"}, `"foo", "bar"`}, } - for _, testCase := range testCases { - assert.Equal(t, testCase.expected, CommaSeparatedStrings(testCase.list), "For list %v", testCase.list) - t.Logf("%v passed", testCase.list) + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + + assert.Equal(t, tt.expected, util.CommaSeparatedStrings(tt.list), "For list %v", tt.list) + t.Logf("%v passed", tt.list) + }) } } func TestStringListInsert(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { list []string element string index int @@ -230,8 +280,14 @@ func TestStringListInsert(t *testing.T) { {[]string{"a", "b", "d"}, "c", 2, []string{"a", "b", "c", "d"}}, } - for _, testCase := range testCases { - assert.Equal(t, testCase.expected, StringListInsert(testCase.list, testCase.element, testCase.index), "For list %v", testCase.list) - t.Logf("%v passed", testCase.list) + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + + assert.Equal(t, tt.expected, util.StringListInsert(tt.list, tt.element, tt.index), "For list %v", tt.list) + t.Logf("%v passed", tt.list) + }) } } diff --git a/util/datetime_test.go b/util/datetime_test.go index 1455121cf..7e8b2205a 100644 --- a/util/datetime_test.go +++ b/util/datetime_test.go @@ -1,10 +1,11 @@ -package util +package util_test import ( "fmt" "testing" "time" + "github.com/gruntwork-io/terragrunt/util" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -12,7 +13,7 @@ import ( func TestParseTimestamp(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { arg string value time.Time err string @@ -23,20 +24,20 @@ func TestParseTimestamp(t *testing.T) { {"2017-11-22 00:00:00Z", time.Time{}, `not a valid RFC3339 timestamp: missing required time introducer 'T'`}, } - for _, testCase := range testCases { - testCase := testCase + for _, tt := range tc { + tt := tt - t.Run(fmt.Sprintf("ParseTimestamp(%#v)", testCase.arg), func(t *testing.T) { + t.Run(fmt.Sprintf("ParseTimestamp(%#v)", tt.arg), func(t *testing.T) { t.Parallel() - actual, err := ParseTimestamp(testCase.arg) - if testCase.err != "" { - require.EqualError(t, err, testCase.err) + actual, err := util.ParseTimestamp(tt.arg) + if tt.err != "" { + require.EqualError(t, err, tt.err) } else { require.NoError(t, err) } - assert.Equal(t, testCase.value, actual) + assert.Equal(t, tt.value, actual) }) } } diff --git a/util/file.go b/util/file.go index 07e221c44..31e896433 100644 --- a/util/file.go +++ b/util/file.go @@ -291,7 +291,7 @@ func CopyFolderContentsWithFilter(source, destination, manifestFile string, filt if err := os.MkdirAll(destination, ownerReadWriteExecutePerms); err != nil { return errors.WithStackTrace(err) } - manifest := newFileManifest(destination, manifestFile) + manifest := NewFileManifest(destination, manifestFile) if err := manifest.Clean(); err != nil { return errors.WithStackTrace(err) } @@ -565,7 +565,7 @@ func (manifest *fileManifest) Close() error { return manifest.fileHandle.Close() } -func newFileManifest(manifestFolder string, manifestFile string) *fileManifest { +func NewFileManifest(manifestFolder string, manifestFile string) *fileManifest { return &fileManifest{ManifestFolder: manifestFolder, ManifestFile: manifestFile} } diff --git a/util/file_test.go b/util/file_test.go index fec3bbbbb..70ca5b538 100644 --- a/util/file_test.go +++ b/util/file_test.go @@ -1,4 +1,4 @@ -package util +package util_test import ( "errors" @@ -6,11 +6,13 @@ import ( "path" "path/filepath" "sort" + "strconv" "testing" "fmt" "github.com/gruntwork-io/terragrunt/test/helpers" + "github.com/gruntwork-io/terragrunt/util" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -18,7 +20,7 @@ import ( func TestGetPathRelativeTo(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { path string basePath string expected string @@ -33,17 +35,23 @@ func TestGetPathRelativeTo(t *testing.T) { {helpers.RootFolder + "root", helpers.RootFolder + "other-root/sub-child/sub-sub-child", "../../../root"}, } - for _, testCase := range testCases { - actual, err := GetPathRelativeTo(testCase.path, testCase.basePath) - require.NoError(t, err) - assert.Equal(t, testCase.expected, actual, "For path %s and basePath %s", testCase.path, testCase.basePath) + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + + actual, err := util.GetPathRelativeTo(tt.path, tt.basePath) + require.NoError(t, err) + assert.Equal(t, tt.expected, actual, "For path %s and basePath %s", tt.path, tt.basePath) + }) } } func TestCanonicalPath(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { path string basePath string expected string @@ -62,10 +70,16 @@ func TestCanonicalPath(t *testing.T) { {helpers.RootFolder + "other/../blah", helpers.RootFolder + "foo", helpers.RootFolder + "blah"}, } - for _, testCase := range testCases { - actual, err := CanonicalPath(testCase.path, testCase.basePath) - require.NoError(t, err) - assert.Equal(t, testCase.expected, actual, "For path %s and basePath %s", testCase.path, testCase.basePath) + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + + actual, err := util.CanonicalPath(tt.path, tt.basePath) + require.NoError(t, err) + assert.Equal(t, tt.expected, actual, "For path %s and basePath %s", tt.path, tt.basePath) + }) } } @@ -80,7 +94,7 @@ func TestGlobCanonicalPath(t *testing.T) { return filepath.ToSlash(filepath.Join(basePath, path)) } - testCases := []struct { + tc := []struct { paths []string expected []string }{ @@ -91,26 +105,32 @@ func TestGlobCanonicalPath(t *testing.T) { {[]string{"module-*/**/*.hcl"}, []string{expectedHelper("module-a/terragrunt.hcl"), expectedHelper("module-b/terragrunt.hcl"), expectedHelper("module-b/module-b-child/terragrunt.hcl")}}, } - for _, testCase := range testCases { - actual, err := GlobCanonicalPath(basePath, testCase.paths...) + for i, tt := range tc { + tt := tt - sort.Slice(actual, func(i, j int) bool { - return actual[i] < actual[j] - }) + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() - sort.Slice(testCase.expected, func(i, j int) bool { - return testCase.expected[i] < testCase.expected[j] - }) + actual, err := util.GlobCanonicalPath(basePath, tt.paths...) - require.NoError(t, err) - assert.Equal(t, testCase.expected, actual, "For path %s and basePath %s", testCase.paths, basePath) + sort.Slice(actual, func(i, j int) bool { + return actual[i] < actual[j] + }) + + sort.Slice(tt.expected, func(i, j int) bool { + return tt.expected[i] < tt.expected[j] + }) + + require.NoError(t, err) + assert.Equal(t, tt.expected, actual, "For path %s and basePath %s", tt.paths, basePath) + }) } } func TestPathContainsHiddenFileOrFolder(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { path string expected bool }{ @@ -130,17 +150,23 @@ func TestPathContainsHiddenFileOrFolder(t *testing.T) { {"/foo/.././.bar/", true}, } - for _, testCase := range testCases { - path := filepath.FromSlash(testCase.path) - actual := TerragruntExcludes(path) - assert.Equal(t, testCase.expected, actual, "For path %s", path) + for _, tt := range tc { + tt := tt + + t.Run(tt.path, func(t *testing.T) { + t.Parallel() + + path := filepath.FromSlash(tt.path) + actual := util.TerragruntExcludes(path) + assert.Equal(t, tt.expected, actual, "For path %s", path) + }) } } func TestJoinTerraformModulePath(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { modulesFolder string path string expected string @@ -161,10 +187,14 @@ func TestJoinTerraformModulePath(t *testing.T) { {"/foo/bar/baz/?ref=feature/1", "//a/b/c", "/foo/bar/baz//a/b/c?ref=feature/1"}, } - for _, testCase := range testCases { - t.Run(fmt.Sprintf("%s-%s", testCase.modulesFolder, testCase.path), func(t *testing.T) { - actual := JoinTerraformModulePath(testCase.modulesFolder, testCase.path) - assert.Equal(t, testCase.expected, actual) + for _, tt := range tc { + tt := tt + + t.Run(fmt.Sprintf("%s-%s", tt.modulesFolder, tt.path), func(t *testing.T) { + t.Parallel() + + actual := util.JoinTerraformModulePath(tt.modulesFolder, tt.path) + assert.Equal(t, tt.expected, actual) }) } } @@ -188,7 +218,7 @@ func TestFileManifest(t *testing.T) { testfiles = append(testfiles, path.Join(dir, "ephemeral-file-that-doesnt-exist.txt")) // create a manifest - manifest := newFileManifest(dir, ".terragrunt-test-manifest") + manifest := util.NewFileManifest(dir, ".terragrunt-test-manifest") require.NoError(t, manifest.Create()) // check the file manifest has been created assert.FileExists(t, filepath.Join(manifest.ManifestFolder, manifest.ManifestFile)) @@ -201,7 +231,7 @@ func TestFileManifest(t *testing.T) { assert.NoError(t, manifest.Clean()) // test if the files have been deleted for _, file := range testfiles { - assert.False(t, FileExists(file)) + assert.False(t, util.FileExists(file)) } } @@ -209,7 +239,7 @@ func TestFileManifest(t *testing.T) { func TestSplitPath(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { path string expected []string }{ @@ -219,16 +249,22 @@ func TestSplitPath(t *testing.T) { {"foo//////bar/.tf/tg.hcl", []string{"foo", "bar", ".tf", "tg.hcl"}}, } - for _, testCase := range testCases { - actual := SplitPath(testCase.path) - assert.Equal(t, testCase.expected, actual, "For path %s", testCase.path) + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + + actual := util.SplitPath(tt.path) + assert.Equal(t, tt.expected, actual, "For path %s", tt.path) + }) } } func TestContainsPath(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { path string subpath string expected bool @@ -248,16 +284,21 @@ func TestContainsPath(t *testing.T) { {"foo/bar/.tf/tg.hcl", "foo/ba", false}, } - for _, testCase := range testCases { - actual := ContainsPath(testCase.path, testCase.subpath) - assert.Equal(t, testCase.expected, actual, "For path %s and subpath %s", testCase.path, testCase.subpath) + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + actual := util.ContainsPath(tt.path, tt.subpath) + assert.Equal(t, tt.expected, actual, "For path %s and subpath %s", tt.path, tt.subpath) + }) } } func TestHasPathPrefix(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { path string prefix string expected bool @@ -277,16 +318,24 @@ func TestHasPathPrefix(t *testing.T) { {"/foo/bar/.tf/tg.hcl", "/foo/ba", false}, } - for _, testCase := range testCases { - actual := HasPathPrefix(testCase.path, testCase.prefix) - assert.Equal(t, testCase.expected, actual, "For path %s and prefix %s", testCase.path, testCase.prefix) + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + + actual := util.HasPathPrefix(tt.path, tt.prefix) + assert.Equal(t, tt.expected, actual, "For path %s and prefix %s", tt.path, tt.prefix) + }) } } func TestIncludeInCopy(t *testing.T) { + t.Parallel() + includeInCopy := []string{"_module/.region2", "**/app2", "**/.include-me-too"} - testCases := []struct { + tc := []struct { path string copyExpected bool }{ @@ -306,36 +355,47 @@ func TestIncludeInCopy(t *testing.T) { destination := filepath.Join(tempDir, "destination") fileContent := []byte("source file") - for _, testCase := range testCases { - path := filepath.Join(source, testCase.path) + for _, tt := range tc { + path := filepath.Join(source, tt.path) assert.NoError(t, os.MkdirAll(filepath.Dir(path), os.ModePerm)) assert.NoError(t, os.WriteFile(path, fileContent, 0644)) } - require.NoError(t, CopyFolderContents(source, destination, ".terragrunt-test", includeInCopy)) + require.NoError(t, util.CopyFolderContents(source, destination, ".terragrunt-test", includeInCopy)) + + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() - for _, testCase := range testCases { - _, err := os.Stat(filepath.Join(destination, testCase.path)) - assert.True(t, - testCase.copyExpected && err == nil || - !testCase.copyExpected && errors.Is(err, os.ErrNotExist), - "Unexpected copy result for file '%s' (should be copied: '%t') - got error: %s", testCase.path, testCase.copyExpected, err) + _, err := os.Stat(filepath.Join(destination, tt.path)) + assert.True(t, + tt.copyExpected && err == nil || + !tt.copyExpected && errors.Is(err, os.ErrNotExist), + "Unexpected copy result for file '%s' (should be copied: '%t') - got error: %s", tt.path, tt.copyExpected, err) + }) } } func TestEmptyDir(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { path string expectEmpty bool }{ {t.TempDir(), true}, {os.TempDir(), false}, } - for _, testCase := range testCases { - emptyValue, err := IsDirectoryEmpty(testCase.path) - require.NoError(t, err) - assert.Equal(t, testCase.expectEmpty, emptyValue, "For path %s", testCase.path) - } + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + emptyValue, err := util.IsDirectoryEmpty(tt.path) + require.NoError(t, err) + assert.Equal(t, tt.expectEmpty, emptyValue, "For path %s", tt.path) + }) + } } diff --git a/util/jsons_test.go b/util/jsons_test.go index ebf699318..2896de2d0 100644 --- a/util/jsons_test.go +++ b/util/jsons_test.go @@ -1,8 +1,10 @@ -package util +package util_test import ( + "strconv" "testing" + "github.com/gruntwork-io/terragrunt/util" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -10,7 +12,7 @@ import ( func TestAsTerraformEnvVarJsonValue(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { value interface{} expected string }{ @@ -18,9 +20,15 @@ func TestAsTerraformEnvVarJsonValue(t *testing.T) { {[]string{"10.0.0.0/16", "10.0.0.10/16"}, "[\"10.0.0.0/16\",\"10.0.0.10/16\"]"}, } - for _, testCase := range testCases { - actual, err := AsTerraformEnvVarJsonValue(testCase.value) - require.NoError(t, err) - assert.Equal(t, testCase.expected, actual) + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + + actual, err := util.AsTerraformEnvVarJsonValue(tt.value) + require.NoError(t, err) + assert.Equal(t, tt.expected, actual) + }) } } diff --git a/util/locks_test.go b/util/locks_test.go index 35a5379b3..5783114b2 100644 --- a/util/locks_test.go +++ b/util/locks_test.go @@ -1,16 +1,17 @@ -package util +package util_test import ( "sync" "testing" + "github.com/gruntwork-io/terragrunt/util" "github.com/stretchr/testify/require" ) // TestKeyLocksBasic verifies basic locking and unlocking behavior. func TestKeyLocksBasic(t *testing.T) { t.Parallel() - kl := NewKeyLocks() + kl := util.NewKeyLocks() var counter int // Counter to track lock/unlock cycles kl.Lock("key1") @@ -24,7 +25,7 @@ func TestKeyLocksBasic(t *testing.T) { // TestKeyLocksConcurrentAccess ensures thread-safe access for multiple keys. func TestKeyLocksConcurrentAccess(t *testing.T) { t.Parallel() - kl := NewKeyLocks() + kl := util.NewKeyLocks() var counters [10]int var wg sync.WaitGroup @@ -49,7 +50,7 @@ func TestKeyLocksConcurrentAccess(t *testing.T) { // TestKeyLocksUnlockWithoutLock checks for safe behavior when unlocking without locking. func TestKeyLocksUnlockWithoutLock(t *testing.T) { t.Parallel() - kl := NewKeyLocks() + kl := util.NewKeyLocks() require.NotPanics(t, func() { kl.Unlock("nonexistent_key") }, "Unlocking without locking should not panic") @@ -58,7 +59,7 @@ func TestKeyLocksUnlockWithoutLock(t *testing.T) { // TestKeyLocksLockUnlockStressWithSharedKey tests a shared key under high concurrent load. func TestKeyLocksLockUnlockStressWithSharedKey(t *testing.T) { t.Parallel() - kl := NewKeyLocks() + kl := util.NewKeyLocks() const numGoroutines = 100 const numOperations = 1000 var wg sync.WaitGroup diff --git a/util/min_test.go b/util/min_test.go index 64746ee36..d1e744dae 100644 --- a/util/min_test.go +++ b/util/min_test.go @@ -1,15 +1,17 @@ -package util +package util_test import ( + "strconv" "testing" + "github.com/gruntwork-io/terragrunt/util" "github.com/stretchr/testify/assert" ) func TestMin(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { x int y int expected int @@ -22,7 +24,13 @@ func TestMin(t *testing.T) { {1, 1, 1}, } - for _, testCase := range testCases { - assert.Equal(t, testCase.expected, Min(testCase.x, testCase.y)) + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + + assert.Equal(t, tt.expected, util.Min(tt.x, tt.y)) + }) } } diff --git a/util/prefix-writer_test.go b/util/prefix-writer_test.go index 51bcf3685..aa4ad91b8 100644 --- a/util/prefix-writer_test.go +++ b/util/prefix-writer_test.go @@ -1,10 +1,12 @@ -package util +package util_test import ( "bytes" "errors" + "strconv" "testing" + "github.com/gruntwork-io/terragrunt/util" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -12,7 +14,7 @@ import ( func TestPrefixWriter(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { prefix string values []string expected string @@ -40,15 +42,21 @@ func TestPrefixWriter(t *testing.T) { {"p1\n", []string{"\n"}, "p1\n\n"}, } - for _, testCase := range testCases { - var b bytes.Buffer - pw := PrefixedWriter(&b, testCase.prefix) - for _, input := range testCase.values { - written, err := pw.Write([]byte(input)) - require.NoError(t, err) - assert.Len(t, input, written) - } - assert.Equal(t, testCase.expected, b.String()) + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + + var b bytes.Buffer + pw := util.PrefixedWriter(&b, tt.prefix) + for _, input := range tt.values { + written, err := pw.Write([]byte(input)) + require.NoError(t, err) + assert.Len(t, input, written) + } + assert.Equal(t, tt.expected, b.String()) + }) } } @@ -61,7 +69,7 @@ func (fw *FailingWriter) Write(b []byte) (int, error) { func TestPrefixWriterFail(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { prefix string values []string expected string @@ -69,12 +77,18 @@ func TestPrefixWriterFail(t *testing.T) { {"p1 ", []string{"a", "b"}, "p1 ab"}, } - for _, testCase := range testCases { - pw := PrefixedWriter(&FailingWriter{}, testCase.prefix) - for _, input := range testCase.values { - written, err := pw.Write([]byte(input)) - require.Error(t, err) - assert.Empty(t, written) - } + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + + pw := util.PrefixedWriter(&FailingWriter{}, tt.prefix) + for _, input := range tt.values { + written, err := pw.Write([]byte(input)) + require.Error(t, err) + assert.Empty(t, written) + } + }) } } diff --git a/util/random_test.go b/util/random_test.go index 71fb4c844..854329e4b 100644 --- a/util/random_test.go +++ b/util/random_test.go @@ -1,14 +1,17 @@ -package util +package util_test import ( + "strconv" "testing" "time" + + "github.com/gruntwork-io/terragrunt/util" ) func TestGetRandomTime(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { lowerBound time.Duration upperBound time.Duration }{ @@ -21,20 +24,30 @@ func TestGetRandomTime(t *testing.T) { } // Loop through each test case - for _, testCase := range testCases { - // Try each test case 100 times to avoid fluke test results - for i := 0; i < 100; i++ { - actual := GetRandomTime(testCase.lowerBound, testCase.upperBound) - - if testCase.lowerBound > 0 && testCase.upperBound > 0 { - if actual < testCase.lowerBound { - t.Fatalf("Randomly computed time %v should not be less than lowerBound %v", actual, testCase.lowerBound) - } - - if actual > testCase.upperBound { - t.Fatalf("Randomly computed time %v should not be greater than upperBound %v", actual, testCase.upperBound) - } + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + + // Try each test case 100 times to avoid fluke test results + for j := 0; j < 100; j++ { + t.Run(strconv.Itoa(j), func(t *testing.T) { + t.Parallel() + + actual := util.GetRandomTime(tt.lowerBound, tt.upperBound) + + if tt.lowerBound > 0 && tt.upperBound > 0 { + if actual < tt.lowerBound { + t.Fatalf("Randomly computed time %v should not be less than lowerBound %v", actual, tt.lowerBound) + } + + if actual > tt.upperBound { + t.Fatalf("Randomly computed time %v should not be greater than upperBound %v", actual, tt.upperBound) + } + } + }) } - } + }) } } diff --git a/util/reflect_test.go b/util/reflect_test.go index b5caea8b5..11239faa6 100644 --- a/util/reflect_test.go +++ b/util/reflect_test.go @@ -1,17 +1,19 @@ -package util +package util_test import ( "math" "reflect" + "strconv" "testing" + "github.com/gruntwork-io/terragrunt/util" "github.com/stretchr/testify/assert" ) func TestKindOf(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { value interface{} expected reflect.Kind }{ @@ -26,17 +28,23 @@ func TestKindOf(t *testing.T) { {"", reflect.String}, {interface{}(false), reflect.Bool}, } - for _, testCase := range testCases { - actual := KindOf(testCase.value).String() - assert.Equal(t, testCase.expected.String(), actual, "For value %v", testCase.value) - t.Logf("%v passed", testCase.value) + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + + actual := util.KindOf(tt.value).String() + assert.Equal(t, tt.expected.String(), actual, "For value %v", tt.value) + t.Logf("%v passed", tt.value) + }) } } func TestMustWalkTerraformOutput(t *testing.T) { t.Parallel() - testCases := []struct { + tc := []struct { value interface{} path []string expected interface{} @@ -71,8 +79,14 @@ func TestMustWalkTerraformOutput(t *testing.T) { }, } - for _, testCase := range testCases { - actual := MustWalkTerraformOutput(testCase.value, testCase.path...) - assert.Equal(t, testCase.expected, actual) + for i, tt := range tc { + tt := tt + + t.Run(strconv.Itoa(i), func(t *testing.T) { + t.Parallel() + + actual := util.MustWalkTerraformOutput(tt.value, tt.path...) + assert.Equal(t, tt.expected, actual) + }) } } diff --git a/util/shell_test.go b/util/shell_test.go index 7b1c342b1..c8db73ed4 100644 --- a/util/shell_test.go +++ b/util/shell_test.go @@ -1,19 +1,20 @@ -package util +package util_test import ( "testing" + "github.com/gruntwork-io/terragrunt/util" "github.com/stretchr/testify/assert" ) func TestExistingCommand(t *testing.T) { t.Parallel() - assert.True(t, IsCommandExecutable("pwd")) + assert.True(t, util.IsCommandExecutable("pwd")) } func TestNotExistingCommand(t *testing.T) { t.Parallel() - assert.False(t, IsCommandExecutable("not-existing-command", "--version")) + assert.False(t, util.IsCommandExecutable("not-existing-command", "--version")) }