diff --git a/go.mod b/go.mod index eec4b65f..52f6cbc5 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/gruntwork-io/terratest v0.40.18 - github.com/hashicorp/terraform-plugin-sdk/v2 v2.23.0 + github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0 github.com/lacework/go-sdk v0.44.1 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.8.0 diff --git a/go.sum b/go.sum index 2db5698d..7f064229 100644 --- a/go.sum +++ b/go.sum @@ -239,8 +239,8 @@ github.com/hashicorp/terraform-plugin-go v0.14.0 h1:ttnSlS8bz3ZPYbMb84DpcPhY4F5D github.com/hashicorp/terraform-plugin-go v0.14.0/go.mod h1:2nNCBeRLaenyQEi78xrGrs9hMbulveqG/zDMQSvVJTE= github.com/hashicorp/terraform-plugin-log v0.7.0 h1:SDxJUyT8TwN4l5b5/VkiTIaQgY6R+Y2BQ0sRZftGKQs= github.com/hashicorp/terraform-plugin-log v0.7.0/go.mod h1:p4R1jWBXRTvL4odmEkFfDdhUjHf9zcs/BCoNHAc7IK4= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.23.0 h1:D4EeQm0piYXIHp6ZH3zjyP2Elq6voC64x3GZptaiefA= -github.com/hashicorp/terraform-plugin-sdk/v2 v2.23.0/go.mod h1:xkJGavPvP9kYS/VbiW8o7JuTNgPwm7Tiw/Ie/b46r4c= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0 h1:FtCLTiTcykdsURXPt/ku7fYXm3y19nbzbZcUxHx9RbI= +github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0/go.mod h1:80wf5oad1tW+oLnbXS4UTYmDCrl7BuN1Q+IA91X1a4Y= github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c h1:D8aRO6+mTqHfLsK/BC3j5OAoogv1WLRWzY1AaTo3rBg= github.com/hashicorp/terraform-registry-address v0.0.0-20220623143253-7d51757b572c/go.mod h1:Wn3Na71knbXc1G8Lh+yu/dQWWJeFQEpDeJMtWMtlmNI= github.com/hashicorp/terraform-svchost v0.0.0-20200729002733-f050f53b9734 h1:HKLsbzeOsfXmKNpr3GiT18XAblV0BjCbzL8KQAMZGa0= diff --git a/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/LICENSE b/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/LICENSE index c33dcc7c..fba4c76f 100644 --- a/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/LICENSE +++ b/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/LICENSE @@ -1,3 +1,5 @@ +Copyright (c) 2019 HashiCorp, Inc. + Mozilla Public License, version 2.0 1. Definitions diff --git a/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource/testing.go b/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource/testing.go index e509586e..c77f0629 100644 --- a/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource/testing.go +++ b/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource/testing.go @@ -570,6 +570,22 @@ type TestStep struct { // at the end of the test step that is verifying import behavior. ImportStatePersist bool + //--------------------------------------------------------------- + // RefreshState testing + //--------------------------------------------------------------- + + // RefreshState, if true, will test the functionality of `terraform + // refresh` by refreshing the state, running any checks against the + // refreshed state, and running a plan to verify against unexpected plan + // differences. + // + // If the refresh is expected to result in a non-empty plan + // ExpectNonEmptyPlan should be set to true in the same TestStep. + // + // RefreshState cannot be the first TestStep and, it is mutually exclusive + // with ImportState. + RefreshState bool + // ProviderFactories can be specified for the providers that are valid for // this TestStep. When providers are specified at the TestStep level, all // TestStep within a TestCase must declare providers. diff --git a/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource/testing_new.go b/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource/testing_new.go index 81fc5965..6fa78c23 100644 --- a/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource/testing_new.go +++ b/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource/testing_new.go @@ -114,7 +114,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest logging.HelperResourceDebug(ctx, "Starting TestSteps") - // use this to track last step succesfully applied + // use this to track last step successfully applied // acts as default for import tests var appliedCfg string @@ -241,6 +241,45 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest continue } + if step.RefreshState { + logging.HelperResourceTrace(ctx, "TestStep is RefreshState mode") + + err := testStepNewRefreshState(ctx, t, wd, step, providers) + if step.ExpectError != nil { + logging.HelperResourceDebug(ctx, "Checking TestStep ExpectError") + if err == nil { + logging.HelperResourceError(ctx, + "Error running refresh: expected an error but got none", + ) + t.Fatalf("Step %d/%d error running refresh: expected an error but got none", stepNumber, len(c.Steps)) + } + if !step.ExpectError.MatchString(err.Error()) { + logging.HelperResourceError(ctx, + fmt.Sprintf("Error running refresh: expected an error with pattern (%s)", step.ExpectError.String()), + map[string]interface{}{logging.KeyError: err}, + ) + t.Fatalf("Step %d/%d error running refresh, expected an error with pattern (%s), no match on: %s", stepNumber, len(c.Steps), step.ExpectError.String(), err) + } + } else { + if err != nil && c.ErrorCheck != nil { + logging.HelperResourceDebug(ctx, "Calling TestCase ErrorCheck") + err = c.ErrorCheck(err) + logging.HelperResourceDebug(ctx, "Called TestCase ErrorCheck") + } + if err != nil { + logging.HelperResourceError(ctx, + "Error running refresh", + map[string]interface{}{logging.KeyError: err}, + ) + t.Fatalf("Step %d/%d error running refresh: %s", stepNumber, len(c.Steps), err) + } + } + + logging.HelperResourceDebug(ctx, "Finished TestStep") + + continue + } + if step.Config != "" { logging.HelperResourceTrace(ctx, "TestStep is Config mode") diff --git a/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource/testing_new_import_state.go b/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource/testing_new_import_state.go index fc4ebc9c..17b4c2ad 100644 --- a/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource/testing_new_import_state.go +++ b/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource/testing_new_import_state.go @@ -158,20 +158,27 @@ func testStepNewImportState(ctx context.Context, t testing.T, helper *plugintest if step.ImportStateVerify { logging.HelperResourceTrace(ctx, "Using TestStep ImportStateVerify") - newResources := importState.RootModule().Resources - oldResources := state.RootModule().Resources + // Ensure that we do not match against data sources as they + // cannot be imported and are not what we want to verify. + // Mode is not present in ResourceState so we use the + // stringified ResourceStateKey for comparison. + newResources := make(map[string]*terraform.ResourceState) + for k, v := range importState.RootModule().Resources { + if !strings.HasPrefix(k, "data.") { + newResources[k] = v + } + } + oldResources := make(map[string]*terraform.ResourceState) + for k, v := range state.RootModule().Resources { + if !strings.HasPrefix(k, "data.") { + oldResources[k] = v + } + } for _, r := range newResources { // Find the existing resource var oldR *terraform.ResourceState - for r2Key, r2 := range oldResources { - // Ensure that we do not match against data sources as they - // cannot be imported and are not what we want to verify. - // Mode is not present in ResourceState so we use the - // stringified ResourceStateKey for comparison. - if strings.HasPrefix(r2Key, "data.") { - continue - } + for _, r2 := range oldResources { if r2.Primary != nil && r2.Primary.ID == r.Primary.ID && r2.Type == r.Type && r2.Provider == r.Provider { oldR = r2 diff --git a/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource/testing_new_refresh_state.go b/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource/testing_new_refresh_state.go new file mode 100644 index 00000000..16112934 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource/testing_new_refresh_state.go @@ -0,0 +1,97 @@ +package resource + +import ( + "context" + "fmt" + + "github.com/davecgh/go-spew/spew" + tfjson "github.com/hashicorp/terraform-json" + "github.com/mitchellh/go-testing-interface" + + "github.com/hashicorp/terraform-plugin-sdk/v2/internal/logging" + "github.com/hashicorp/terraform-plugin-sdk/v2/internal/plugintest" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" +) + +func testStepNewRefreshState(ctx context.Context, t testing.T, wd *plugintest.WorkingDir, step TestStep, providers *providerFactories) error { + t.Helper() + + spewConf := spew.NewDefaultConfig() + spewConf.SortKeys = true + + var err error + // Explicitly ensure prior state exists before refresh. + err = runProviderCommand(ctx, t, func() error { + _, err = getState(ctx, t, wd) + if err != nil { + return err + } + return nil + }, wd, providers) + if err != nil { + t.Fatalf("Error getting state: %s", err) + } + + err = runProviderCommand(ctx, t, func() error { + return wd.Refresh(ctx) + }, wd, providers) + if err != nil { + return err + } + + var refreshState *terraform.State + err = runProviderCommand(ctx, t, func() error { + refreshState, err = getState(ctx, t, wd) + if err != nil { + return err + } + return nil + }, wd, providers) + if err != nil { + t.Fatalf("Error getting state: %s", err) + } + + // Go through the refreshed state and verify + if step.Check != nil { + logging.HelperResourceDebug(ctx, "Calling TestStep Check for RefreshState") + + if err := step.Check(refreshState); err != nil { + t.Fatal(err) + } + + logging.HelperResourceDebug(ctx, "Called TestStep Check for RefreshState") + } + + // do a plan + err = runProviderCommand(ctx, t, func() error { + return wd.CreatePlan(ctx) + }, wd, providers) + if err != nil { + return fmt.Errorf("Error running post-apply plan: %w", err) + } + + var plan *tfjson.Plan + err = runProviderCommand(ctx, t, func() error { + var err error + plan, err = wd.SavedPlan(ctx) + return err + }, wd, providers) + if err != nil { + return fmt.Errorf("Error retrieving post-apply plan: %w", err) + } + + if !planIsEmpty(plan) && !step.ExpectNonEmptyPlan { + var stdout string + err = runProviderCommand(ctx, t, func() error { + var err error + stdout, err = wd.SavedPlanRawStdout(ctx) + return err + }, wd, providers) + if err != nil { + return fmt.Errorf("Error retrieving formatted plan output: %w", err) + } + return fmt.Errorf("After refreshing state during this test step, a followup plan was not empty.\nstdout:\n\n%s", stdout) + } + + return nil +} diff --git a/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource/teststep_validate.go b/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource/teststep_validate.go index 95b36e7b..0ba65516 100644 --- a/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource/teststep_validate.go +++ b/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource/teststep_validate.go @@ -43,7 +43,10 @@ func (s TestStep) hasProviders(_ context.Context) bool { // validate ensures the TestStep is valid based on the following criteria: // -// - Config or ImportState is set. +// - Config or ImportState or RefreshState is set. +// - Config and RefreshState are not both set. +// - RefreshState and Destroy are not both set. +// - RefreshState is not the first TestStep. // - Providers are not specified (ExternalProviders, // ProtoV5ProviderFactories, ProtoV6ProviderFactories, ProviderFactories) // if specified at the TestCase level. @@ -58,8 +61,32 @@ func (s TestStep) validate(ctx context.Context, req testStepValidateRequest) err logging.HelperResourceTrace(ctx, "Validating TestStep") - if s.Config == "" && !s.ImportState { - err := fmt.Errorf("TestStep missing Config or ImportState") + if s.Config == "" && !s.ImportState && !s.RefreshState { + err := fmt.Errorf("TestStep missing Config or ImportState or RefreshState") + logging.HelperResourceError(ctx, "TestStep validation error", map[string]interface{}{logging.KeyError: err}) + return err + } + + if s.Config != "" && s.RefreshState { + err := fmt.Errorf("TestStep cannot have Config and RefreshState") + logging.HelperResourceError(ctx, "TestStep validation error", map[string]interface{}{logging.KeyError: err}) + return err + } + + if s.RefreshState && s.Destroy { + err := fmt.Errorf("TestStep cannot have RefreshState and Destroy") + logging.HelperResourceError(ctx, "TestStep validation error", map[string]interface{}{logging.KeyError: err}) + return err + } + + if s.RefreshState && req.StepNumber == 1 { + err := fmt.Errorf("TestStep cannot have RefreshState as first step") + logging.HelperResourceError(ctx, "TestStep validation error", map[string]interface{}{logging.KeyError: err}) + return err + } + + if s.ImportState && s.RefreshState { + err := fmt.Errorf("TestStep cannot have ImportState and RefreshState in same step") logging.HelperResourceError(ctx, "TestStep validation error", map[string]interface{}{logging.KeyError: err}) return err } diff --git a/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema/schema.go b/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema/schema.go index 5b398fd1..4a3e146b 100644 --- a/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema/schema.go +++ b/vendor/github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema/schema.go @@ -1093,9 +1093,10 @@ func checkKeysAgainstSchemaFlags(k string, keys []string, topSchemaMap schemaMap return nil } +var validFieldNameRe = regexp.MustCompile("^[a-z0-9_]+$") + func isValidFieldName(name string) bool { - re := regexp.MustCompile("^[a-z0-9_]+$") - return re.MatchString(name) + return validFieldNameRe.MatchString(name) } // resourceDiffer is an interface that is used by the private diff functions. diff --git a/vendor/modules.txt b/vendor/modules.txt index 44c4dd5b..e49a4640 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -216,7 +216,7 @@ github.com/hashicorp/terraform-plugin-log/internal/hclogutils github.com/hashicorp/terraform-plugin-log/internal/logging github.com/hashicorp/terraform-plugin-log/tflog github.com/hashicorp/terraform-plugin-log/tfsdklog -# github.com/hashicorp/terraform-plugin-sdk/v2 v2.23.0 +# github.com/hashicorp/terraform-plugin-sdk/v2 v2.24.0 ## explicit; go 1.18 github.com/hashicorp/terraform-plugin-sdk/v2/diag github.com/hashicorp/terraform-plugin-sdk/v2/helper/logging