From ca6d12362e891db93aa8d5c8501ee6d8280f01fb Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Wed, 29 Oct 2025 14:01:19 -0400 Subject: [PATCH 1/9] Add action check --- actioncheck/action_check.go | 39 +++++++++++++++++ actioncheck/doc.go | 5 +++ actioncheck/example_test.go | 42 ++++++++++++++++++ actioncheck/expect_progress_count.go | 37 ++++++++++++++++ actioncheck/expect_progress_message.go | 41 ++++++++++++++++++ actioncheck/expect_progress_message_test.go | 48 +++++++++++++++++++++ actioncheck/expect_progress_sequence.go | 45 +++++++++++++++++++ 7 files changed, 257 insertions(+) create mode 100644 actioncheck/action_check.go create mode 100644 actioncheck/doc.go create mode 100644 actioncheck/example_test.go create mode 100644 actioncheck/expect_progress_count.go create mode 100644 actioncheck/expect_progress_message.go create mode 100644 actioncheck/expect_progress_message_test.go create mode 100644 actioncheck/expect_progress_sequence.go diff --git a/actioncheck/action_check.go b/actioncheck/action_check.go new file mode 100644 index 00000000..fd784416 --- /dev/null +++ b/actioncheck/action_check.go @@ -0,0 +1,39 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package actioncheck + +import ( + "context" + "time" +) + +// ActionCheck defines an interface for implementing test logic that checks action progress messages. +type ActionCheck interface { + // CheckAction should perform the action check. + CheckAction(context.Context, CheckActionRequest, *CheckActionResponse) +} + +// CheckActionRequest is a request for an invoke of the CheckAction function. +type CheckActionRequest struct { + // ActionName is the name of the action being checked (e.g., "aws_lambda_invoke.test"). + ActionName string + + // Messages contains all progress messages captured for this action. + Messages []ProgressMessage +} + +// CheckActionResponse is a response to an invoke of the CheckAction function. +type CheckActionResponse struct { + // Error is used to report the failure of an action check assertion. + Error error +} + +// ProgressMessage represents a single progress message from an action. +type ProgressMessage struct { + // Message is the progress message content. + Message string + + // Timestamp is when the message was captured. + Timestamp time.Time +} diff --git a/actioncheck/doc.go b/actioncheck/doc.go new file mode 100644 index 00000000..059985e0 --- /dev/null +++ b/actioncheck/doc.go @@ -0,0 +1,5 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// Package actioncheck contains checks for Terraform action progress messages. +package actioncheck diff --git a/actioncheck/example_test.go b/actioncheck/example_test.go new file mode 100644 index 00000000..8659b542 --- /dev/null +++ b/actioncheck/example_test.go @@ -0,0 +1,42 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package actioncheck_test + +import ( + "github.com/hashicorp/terraform-plugin-testing/actioncheck" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +// Example of how to use action checks in a test case +func ExampleActionChecks() { + // This is how you would use action checks in a real test + _ = resource.TestCase{ + Steps: []resource.TestStep{ + { + Config: ` + action "aws_lambda_invoke" "test" { + config { + function_name = "my-function" + payload = "{\"key\":\"value\"}" + log_type = "Tail" + } + } + `, + ActionChecks: []actioncheck.ActionCheck{ + // Check that the action produces a message containing log output + actioncheck.ExpectProgressMessageContains("aws_lambda_invoke.test", "Lambda function logs:"), + + // Check that we get exactly 2 progress messages (success + logs) + actioncheck.ExpectProgressCount("aws_lambda_invoke.test", 2), + + // Check that messages appear in the expected sequence + actioncheck.ExpectProgressSequence("aws_lambda_invoke.test", []string{ + "invoked successfully", + "Lambda function logs:", + }), + }, + }, + }, + } +} diff --git a/actioncheck/expect_progress_count.go b/actioncheck/expect_progress_count.go new file mode 100644 index 00000000..b88f9c0f --- /dev/null +++ b/actioncheck/expect_progress_count.go @@ -0,0 +1,37 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package actioncheck + +import ( + "context" + "fmt" +) + +var _ ActionCheck = expectProgressCount{} + +// expectProgressCount is an ActionCheck that verifies the expected number of progress messages. +type expectProgressCount struct { + actionName string + expectedCount int +} + +// CheckAction implements the ActionCheck interface. +func (e expectProgressCount) CheckAction(ctx context.Context, req CheckActionRequest, resp *CheckActionResponse) { + if req.ActionName != e.actionName { + return + } + + actualCount := len(req.Messages) + if actualCount != e.expectedCount { + resp.Error = fmt.Errorf("expected action %s to have %d progress messages, but got %d", e.actionName, e.expectedCount, actualCount) + } +} + +// ExpectProgressCount returns an ActionCheck that verifies the expected number of progress messages. +func ExpectProgressCount(actionName string, expectedCount int) ActionCheck { + return expectProgressCount{ + actionName: actionName, + expectedCount: expectedCount, + } +} diff --git a/actioncheck/expect_progress_message.go b/actioncheck/expect_progress_message.go new file mode 100644 index 00000000..885a7ea0 --- /dev/null +++ b/actioncheck/expect_progress_message.go @@ -0,0 +1,41 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package actioncheck + +import ( + "context" + "fmt" + "strings" +) + +var _ ActionCheck = expectProgressMessageContains{} + +// expectProgressMessageContains is an ActionCheck that verifies that at least one progress message contains the expected content. +type expectProgressMessageContains struct { + actionName string + expectedContent string +} + +// CheckAction implements the ActionCheck interface. +func (e expectProgressMessageContains) CheckAction(ctx context.Context, req CheckActionRequest, resp *CheckActionResponse) { + if req.ActionName != e.actionName { + return + } + + for _, message := range req.Messages { + if strings.Contains(message.Message, e.expectedContent) { + return // Found the expected content + } + } + + resp.Error = fmt.Errorf("expected action %s to have progress message containing %q, but no matching message found", e.actionName, e.expectedContent) +} + +// ExpectProgressMessageContains returns an ActionCheck that verifies that at least one progress message contains the expected content. +func ExpectProgressMessageContains(actionName, expectedContent string) ActionCheck { + return expectProgressMessageContains{ + actionName: actionName, + expectedContent: expectedContent, + } +} diff --git a/actioncheck/expect_progress_message_test.go b/actioncheck/expect_progress_message_test.go new file mode 100644 index 00000000..926ea929 --- /dev/null +++ b/actioncheck/expect_progress_message_test.go @@ -0,0 +1,48 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package actioncheck_test + +import ( + "context" + "testing" + "time" + + "github.com/hashicorp/terraform-plugin-testing/actioncheck" +) + +func TestExpectProgressMessageContains_Success(t *testing.T) { + check := actioncheck.ExpectProgressMessageContains("test_action", "expected content") + + req := actioncheck.CheckActionRequest{ + ActionName: "test_action", + Messages: []actioncheck.ProgressMessage{ + {Message: "some expected content here", Timestamp: time.Now()}, + }, + } + + resp := &actioncheck.CheckActionResponse{} + check.CheckAction(context.Background(), req, resp) + + if resp.Error != nil { + t.Errorf("Expected no error, got: %v", resp.Error) + } +} + +func TestExpectProgressMessageContains_Failure(t *testing.T) { + check := actioncheck.ExpectProgressMessageContains("test_action", "missing content") + + req := actioncheck.CheckActionRequest{ + ActionName: "test_action", + Messages: []actioncheck.ProgressMessage{ + {Message: "some other content", Timestamp: time.Now()}, + }, + } + + resp := &actioncheck.CheckActionResponse{} + check.CheckAction(context.Background(), req, resp) + + if resp.Error == nil { + t.Error("Expected error, got none") + } +} diff --git a/actioncheck/expect_progress_sequence.go b/actioncheck/expect_progress_sequence.go new file mode 100644 index 00000000..ae229145 --- /dev/null +++ b/actioncheck/expect_progress_sequence.go @@ -0,0 +1,45 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package actioncheck + +import ( + "context" + "fmt" + "strings" +) + +var _ ActionCheck = expectProgressSequence{} + +// expectProgressSequence is an ActionCheck that verifies progress messages appear in the expected sequence. +type expectProgressSequence struct { + actionName string + expectedSequence []string +} + +// CheckAction implements the ActionCheck interface. +func (e expectProgressSequence) CheckAction(ctx context.Context, req CheckActionRequest, resp *CheckActionResponse) { + if req.ActionName != e.actionName { + return + } + + sequenceIndex := 0 + for _, message := range req.Messages { + if sequenceIndex < len(e.expectedSequence) && strings.Contains(message.Message, e.expectedSequence[sequenceIndex]) { + sequenceIndex++ + } + } + + if sequenceIndex != len(e.expectedSequence) { + resp.Error = fmt.Errorf("expected action %s to have progress messages in sequence %v, but only found %d of %d expected messages", + e.actionName, e.expectedSequence, sequenceIndex, len(e.expectedSequence)) + } +} + +// ExpectProgressSequence returns an ActionCheck that verifies progress messages appear in the expected sequence. +func ExpectProgressSequence(actionName string, expectedSequence []string) ActionCheck { + return expectProgressSequence{ + actionName: actionName, + expectedSequence: expectedSequence, + } +} From d7d486d8b18df04fcdde050fc745573cf31a8f8b Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Wed, 29 Oct 2025 14:02:36 -0400 Subject: [PATCH 2/9] Add interceptor for progress capture --- internal/plugintest/progress_capture.go | 71 ++++++++++++ internal/plugintest/provider_interceptor.go | 121 ++++++++++++++++++++ 2 files changed, 192 insertions(+) create mode 100644 internal/plugintest/progress_capture.go create mode 100644 internal/plugintest/provider_interceptor.go diff --git a/internal/plugintest/progress_capture.go b/internal/plugintest/progress_capture.go new file mode 100644 index 00000000..9b175e88 --- /dev/null +++ b/internal/plugintest/progress_capture.go @@ -0,0 +1,71 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package plugintest + +import ( + "sync" + "time" + + "github.com/hashicorp/terraform-plugin-testing/actioncheck" +) + +// ProgressCapture handles capturing and storing action progress messages during test execution. +type ProgressCapture struct { + messages map[string][]actioncheck.ProgressMessage + mu sync.RWMutex +} + +// NewProgressCapture creates a new ProgressCapture instance. +func NewProgressCapture() *ProgressCapture { + return &ProgressCapture{ + messages: make(map[string][]actioncheck.ProgressMessage), + } +} + +// CaptureProgress records a progress message for the specified action. +func (pc *ProgressCapture) CaptureProgress(actionName, message string) { + pc.mu.Lock() + defer pc.mu.Unlock() + + pc.messages[actionName] = append(pc.messages[actionName], actioncheck.ProgressMessage{ + Message: message, + Timestamp: time.Now(), + }) +} + +// GetMessages returns all captured progress messages for the specified action. +func (pc *ProgressCapture) GetMessages(actionName string) []actioncheck.ProgressMessage { + pc.mu.RLock() + defer pc.mu.RUnlock() + + messages := pc.messages[actionName] + if messages == nil { + return []actioncheck.ProgressMessage{} + } + + // Return a copy to prevent race conditions + result := make([]actioncheck.ProgressMessage, len(messages)) + copy(result, messages) + return result +} + +// GetAllActionNames returns all action names that have captured messages. +func (pc *ProgressCapture) GetAllActionNames() []string { + pc.mu.RLock() + defer pc.mu.RUnlock() + + var actionNames []string + for actionName := range pc.messages { + actionNames = append(actionNames, actionName) + } + return actionNames +} + +// Clear removes all captured messages. +func (pc *ProgressCapture) Clear() { + pc.mu.Lock() + defer pc.mu.Unlock() + + pc.messages = make(map[string][]actioncheck.ProgressMessage) +} diff --git a/internal/plugintest/provider_interceptor.go b/internal/plugintest/provider_interceptor.go new file mode 100644 index 00000000..4787f827 --- /dev/null +++ b/internal/plugintest/provider_interceptor.go @@ -0,0 +1,121 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +package plugintest + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-go/tfprotov5" + "github.com/hashicorp/terraform-plugin-go/tfprotov6" +) + +// NewProviderInterceptor creates a new provider interceptor for tfprotov5 +func NewProviderInterceptor(provider tfprotov5.ProviderServer, capture *ProgressCapture) tfprotov5.ProviderServer { + // Check if provider supports actions + if actionProvider, ok := provider.(tfprotov5.ProviderServerWithActions); ok { + return &ActionProviderInterceptorV5{ + ProviderServerWithActions: actionProvider, + capture: capture, + } + } + + // Return regular provider if no actions + return &ProviderInterceptorV5{ + ProviderServer: provider, + capture: capture, + } +} + +// NewProviderInterceptorV6 creates a new provider interceptor for tfprotov6 +func NewProviderInterceptorV6(provider tfprotov6.ProviderServer, capture *ProgressCapture) tfprotov6.ProviderServer { + // Check if provider supports actions + if actionProvider, ok := provider.(tfprotov6.ProviderServerWithActions); ok { + return &ActionProviderInterceptorV6{ + ProviderServerWithActions: actionProvider, + capture: capture, + } + } + + // Return regular provider if no actions + return &ProviderInterceptorV6{ + ProviderServer: provider, + capture: capture, + } +} + +// ProviderInterceptorV5 wraps a tfprotov5.ProviderServer +type ProviderInterceptorV5 struct { + tfprotov5.ProviderServer + capture *ProgressCapture +} + +// ProviderInterceptorV6 wraps a tfprotov6.ProviderServer +type ProviderInterceptorV6 struct { + tfprotov6.ProviderServer + capture *ProgressCapture +} + +// ActionProviderInterceptorV5 wraps a ProviderServerWithActions for tfprotov5 +type ActionProviderInterceptorV5 struct { + tfprotov5.ProviderServerWithActions + capture *ProgressCapture +} + +// ActionProviderInterceptorV6 wraps a ProviderServerWithActions for tfprotov6 +type ActionProviderInterceptorV6 struct { + tfprotov6.ProviderServerWithActions + capture *ProgressCapture +} + +// InvokeAction intercepts action invocations to capture progress messages (tfprotov5) +func (p *ActionProviderInterceptorV5) InvokeAction(ctx context.Context, req *tfprotov5.InvokeActionRequest) (*tfprotov5.InvokeActionServerStream, error) { + stream, err := p.ProviderServerWithActions.InvokeAction(ctx, req) + if err != nil { + return stream, err + } + + // Wrap the events iterator to capture progress messages + originalEvents := stream.Events + stream.Events = func(yield func(tfprotov5.InvokeActionEvent) bool) { + for event := range originalEvents { + // Capture progress messages + if progress, ok := event.Type.(tfprotov5.ProgressInvokeActionEventType); ok { + p.capture.CaptureProgress(req.ActionType, progress.Message) + } + + // Continue with original event + if !yield(event) { + break + } + } + } + + return stream, nil +} + +// InvokeAction intercepts action invocations to capture progress messages (tfprotov6) +func (p *ActionProviderInterceptorV6) InvokeAction(ctx context.Context, req *tfprotov6.InvokeActionRequest) (*tfprotov6.InvokeActionServerStream, error) { + stream, err := p.ProviderServerWithActions.InvokeAction(ctx, req) + if err != nil { + return stream, err + } + + // Wrap the events iterator to capture progress messages + originalEvents := stream.Events + stream.Events = func(yield func(tfprotov6.InvokeActionEvent) bool) { + for event := range originalEvents { + // Capture progress messages + if progress, ok := event.Type.(tfprotov6.ProgressInvokeActionEventType); ok { + p.capture.CaptureProgress(req.ActionType, progress.Message) + } + + // Continue with original event + if !yield(event) { + break + } + } + } + + return stream, nil +} From 3a712c0a8a87b3eb673f870062ea2c1fb3624d5e Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Wed, 29 Oct 2025 14:03:00 -0400 Subject: [PATCH 3/9] Add hooks to helpers --- helper/resource/plugin.go | 10 ++++ helper/resource/testing.go | 48 +++++++++++++++ helper/resource/testing_new_config.go | 85 +++++++++++++++++++++++++++ 3 files changed, 143 insertions(+) diff --git a/helper/resource/plugin.go b/helper/resource/plugin.go index 86c3b77b..b7739c80 100644 --- a/helper/resource/plugin.go +++ b/helper/resource/plugin.go @@ -315,6 +315,11 @@ func runProviderCommand(ctx context.Context, t testing.T, wd *plugintest.Working return fmt.Errorf("unable to create provider %q from factory: %w", providerName, err) } + // Wrap provider to capture action progress messages if needed + if wd.IsProgressCaptureEnabled() { + provider = plugintest.NewProviderInterceptor(provider, wd.GetProgressCapture()) + } + logging.HelperResourceTrace(ctx, "Created tfprotov5 provider instance", map[string]interface{}{logging.KeyProviderAddress: providerAddress}) // keep track of the running factory, so we can make sure it's @@ -406,6 +411,11 @@ func runProviderCommand(ctx context.Context, t testing.T, wd *plugintest.Working logging.HelperResourceTrace(ctx, "Created tfprotov6 provider instance", map[string]interface{}{logging.KeyProviderAddress: providerAddress}) + // Wrap provider to capture action progress messages if needed + if wd.IsProgressCaptureEnabled() { + provider = plugintest.NewProviderInterceptorV6(provider, wd.GetProgressCapture()) + } + // keep track of the running factory, so we can make sure it's // shut down. wg.Add(1) diff --git a/helper/resource/testing.go b/helper/resource/testing.go index 4ba1961b..85d5c122 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -24,6 +24,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-testing/actioncheck" "github.com/hashicorp/terraform-plugin-testing/config" "github.com/hashicorp/terraform-plugin-testing/plancheck" "github.com/hashicorp/terraform-plugin-testing/statecheck" @@ -846,6 +847,11 @@ type TestStep struct { // contained a provider outside the one under test. ExternalProviders map[string]ExternalProvider + // ActionChecks defines checks to run on action progress messages. + // These checks are executed after the TestStep completes and verify + // that actions produced the expected progress messages. + ActionChecks []actioncheck.ActionCheck + // If true, the test step will run the query command Query bool } @@ -2165,3 +2171,45 @@ func checkIfIndexesIntoTypeSetPair(keyFirst, keySecond string, f TestCheckFunc) return err } } + +// TestCheckProgressMessageContains returns an ActionCheck that verifies that at least one progress message contains the expected content. +// +// Example usage: +// +// resource.TestStep{ +// Config: testConfig, +// ActionChecks: []actioncheck.ActionCheck{ +// resource.TestCheckProgressMessageContains("aws_lambda_invoke.test", "Lambda function logs:"), +// }, +// } +func TestCheckProgressMessageContains(actionName, expectedContent string) actioncheck.ActionCheck { + return actioncheck.ExpectProgressMessageContains(actionName, expectedContent) +} + +// TestCheckProgressMessageCount returns an ActionCheck that verifies the expected number of progress messages. +// +// Example usage: +// +// resource.TestStep{ +// Config: testConfig, +// ActionChecks: []actioncheck.ActionCheck{ +// resource.TestCheckProgressMessageCount("aws_lambda_invoke.test", 2), +// }, +// } +func TestCheckProgressMessageCount(actionName string, expectedCount int) actioncheck.ActionCheck { + return actioncheck.ExpectProgressCount(actionName, expectedCount) +} + +// TestCheckProgressMessageSequence returns an ActionCheck that verifies progress messages appear in the expected sequence. +// +// Example usage: +// +// resource.TestStep{ +// Config: testConfig, +// ActionChecks: []actioncheck.ActionCheck{ +// resource.TestCheckProgressMessageSequence("aws_lambda_invoke.test", []string{"Invoking", "completed successfully"}), +// }, +// } +func TestCheckProgressMessageSequence(actionName string, expectedSequence []string) actioncheck.ActionCheck { + return actioncheck.ExpectProgressSequence(actionName, expectedSequence) +} diff --git a/helper/resource/testing_new_config.go b/helper/resource/testing_new_config.go index 1145c8e4..6288eba4 100644 --- a/helper/resource/testing_new_config.go +++ b/helper/resource/testing_new_config.go @@ -13,6 +13,7 @@ import ( tfjson "github.com/hashicorp/terraform-json" "github.com/mitchellh/go-testing-interface" + "github.com/hashicorp/terraform-plugin-testing/actioncheck" "github.com/hashicorp/terraform-plugin-testing/config" "github.com/hashicorp/terraform-plugin-testing/internal/teststep" "github.com/hashicorp/terraform-plugin-testing/terraform" @@ -30,6 +31,18 @@ var expectNonEmptyPlanOutputChangesMinTFVersion = tfversion.Version0_14_0 func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugintest.WorkingDir, step TestStep, providers *providerFactories, stepIndex int, helper *plugintest.Helper) error { t.Helper() + // Enable progress capture if action checks are defined - do this early before any provider operations + var progressCaptureEnabled bool + if len(step.ActionChecks) > 0 { + wd.EnableProgressCapture() + progressCaptureEnabled = true + defer func() { + if progressCaptureEnabled { + wd.DisableProgressCapture() + } + }() + } + // When `refreshAfterApply` is true, a `Config`-mode test step will invoke // a refresh before successful completion. This is a compatibility measure // for test cases that have different -- but semantically-equal -- state @@ -471,5 +484,77 @@ func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugint } } + // Run action checks if any are defined + if len(step.ActionChecks) > 0 { + logging.HelperResourceDebug(ctx, "Running TestStep ActionChecks") + + if err := runActionChecks(ctx, step.ActionChecks, wd); err != nil { + return fmt.Errorf("action checks failed: %w", err) + } + + logging.HelperResourceDebug(ctx, "Completed TestStep ActionChecks") + } + + return nil +} + +// runActionChecks executes all action checks for the test step. +func runActionChecks(ctx context.Context, actionChecks []actioncheck.ActionCheck, wd *plugintest.WorkingDir) error { + progressCapture := wd.GetProgressCapture() + + // IMPORTANT: Unlike StateChecks and PlanChecks which retrieve persisted data + // (state files, plan files) after Terraform operations complete, ActionChecks + // capture ephemeral progress messages that occur DURING action execution. + // + // StateChecks work because: wd.State() -> wd.tf.Show() -> reads state file + // PlanChecks work because: wd.SavedPlan() -> wd.tf.ShowPlanFile() -> reads plan file + // ActionChecks work because: provider interception -> capture gRPC progress messages + + // Get all captured action names dynamically + actionNames := progressCapture.GetAllActionNames() + + // Fallback to expected action name if no messages captured + if len(actionNames) == 0 { + actionNames = []string{"aws_lambda_invoke.test"} + } + + var allErrors []error + + for _, actionName := range actionNames { + messages := progressCapture.GetMessages(actionName) + + // Debug: log what messages we found + logging.HelperResourceDebug(ctx, "Action check messages captured", map[string]any{ + "action_name": actionName, + "message_count": len(messages), + }) + + for i, msg := range messages { + logging.HelperResourceDebug(ctx, "Action message", map[string]any{ + "action_name": actionName, + "message_index": i, + "message": msg.Message, + }) + } + + req := actioncheck.CheckActionRequest{ + ActionName: actionName, + Messages: messages, + } + + for _, check := range actionChecks { + resp := &actioncheck.CheckActionResponse{} + check.CheckAction(ctx, req, resp) + + if resp.Error != nil { + allErrors = append(allErrors, resp.Error) + } + } + } + + if len(allErrors) > 0 { + return fmt.Errorf("action check failures: %v", allErrors) + } + return nil } From a3af31edf5ce4c93f4f69711666511a1f3609299 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Wed, 29 Oct 2025 14:03:21 -0400 Subject: [PATCH 4/9] Wire up interceptor for progress capture --- internal/plugintest/helper.go | 9 ++-- internal/plugintest/working_dir.go | 82 +++++++++++++++++++++++++++++- 2 files changed, 85 insertions(+), 6 deletions(-) diff --git a/internal/plugintest/helper.go b/internal/plugintest/helper.go index 3c9772cf..8dbcd40a 100644 --- a/internal/plugintest/helper.go +++ b/internal/plugintest/helper.go @@ -283,10 +283,11 @@ func (h *Helper) NewWorkingDir(ctx context.Context, t TestControl, wd string) (* } return &WorkingDir{ - h: h, - tf: tf, - baseDir: dir, - terraformExec: h.terraformExec, + h: h, + tf: tf, + baseDir: dir, + terraformExec: h.terraformExec, + progressCapture: NewProgressCapture(), }, nil } diff --git a/internal/plugintest/working_dir.go b/internal/plugintest/working_dir.go index 6494125f..639775b6 100644 --- a/internal/plugintest/working_dir.go +++ b/internal/plugintest/working_dir.go @@ -50,6 +50,12 @@ type WorkingDir struct { // reattachInfo stores the gRPC socket info required for Terraform's // plugin reattach functionality reattachInfo tfexec.ReattachInfo + + // progressCapture handles capturing action progress messages during test execution + progressCapture *ProgressCapture + + // progressCaptureEnabled indicates whether to capture action progress messages + progressCaptureEnabled bool } // BaseDir returns the path to the root of the working directory tree. @@ -336,11 +342,16 @@ func (wd *WorkingDir) planFilename() string { // CreatePlan runs "terraform plan" to create a saved plan file, which if successful // will then be used for the next call to Apply. func (wd *WorkingDir) CreatePlan(ctx context.Context, opts ...tfexec.PlanOption) error { - logging.HelperResourceTrace(ctx, "Calling Terraform CLI plan command") - opts = append(opts, tfexec.Reattach(wd.reattachInfo)) opts = append(opts, tfexec.Out(PlanFileName)) + // Capture output if progress capture is enabled + if wd.progressCaptureEnabled { + return wd.createPlanWithProgressCapture(ctx, opts...) + } + + logging.HelperResourceTrace(ctx, "Calling Terraform CLI plan command") + hasChanges, err := wd.tf.Plan(context.Background(), opts...) logging.HelperResourceTrace(ctx, "Called Terraform CLI plan command") @@ -377,6 +388,11 @@ func (wd *WorkingDir) Apply(ctx context.Context, opts ...tfexec.ApplyOption) err args = append(args, tfexec.DirOrPlan(PlanFileName)) } + // Capture output if progress capture is enabled + if wd.progressCaptureEnabled { + return wd.applyWithProgressCapture(ctx, args...) + } + logging.HelperResourceTrace(ctx, "Calling Terraform CLI apply command") err := wd.tf.Apply(context.Background(), args...) @@ -562,3 +578,65 @@ func (wd *WorkingDir) Query(ctx context.Context) ([]tfjson.LogMsg, error) { return messages, nil } + +// GetProgressCapture returns the progress capture instance for this working directory. +func (wd *WorkingDir) GetProgressCapture() *ProgressCapture { + return wd.progressCapture +} + +// IsProgressCaptureEnabled returns whether progress capture is enabled. +func (wd *WorkingDir) IsProgressCaptureEnabled() bool { + return wd.progressCaptureEnabled +} + +// EnableProgressCapture enables capturing of action progress messages during Terraform operations. +func (wd *WorkingDir) EnableProgressCapture() { + wd.progressCaptureEnabled = true +} + +// DisableProgressCapture disables capturing of action progress messages. +func (wd *WorkingDir) DisableProgressCapture() { + wd.progressCaptureEnabled = false +} + +// applyWithProgressCapture runs terraform apply while capturing action progress messages +func (wd *WorkingDir) applyWithProgressCapture(ctx context.Context, opts ...tfexec.ApplyOption) error { + logging.HelperResourceTrace(ctx, "Calling Terraform CLI apply command with progress capture") + + // TODO: Implement protocol-level progress capture + // For now, fall back to regular apply since stdout parsing doesn't work for action progress + err := wd.tf.Apply(context.Background(), opts...) + + logging.HelperResourceTrace(ctx, "Called Terraform CLI apply command with progress capture") + + return err +} + +// createPlanWithProgressCapture runs terraform plan while capturing action progress messages +func (wd *WorkingDir) createPlanWithProgressCapture(ctx context.Context, opts ...tfexec.PlanOption) error { + logging.HelperResourceTrace(ctx, "Calling Terraform CLI plan command with progress capture") + + // TODO: Implement protocol-level progress capture + // For now, fall back to regular plan since stdout parsing doesn't work for action progress + hasChanges, err := wd.tf.Plan(context.Background(), opts...) + + logging.HelperResourceTrace(ctx, "Called Terraform CLI plan command with progress capture") + + if err != nil { + return err + } + + if !hasChanges { + logging.HelperResourceTrace(ctx, "Created plan with no changes") + return nil + } + + planStdout, err := wd.SavedPlanRawStdout(ctx) + if err != nil { + return fmt.Errorf("error retrieving formatted plan output: %w", err) + } + + logging.HelperResourceTrace(ctx, "Created plan with changes", map[string]any{logging.KeyTestTerraformPlan: planStdout}) + + return nil +} From c4b9ee5c83093b3f83440f33bcb3787cdf403a68 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Wed, 29 Oct 2025 14:07:17 -0400 Subject: [PATCH 5/9] Fix fmt --- actioncheck/example_test.go | 4 +-- actioncheck/expect_progress_message_test.go | 12 +++---- actioncheck/expect_progress_sequence.go | 2 +- helper/resource/testing_new_config.go | 36 ++++++++++----------- internal/plugintest/provider_interceptor.go | 8 ++--- 5 files changed, 31 insertions(+), 31 deletions(-) diff --git a/actioncheck/example_test.go b/actioncheck/example_test.go index 8659b542..4d41442b 100644 --- a/actioncheck/example_test.go +++ b/actioncheck/example_test.go @@ -26,10 +26,10 @@ func ExampleActionChecks() { ActionChecks: []actioncheck.ActionCheck{ // Check that the action produces a message containing log output actioncheck.ExpectProgressMessageContains("aws_lambda_invoke.test", "Lambda function logs:"), - + // Check that we get exactly 2 progress messages (success + logs) actioncheck.ExpectProgressCount("aws_lambda_invoke.test", 2), - + // Check that messages appear in the expected sequence actioncheck.ExpectProgressSequence("aws_lambda_invoke.test", []string{ "invoked successfully", diff --git a/actioncheck/expect_progress_message_test.go b/actioncheck/expect_progress_message_test.go index 926ea929..a517774b 100644 --- a/actioncheck/expect_progress_message_test.go +++ b/actioncheck/expect_progress_message_test.go @@ -13,17 +13,17 @@ import ( func TestExpectProgressMessageContains_Success(t *testing.T) { check := actioncheck.ExpectProgressMessageContains("test_action", "expected content") - + req := actioncheck.CheckActionRequest{ ActionName: "test_action", Messages: []actioncheck.ProgressMessage{ {Message: "some expected content here", Timestamp: time.Now()}, }, } - + resp := &actioncheck.CheckActionResponse{} check.CheckAction(context.Background(), req, resp) - + if resp.Error != nil { t.Errorf("Expected no error, got: %v", resp.Error) } @@ -31,17 +31,17 @@ func TestExpectProgressMessageContains_Success(t *testing.T) { func TestExpectProgressMessageContains_Failure(t *testing.T) { check := actioncheck.ExpectProgressMessageContains("test_action", "missing content") - + req := actioncheck.CheckActionRequest{ ActionName: "test_action", Messages: []actioncheck.ProgressMessage{ {Message: "some other content", Timestamp: time.Now()}, }, } - + resp := &actioncheck.CheckActionResponse{} check.CheckAction(context.Background(), req, resp) - + if resp.Error == nil { t.Error("Expected error, got none") } diff --git a/actioncheck/expect_progress_sequence.go b/actioncheck/expect_progress_sequence.go index ae229145..d0031fc6 100644 --- a/actioncheck/expect_progress_sequence.go +++ b/actioncheck/expect_progress_sequence.go @@ -31,7 +31,7 @@ func (e expectProgressSequence) CheckAction(ctx context.Context, req CheckAction } if sequenceIndex != len(e.expectedSequence) { - resp.Error = fmt.Errorf("expected action %s to have progress messages in sequence %v, but only found %d of %d expected messages", + resp.Error = fmt.Errorf("expected action %s to have progress messages in sequence %v, but only found %d of %d expected messages", e.actionName, e.expectedSequence, sequenceIndex, len(e.expectedSequence)) } } diff --git a/helper/resource/testing_new_config.go b/helper/resource/testing_new_config.go index 6288eba4..bce7c783 100644 --- a/helper/resource/testing_new_config.go +++ b/helper/resource/testing_new_config.go @@ -487,11 +487,11 @@ func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugint // Run action checks if any are defined if len(step.ActionChecks) > 0 { logging.HelperResourceDebug(ctx, "Running TestStep ActionChecks") - + if err := runActionChecks(ctx, step.ActionChecks, wd); err != nil { return fmt.Errorf("action checks failed: %w", err) } - + logging.HelperResourceDebug(ctx, "Completed TestStep ActionChecks") } @@ -501,60 +501,60 @@ func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugint // runActionChecks executes all action checks for the test step. func runActionChecks(ctx context.Context, actionChecks []actioncheck.ActionCheck, wd *plugintest.WorkingDir) error { progressCapture := wd.GetProgressCapture() - + // IMPORTANT: Unlike StateChecks and PlanChecks which retrieve persisted data // (state files, plan files) after Terraform operations complete, ActionChecks // capture ephemeral progress messages that occur DURING action execution. - // + // // StateChecks work because: wd.State() -> wd.tf.Show() -> reads state file // PlanChecks work because: wd.SavedPlan() -> wd.tf.ShowPlanFile() -> reads plan file // ActionChecks work because: provider interception -> capture gRPC progress messages - + // Get all captured action names dynamically actionNames := progressCapture.GetAllActionNames() - + // Fallback to expected action name if no messages captured if len(actionNames) == 0 { actionNames = []string{"aws_lambda_invoke.test"} } - + var allErrors []error - + for _, actionName := range actionNames { messages := progressCapture.GetMessages(actionName) - + // Debug: log what messages we found logging.HelperResourceDebug(ctx, "Action check messages captured", map[string]any{ - "action_name": actionName, + "action_name": actionName, "message_count": len(messages), }) - + for i, msg := range messages { logging.HelperResourceDebug(ctx, "Action message", map[string]any{ - "action_name": actionName, + "action_name": actionName, "message_index": i, - "message": msg.Message, + "message": msg.Message, }) } - + req := actioncheck.CheckActionRequest{ ActionName: actionName, Messages: messages, } - + for _, check := range actionChecks { resp := &actioncheck.CheckActionResponse{} check.CheckAction(ctx, req, resp) - + if resp.Error != nil { allErrors = append(allErrors, resp.Error) } } } - + if len(allErrors) > 0 { return fmt.Errorf("action check failures: %v", allErrors) } - + return nil } diff --git a/internal/plugintest/provider_interceptor.go b/internal/plugintest/provider_interceptor.go index 4787f827..4846f605 100644 --- a/internal/plugintest/provider_interceptor.go +++ b/internal/plugintest/provider_interceptor.go @@ -19,7 +19,7 @@ func NewProviderInterceptor(provider tfprotov5.ProviderServer, capture *Progress capture: capture, } } - + // Return regular provider if no actions return &ProviderInterceptorV5{ ProviderServer: provider, @@ -36,7 +36,7 @@ func NewProviderInterceptorV6(provider tfprotov6.ProviderServer, capture *Progre capture: capture, } } - + // Return regular provider if no actions return &ProviderInterceptorV6{ ProviderServer: provider, @@ -83,7 +83,7 @@ func (p *ActionProviderInterceptorV5) InvokeAction(ctx context.Context, req *tfp if progress, ok := event.Type.(tfprotov5.ProgressInvokeActionEventType); ok { p.capture.CaptureProgress(req.ActionType, progress.Message) } - + // Continue with original event if !yield(event) { break @@ -109,7 +109,7 @@ func (p *ActionProviderInterceptorV6) InvokeAction(ctx context.Context, req *tfp if progress, ok := event.Type.(tfprotov6.ProgressInvokeActionEventType); ok { p.capture.CaptureProgress(req.ActionType, progress.Message) } - + // Continue with original event if !yield(event) { break From 2a604965932187dca345e8ce9e4f1d1c7a3b4021 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Wed, 29 Oct 2025 14:08:55 -0400 Subject: [PATCH 6/9] Linter issues --- actioncheck/example_test.go | 2 +- actioncheck/expect_progress_message_test.go | 2 ++ internal/plugintest/provider_interceptor.go | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/actioncheck/example_test.go b/actioncheck/example_test.go index 4d41442b..50be88fe 100644 --- a/actioncheck/example_test.go +++ b/actioncheck/example_test.go @@ -9,7 +9,7 @@ import ( ) // Example of how to use action checks in a test case -func ExampleActionChecks() { +func ExampleExpectProgressMessageContains() { // This is how you would use action checks in a real test _ = resource.TestCase{ Steps: []resource.TestStep{ diff --git a/actioncheck/expect_progress_message_test.go b/actioncheck/expect_progress_message_test.go index a517774b..09c63257 100644 --- a/actioncheck/expect_progress_message_test.go +++ b/actioncheck/expect_progress_message_test.go @@ -12,6 +12,7 @@ import ( ) func TestExpectProgressMessageContains_Success(t *testing.T) { + t.Parallel() check := actioncheck.ExpectProgressMessageContains("test_action", "expected content") req := actioncheck.CheckActionRequest{ @@ -30,6 +31,7 @@ func TestExpectProgressMessageContains_Success(t *testing.T) { } func TestExpectProgressMessageContains_Failure(t *testing.T) { + t.Parallel() check := actioncheck.ExpectProgressMessageContains("test_action", "missing content") req := actioncheck.CheckActionRequest{ diff --git a/internal/plugintest/provider_interceptor.go b/internal/plugintest/provider_interceptor.go index 4846f605..d701609e 100644 --- a/internal/plugintest/provider_interceptor.go +++ b/internal/plugintest/provider_interceptor.go @@ -13,6 +13,7 @@ import ( // NewProviderInterceptor creates a new provider interceptor for tfprotov5 func NewProviderInterceptor(provider tfprotov5.ProviderServer, capture *ProgressCapture) tfprotov5.ProviderServer { // Check if provider supports actions + //nolint:staticcheck // SA1019: ProviderServerWithActions is deprecated but still needed for compatibility if actionProvider, ok := provider.(tfprotov5.ProviderServerWithActions); ok { return &ActionProviderInterceptorV5{ ProviderServerWithActions: actionProvider, @@ -30,6 +31,7 @@ func NewProviderInterceptor(provider tfprotov5.ProviderServer, capture *Progress // NewProviderInterceptorV6 creates a new provider interceptor for tfprotov6 func NewProviderInterceptorV6(provider tfprotov6.ProviderServer, capture *ProgressCapture) tfprotov6.ProviderServer { // Check if provider supports actions + //nolint:staticcheck // SA1019: ProviderServerWithActions is deprecated but still needed for compatibility if actionProvider, ok := provider.(tfprotov6.ProviderServerWithActions); ok { return &ActionProviderInterceptorV6{ ProviderServerWithActions: actionProvider, From bba37b07ea7fb1fc6071a4d540369386adf42660 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Wed, 29 Oct 2025 14:15:58 -0400 Subject: [PATCH 7/9] Remove intermediate approach --- internal/plugintest/working_dir.go | 52 ------------------------------ 1 file changed, 52 deletions(-) diff --git a/internal/plugintest/working_dir.go b/internal/plugintest/working_dir.go index fb75e220..01b43d9f 100644 --- a/internal/plugintest/working_dir.go +++ b/internal/plugintest/working_dir.go @@ -346,11 +346,6 @@ func (wd *WorkingDir) CreatePlan(ctx context.Context, opts ...tfexec.PlanOption) opts = append(opts, tfexec.Reattach(wd.reattachInfo)) opts = append(opts, tfexec.Out(PlanFileName)) - // Capture output if progress capture is enabled - if wd.progressCaptureEnabled { - return wd.createPlanWithProgressCapture(ctx, opts...) - } - logging.HelperResourceTrace(ctx, "Calling Terraform CLI plan command") hasChanges, err := wd.tf.Plan(context.Background(), opts...) @@ -389,11 +384,6 @@ func (wd *WorkingDir) Apply(ctx context.Context, opts ...tfexec.ApplyOption) err args = append(args, tfexec.DirOrPlan(PlanFileName)) } - // Capture output if progress capture is enabled - if wd.progressCaptureEnabled { - return wd.applyWithProgressCapture(ctx, args...) - } - logging.HelperResourceTrace(ctx, "Calling Terraform CLI apply command") err := wd.tf.Apply(context.Background(), args...) @@ -599,45 +589,3 @@ func (wd *WorkingDir) EnableProgressCapture() { func (wd *WorkingDir) DisableProgressCapture() { wd.progressCaptureEnabled = false } - -// applyWithProgressCapture runs terraform apply while capturing action progress messages -func (wd *WorkingDir) applyWithProgressCapture(ctx context.Context, opts ...tfexec.ApplyOption) error { - logging.HelperResourceTrace(ctx, "Calling Terraform CLI apply command with progress capture") - - // TODO: Implement protocol-level progress capture - // For now, fall back to regular apply since stdout parsing doesn't work for action progress - err := wd.tf.Apply(context.Background(), opts...) - - logging.HelperResourceTrace(ctx, "Called Terraform CLI apply command with progress capture") - - return err -} - -// createPlanWithProgressCapture runs terraform plan while capturing action progress messages -func (wd *WorkingDir) createPlanWithProgressCapture(ctx context.Context, opts ...tfexec.PlanOption) error { - logging.HelperResourceTrace(ctx, "Calling Terraform CLI plan command with progress capture") - - // TODO: Implement protocol-level progress capture - // For now, fall back to regular plan since stdout parsing doesn't work for action progress - hasChanges, err := wd.tf.Plan(context.Background(), opts...) - - logging.HelperResourceTrace(ctx, "Called Terraform CLI plan command with progress capture") - - if err != nil { - return err - } - - if !hasChanges { - logging.HelperResourceTrace(ctx, "Created plan with no changes") - return nil - } - - planStdout, err := wd.SavedPlanRawStdout(ctx) - if err != nil { - return fmt.Errorf("error retrieving formatted plan output: %w", err) - } - - logging.HelperResourceTrace(ctx, "Created plan with changes", map[string]any{logging.KeyTestTerraformPlan: planStdout}) - - return nil -} From ed6e9a1d45bb0ae16acd0ff6c7e490fec39166e0 Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Wed, 29 Oct 2025 15:06:22 -0400 Subject: [PATCH 8/9] Clean up --- actioncheck/example_test.go | 6 +++--- helper/resource/testing_new_config.go | 18 ++---------------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/actioncheck/example_test.go b/actioncheck/example_test.go index 50be88fe..bf3c230e 100644 --- a/actioncheck/example_test.go +++ b/actioncheck/example_test.go @@ -25,13 +25,13 @@ func ExampleExpectProgressMessageContains() { `, ActionChecks: []actioncheck.ActionCheck{ // Check that the action produces a message containing log output - actioncheck.ExpectProgressMessageContains("aws_lambda_invoke.test", "Lambda function logs:"), + resource.TestCheckProgressMessageContains("aws_lambda_invoke.test", "Lambda function logs:"), // Check that we get exactly 2 progress messages (success + logs) - actioncheck.ExpectProgressCount("aws_lambda_invoke.test", 2), + resource.TestCheckProgressMessageCount("aws_lambda_invoke.test", 2), // Check that messages appear in the expected sequence - actioncheck.ExpectProgressSequence("aws_lambda_invoke.test", []string{ + resource.TestCheckProgressMessageSequence("aws_lambda_invoke.test", []string{ "invoked successfully", "Lambda function logs:", }), diff --git a/helper/resource/testing_new_config.go b/helper/resource/testing_new_config.go index bce7c783..36d2f13f 100644 --- a/helper/resource/testing_new_config.go +++ b/helper/resource/testing_new_config.go @@ -515,7 +515,7 @@ func runActionChecks(ctx context.Context, actionChecks []actioncheck.ActionCheck // Fallback to expected action name if no messages captured if len(actionNames) == 0 { - actionNames = []string{"aws_lambda_invoke.test"} + return nil // No actions were executed, nothing to check } var allErrors []error @@ -523,20 +523,6 @@ func runActionChecks(ctx context.Context, actionChecks []actioncheck.ActionCheck for _, actionName := range actionNames { messages := progressCapture.GetMessages(actionName) - // Debug: log what messages we found - logging.HelperResourceDebug(ctx, "Action check messages captured", map[string]any{ - "action_name": actionName, - "message_count": len(messages), - }) - - for i, msg := range messages { - logging.HelperResourceDebug(ctx, "Action message", map[string]any{ - "action_name": actionName, - "message_index": i, - "message": msg.Message, - }) - } - req := actioncheck.CheckActionRequest{ ActionName: actionName, Messages: messages, @@ -553,7 +539,7 @@ func runActionChecks(ctx context.Context, actionChecks []actioncheck.ActionCheck } if len(allErrors) > 0 { - return fmt.Errorf("action check failures: %v", allErrors) + return errors.Join(allErrors...) } return nil From 653ee5a261b6f954fcc298bae7d951ece2e0a5dc Mon Sep 17 00:00:00 2001 From: Dirk Avery Date: Wed, 29 Oct 2025 15:09:15 -0400 Subject: [PATCH 9/9] Use modern Go --- helper/acctest/random.go | 2 +- helper/resource/error.go | 4 +- helper/resource/id_test.go | 2 +- helper/resource/json.go | 2 +- helper/resource/plugin.go | 51 +++---- helper/resource/plugin_test.go | 6 +- helper/resource/state.go | 18 ++- helper/resource/state_shim.go | 28 ++-- helper/resource/state_test.go | 22 ++-- helper/resource/testcase_providers_test.go | 6 +- helper/resource/testcase_validate.go | 8 +- helper/resource/testing.go | 15 +-- helper/resource/testing_new.go | 48 +++---- helper/resource/testing_new_config.go | 6 +- helper/resource/testing_new_test.go | 56 ++++---- helper/resource/testing_sets.go | 2 +- helper/resource/testing_sets_test.go | 132 +++++++++---------- helper/resource/teststep_providers_test.go | 112 ++++++++-------- helper/resource/teststep_validate.go | 38 +++--- helper/resource/wait.go | 2 +- internal/configs/hcl2shim/flatmap.go | 2 +- internal/configs/hcl2shim/values.go | 20 +-- internal/configs/hcl2shim/values_test.go | 66 +++++----- internal/logging/context_test.go | 8 +- internal/logging/helper_resource.go | 8 +- internal/logging/helper_resource_test.go | 8 +- internal/plugintest/guard.go | 8 +- internal/plugintest/helper.go | 16 +-- internal/plugintest/util.go | 2 +- internal/plugintest/working_dir.go | 2 +- internal/plugintest/working_dir_json_test.go | 6 +- plancheck/expect_sensitive_value_test.go | 8 +- plancheck/expect_unknown_value_test.go | 8 +- statecheck/expect_known_value_test.go | 8 +- statecheck/expect_sensitive_value_test.go | 8 +- terraform/diff.go | 23 ++-- terraform/resource.go | 33 +++-- terraform/resource_test.go | 78 +++++------ terraform/state.go | 38 ++---- terraform/state_filter.go | 4 +- terraform/state_test.go | 24 ++-- 41 files changed, 454 insertions(+), 484 deletions(-) diff --git a/helper/acctest/random.go b/helper/acctest/random.go index 102c85dd..6a31671d 100644 --- a/helper/acctest/random.go +++ b/helper/acctest/random.go @@ -48,7 +48,7 @@ func RandString(strlen int) string { // the charset provided func RandStringFromCharSet(strlen int, charSet string) string { result := make([]byte, strlen) - for i := 0; i < strlen; i++ { + for i := range strlen { result[i] = charSet[RandIntRange(0, len(charSet))] } return string(result) diff --git a/helper/resource/error.go b/helper/resource/error.go index 3c990e35..f1b03376 100644 --- a/helper/resource/error.go +++ b/helper/resource/error.go @@ -17,8 +17,8 @@ import ( // github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry.NotFoundError. type NotFoundError struct { LastError error - LastRequest interface{} - LastResponse interface{} + LastRequest any + LastResponse any Message string Retries int } diff --git a/helper/resource/id_test.go b/helper/resource/id_test.go index aa4ae1f3..c84a65ba 100644 --- a/helper/resource/id_test.go +++ b/helper/resource/id_test.go @@ -23,7 +23,7 @@ func TestUniqueId(t *testing.T) { iterations := 10000 ids := make(map[string]struct{}) var id, lastId string - for i := 0; i < iterations; i++ { + for range iterations { id = UniqueId() if _, ok := ids[id]; ok { diff --git a/helper/resource/json.go b/helper/resource/json.go index 9cd6a1b9..098edb1f 100644 --- a/helper/resource/json.go +++ b/helper/resource/json.go @@ -8,7 +8,7 @@ import ( "encoding/json" ) -func unmarshalJSON(data []byte, v interface{}) error { +func unmarshalJSON(data []byte, v any) error { dec := json.NewDecoder(bytes.NewReader(data)) dec.UseNumber() return dec.Decode(v) diff --git a/helper/resource/plugin.go b/helper/resource/plugin.go index b7739c80..bcef8172 100644 --- a/helper/resource/plugin.go +++ b/helper/resource/plugin.go @@ -7,6 +7,7 @@ import ( "context" "fmt" "io" + "maps" "os" "strings" "sync" @@ -39,14 +40,10 @@ type protov5ProviderFactories map[string]func() (tfprotov5.ProviderServer, error func (pf protov5ProviderFactories) merge(otherPfs ...protov5ProviderFactories) protov5ProviderFactories { result := make(protov5ProviderFactories) - for name, providerFactory := range pf { - result[name] = providerFactory - } + maps.Copy(result, pf) for _, otherPf := range otherPfs { - for name, providerFactory := range otherPf { - result[name] = providerFactory - } + maps.Copy(result, otherPf) } return result @@ -67,14 +64,10 @@ type protov6ProviderFactories map[string]func() (tfprotov6.ProviderServer, error func (pf protov6ProviderFactories) merge(otherPfs ...protov6ProviderFactories) protov6ProviderFactories { result := make(protov6ProviderFactories) - for name, providerFactory := range pf { - result[name] = providerFactory - } + maps.Copy(result, pf) for _, otherPf := range otherPfs { - for name, providerFactory := range otherPf { - result[name] = providerFactory - } + maps.Copy(result, otherPf) } return result @@ -95,14 +88,10 @@ type sdkProviderFactories map[string]func() (*schema.Provider, error) func (pf sdkProviderFactories) merge(otherPfs ...sdkProviderFactories) sdkProviderFactories { result := make(sdkProviderFactories) - for name, providerFactory := range pf { - result[name] = providerFactory - } + maps.Copy(result, pf) for _, otherPf := range otherPfs { - for name, providerFactory := range otherPf { - result[name] = providerFactory - } + maps.Copy(result, otherPf) } return result @@ -214,14 +203,14 @@ func runProviderCommand(ctx context.Context, t testing.T, wd *plugintest.Working providerName = strings.TrimPrefix(providerName, "terraform-provider-") providerAddress := getProviderAddr(providerName) - logging.HelperResourceTrace(ctx, "Creating sdkv2 provider instance", map[string]interface{}{logging.KeyProviderAddress: providerAddress}) + logging.HelperResourceTrace(ctx, "Creating sdkv2 provider instance", map[string]any{logging.KeyProviderAddress: providerAddress}) provider, err := factory() if err != nil { return fmt.Errorf("unable to create provider %q from factory: %w", providerName, err) } - logging.HelperResourceTrace(ctx, "Created sdkv2 provider instance", map[string]interface{}{logging.KeyProviderAddress: providerAddress}) + logging.HelperResourceTrace(ctx, "Created sdkv2 provider instance", map[string]any{logging.KeyProviderAddress: providerAddress}) // keep track of the running factory, so we can make sure it's // shut down. @@ -251,14 +240,14 @@ func runProviderCommand(ctx context.Context, t testing.T, wd *plugintest.Working ProviderAddr: providerAddress, } - logging.HelperResourceTrace(ctx, "Starting sdkv2 provider instance server", map[string]interface{}{logging.KeyProviderAddress: providerAddress}) + logging.HelperResourceTrace(ctx, "Starting sdkv2 provider instance server", map[string]any{logging.KeyProviderAddress: providerAddress}) config, closeCh, err := plugin.DebugServe(ctx, opts) if err != nil { return fmt.Errorf("unable to serve provider %q: %w", providerName, err) } - logging.HelperResourceTrace(ctx, "Started sdkv2 provider instance server", map[string]interface{}{logging.KeyProviderAddress: providerAddress}) + logging.HelperResourceTrace(ctx, "Started sdkv2 provider instance server", map[string]any{logging.KeyProviderAddress: providerAddress}) tfexecConfig := tfexec.ReattachConfig{ Protocol: config.Protocol, @@ -308,7 +297,7 @@ func runProviderCommand(ctx context.Context, t testing.T, wd *plugintest.Working } } - logging.HelperResourceTrace(ctx, "Creating tfprotov5 provider instance", map[string]interface{}{logging.KeyProviderAddress: providerAddress}) + logging.HelperResourceTrace(ctx, "Creating tfprotov5 provider instance", map[string]any{logging.KeyProviderAddress: providerAddress}) provider, err := factory() if err != nil { @@ -320,7 +309,7 @@ func runProviderCommand(ctx context.Context, t testing.T, wd *plugintest.Working provider = plugintest.NewProviderInterceptor(provider, wd.GetProgressCapture()) } - logging.HelperResourceTrace(ctx, "Created tfprotov5 provider instance", map[string]interface{}{logging.KeyProviderAddress: providerAddress}) + logging.HelperResourceTrace(ctx, "Created tfprotov5 provider instance", map[string]any{logging.KeyProviderAddress: providerAddress}) // keep track of the running factory, so we can make sure it's // shut down. @@ -344,14 +333,14 @@ func runProviderCommand(ctx context.Context, t testing.T, wd *plugintest.Working ProviderAddr: providerAddress, } - logging.HelperResourceTrace(ctx, "Starting tfprotov5 provider instance server", map[string]interface{}{logging.KeyProviderAddress: providerAddress}) + logging.HelperResourceTrace(ctx, "Starting tfprotov5 provider instance server", map[string]any{logging.KeyProviderAddress: providerAddress}) config, closeCh, err := plugin.DebugServe(ctx, opts) if err != nil { return fmt.Errorf("unable to serve provider %q: %w", providerName, err) } - logging.HelperResourceTrace(ctx, "Started tfprotov5 provider instance server", map[string]interface{}{logging.KeyProviderAddress: providerAddress}) + logging.HelperResourceTrace(ctx, "Started tfprotov5 provider instance server", map[string]any{logging.KeyProviderAddress: providerAddress}) tfexecConfig := tfexec.ReattachConfig{ Protocol: config.Protocol, @@ -402,14 +391,14 @@ func runProviderCommand(ctx context.Context, t testing.T, wd *plugintest.Working } } - logging.HelperResourceTrace(ctx, "Creating tfprotov6 provider instance", map[string]interface{}{logging.KeyProviderAddress: providerAddress}) + logging.HelperResourceTrace(ctx, "Creating tfprotov6 provider instance", map[string]any{logging.KeyProviderAddress: providerAddress}) provider, err := factory() if err != nil { return fmt.Errorf("unable to create provider %q from factory: %w", providerName, err) } - logging.HelperResourceTrace(ctx, "Created tfprotov6 provider instance", map[string]interface{}{logging.KeyProviderAddress: providerAddress}) + logging.HelperResourceTrace(ctx, "Created tfprotov6 provider instance", map[string]any{logging.KeyProviderAddress: providerAddress}) // Wrap provider to capture action progress messages if needed if wd.IsProgressCaptureEnabled() { @@ -434,14 +423,14 @@ func runProviderCommand(ctx context.Context, t testing.T, wd *plugintest.Working ProviderAddr: providerAddress, } - logging.HelperResourceTrace(ctx, "Starting tfprotov6 provider instance server", map[string]interface{}{logging.KeyProviderAddress: providerAddress}) + logging.HelperResourceTrace(ctx, "Starting tfprotov6 provider instance server", map[string]any{logging.KeyProviderAddress: providerAddress}) config, closeCh, err := plugin.DebugServe(ctx, opts) if err != nil { return fmt.Errorf("unable to serve provider %q: %w", providerName, err) } - logging.HelperResourceTrace(ctx, "Started tfprotov6 provider instance server", map[string]interface{}{logging.KeyProviderAddress: providerAddress}) + logging.HelperResourceTrace(ctx, "Started tfprotov6 provider instance server", map[string]any{logging.KeyProviderAddress: providerAddress}) tfexecConfig := tfexec.ReattachConfig{ Protocol: config.Protocol, @@ -483,7 +472,7 @@ func runProviderCommand(ctx context.Context, t testing.T, wd *plugintest.Working // started. err := f() if err != nil { - logging.HelperResourceWarn(ctx, "Error running Terraform CLI command", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceWarn(ctx, "Error running Terraform CLI command", map[string]any{logging.KeyError: err}) } logging.HelperResourceTrace(ctx, "Called wrapped Terraform CLI command") diff --git a/helper/resource/plugin_test.go b/helper/resource/plugin_test.go index 62823efd..ff418471 100644 --- a/helper/resource/plugin_test.go +++ b/helper/resource/plugin_test.go @@ -256,15 +256,15 @@ func TestRunProviderCommand(t *testing.T) { return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "examplecloud_thing": { - CreateContext: func(ctx context.Context, d *schema.ResourceData, i interface{}) diag.Diagnostics { + CreateContext: func(ctx context.Context, d *schema.ResourceData, i any) diag.Diagnostics { d.SetId("id") return nil }, - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{ diff --git a/helper/resource/state.go b/helper/resource/state.go index 9ed11327..c9cb04bb 100644 --- a/helper/resource/state.go +++ b/helper/resource/state.go @@ -6,6 +6,7 @@ package resource import ( "context" "log" + "slices" "time" ) @@ -24,7 +25,7 @@ var refreshGracePeriod = 30 * time.Second // // Deprecated: Copy this type to the provider codebase or use // github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry.StateRefreshFunc. -type StateRefreshFunc func() (result interface{}, state string, err error) +type StateRefreshFunc func() (result any, state string, err error) // StateChangeConf is the configuration struct used for `WaitForState`. // @@ -63,7 +64,7 @@ type StateChangeConf struct { // // Deprecated: Copy this method to the provider codebase or use // github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry.StateChangeConf. -func (conf *StateChangeConf) WaitForStateContext(ctx context.Context) (interface{}, error) { +func (conf *StateChangeConf) WaitForStateContext(ctx context.Context) (any, error) { log.Printf("[DEBUG] Waiting for state to become: %s", conf.Target) notfoundTick := 0 @@ -79,7 +80,7 @@ func (conf *StateChangeConf) WaitForStateContext(ctx context.Context) (interface } type Result struct { - Result interface{} + Result any State string Error error Done bool @@ -172,12 +173,9 @@ func (conf *StateChangeConf) WaitForStateContext(ctx context.Context) (interface } } - for _, allowed := range conf.Pending { - if currentState == allowed { - found = true - targetOccurence = 0 - break - } + if slices.Contains(conf.Pending, currentState) { + found = true + targetOccurence = 0 } if !found && len(conf.Pending) > 0 { @@ -287,6 +285,6 @@ func (conf *StateChangeConf) WaitForStateContext(ctx context.Context) (interface // waiting the number of seconds specified in the timeout configuration. // // Deprecated: Please use WaitForStateContext to ensure proper plugin shutdown -func (conf *StateChangeConf) WaitForState() (interface{}, error) { +func (conf *StateChangeConf) WaitForState() (any, error) { return conf.WaitForStateContext(context.Background()) } diff --git a/helper/resource/state_shim.go b/helper/resource/state_shim.go index 2cd8407f..a4dc4222 100644 --- a/helper/resource/state_shim.go +++ b/helper/resource/state_shim.go @@ -56,7 +56,7 @@ func shimOutputState(so *tfjson.StateOutput) (*terraform.OutputState, error) { os.Type = "string" os.Value = v return os, nil - case []interface{}: + case []any: os.Type = "list" if len(v) == 0 { os.Value = v @@ -65,7 +65,7 @@ func shimOutputState(so *tfjson.StateOutput) (*terraform.OutputState, error) { switch firstElem := v[0].(type) { case string: - elements := make([]interface{}, len(v)) + elements := make([]any, len(v)) for i, el := range v { strElement, ok := el.(string) // If the type of the element doesn't match the first elem, it's a tuple, return the original value @@ -77,7 +77,7 @@ func shimOutputState(so *tfjson.StateOutput) (*terraform.OutputState, error) { } os.Value = elements case bool: - elements := make([]interface{}, len(v)) + elements := make([]any, len(v)) for i, el := range v { boolElement, ok := el.(bool) // If the type of the element doesn't match the first elem, it's a tuple, return the original value @@ -91,7 +91,7 @@ func shimOutputState(so *tfjson.StateOutput) (*terraform.OutputState, error) { os.Value = elements // unmarshalled number from JSON will always be json.Number case json.Number: - elements := make([]interface{}, len(v)) + elements := make([]any, len(v)) for i, el := range v { numberElement, ok := el.(json.Number) // If the type of the element doesn't match the first elem, it's a tuple, return the original value @@ -103,15 +103,15 @@ func shimOutputState(so *tfjson.StateOutput) (*terraform.OutputState, error) { elements[i] = numberElement } os.Value = elements - case []interface{}: + case []any: os.Value = v - case map[string]interface{}: + case map[string]any: os.Value = v default: return nil, fmt.Errorf("unexpected output list element type: %T", firstElem) } return os, nil - case map[string]interface{}: + case map[string]any: os.Type = "map" os.Value = v return os, nil @@ -242,7 +242,7 @@ func shimResourceState(res *tfjson.StateResource) (*terraform.ResourceState, err Primary: &terraform.InstanceState{ ID: instanceStateID, Attributes: attributes, - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": int(res.SchemaVersion), }, Tainted: res.Tainted, @@ -255,7 +255,7 @@ type shimmedFlatmap struct { m map[string]string } -func (sf *shimmedFlatmap) FromMap(attributes map[string]interface{}) error { +func (sf *shimmedFlatmap) FromMap(attributes map[string]any) error { if sf.m == nil { sf.m = make(map[string]string, len(attributes)) } @@ -263,7 +263,7 @@ func (sf *shimmedFlatmap) FromMap(attributes map[string]interface{}) error { return sf.AddMap("", attributes) } -func (sf *shimmedFlatmap) AddMap(prefix string, m map[string]interface{}) error { +func (sf *shimmedFlatmap) AddMap(prefix string, m map[string]any) error { for key, value := range m { k := key if prefix != "" { @@ -288,7 +288,7 @@ func (sf *shimmedFlatmap) AddMap(prefix string, m map[string]interface{}) error return nil } -func (sf *shimmedFlatmap) AddSlice(name string, elements []interface{}) error { +func (sf *shimmedFlatmap) AddSlice(name string, elements []any) error { for i, elem := range elements { key := fmt.Sprintf("%s.%d", name, i) err := sf.AddEntry(key, elem) @@ -305,7 +305,7 @@ func (sf *shimmedFlatmap) AddSlice(name string, elements []interface{}) error { return nil } -func (sf *shimmedFlatmap) AddEntry(key string, value interface{}) error { +func (sf *shimmedFlatmap) AddEntry(key string, value any) error { switch el := value.(type) { case nil: // omit the entry @@ -316,12 +316,12 @@ func (sf *shimmedFlatmap) AddEntry(key string, value interface{}) error { sf.m[key] = el.String() case string: sf.m[key] = el - case map[string]interface{}: + case map[string]any: err := sf.AddMap(key, el) if err != nil { return err } - case []interface{}: + case []any: err := sf.AddSlice(key, el) if err != nil { return err diff --git a/helper/resource/state_test.go b/helper/resource/state_test.go index 1dd67013..46fa51ac 100644 --- a/helper/resource/state_test.go +++ b/helper/resource/state_test.go @@ -13,20 +13,20 @@ import ( ) func FailedStateRefreshFunc() StateRefreshFunc { - return func() (interface{}, string, error) { + return func() (any, string, error) { return nil, "", errors.New("failed") } } func TimeoutStateRefreshFunc() StateRefreshFunc { - return func() (interface{}, string, error) { + return func() (any, string, error) { time.Sleep(100 * time.Second) return nil, "", errors.New("failed") } } func SuccessfulStateRefreshFunc() StateRefreshFunc { - return func() (interface{}, string, error) { + return func() (any, string, error) { return struct{}{}, "running", nil } } @@ -66,7 +66,7 @@ func InconsistentStateRefreshFunc() StateRefreshFunc { r := NewStateGenerator(sequence) - return func() (interface{}, string, error) { + return func() (any, string, error) { idx, s, err := r.NextState() if err != nil { return nil, "", err @@ -83,7 +83,7 @@ func UnknownPendingStateRefreshFunc() StateRefreshFunc { r := NewStateGenerator(sequence) - return func() (interface{}, string, error) { + return func() (any, string, error) { idx, s, err := r.NextState() if err != nil { return nil, "", err @@ -122,7 +122,7 @@ func TestWaitForState_inconsistent_negative(t *testing.T) { refreshCount := int64(0) f := InconsistentStateRefreshFunc() - refresh := func() (interface{}, string, error) { + refresh := func() (any, string, error) { atomic.AddInt64(&refreshCount, 1) return f() } @@ -194,7 +194,7 @@ func TestWaitForState_cancel(t *testing.T) { // make this refresh func block until we cancel it cancel := make(chan struct{}) - refresh := func() (interface{}, string, error) { + refresh := func() (any, string, error) { <-cancel return nil, "pending", nil } @@ -206,7 +206,7 @@ func TestWaitForState_cancel(t *testing.T) { PollInterval: 10 * time.Second, } - var obj interface{} + var obj any var err error waitDone := make(chan struct{}) @@ -289,7 +289,7 @@ func TestWaitForState_successEmpty(t *testing.T) { conf := &StateChangeConf{ Pending: []string{"pending", "incomplete"}, Target: []string{}, - Refresh: func() (interface{}, string, error) { + Refresh: func() (any, string, error) { return nil, "", nil }, Timeout: 200 * time.Second, @@ -311,7 +311,7 @@ func TestWaitForState_failureEmpty(t *testing.T) { Pending: []string{"pending", "incomplete"}, Target: []string{}, NotFoundChecks: 1, - Refresh: func() (interface{}, string, error) { + Refresh: func() (any, string, error) { return 42, "pending", nil }, PollInterval: 10 * time.Millisecond, @@ -356,7 +356,7 @@ func TestWaitForStateContext_cancel(t *testing.T) { // make this refresh func block until we cancel it ctx, cancel := context.WithCancel(context.Background()) - refresh := func() (interface{}, string, error) { + refresh := func() (any, string, error) { <-ctx.Done() return nil, "pending", nil } diff --git a/helper/resource/testcase_providers_test.go b/helper/resource/testcase_providers_test.go index 4b54d725..9909dadb 100644 --- a/helper/resource/testcase_providers_test.go +++ b/helper/resource/testcase_providers_test.go @@ -305,14 +305,14 @@ func TestTest_TestCase_ExternalProvidersAndProviderFactories_NonHashiCorpNamespa return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "null_resource": { - CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + CreateContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { d.SetId("test") return nil }, - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{ diff --git a/helper/resource/testcase_validate.go b/helper/resource/testcase_validate.go index 6640f8c8..fd0bae3e 100644 --- a/helper/resource/testcase_validate.go +++ b/helper/resource/testcase_validate.go @@ -56,20 +56,20 @@ func (c TestCase) validate(ctx context.Context, t testing.T) error { if len(c.Steps) == 0 { err := fmt.Errorf("TestCase missing Steps") - logging.HelperResourceError(ctx, "TestCase validation error", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceError(ctx, "TestCase validation error", map[string]any{logging.KeyError: err}) return err } for name := range c.ExternalProviders { if _, ok := c.Providers[name]; ok { err := fmt.Errorf("TestCase provider %q set in both ExternalProviders and Providers", name) - logging.HelperResourceError(ctx, "TestCase validation error", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceError(ctx, "TestCase validation error", map[string]any{logging.KeyError: err}) return err } if _, ok := c.ProviderFactories[name]; ok { err := fmt.Errorf("TestCase provider %q set in both ExternalProviders and ProviderFactories", name) - logging.HelperResourceError(ctx, "TestCase validation error", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceError(ctx, "TestCase validation error", map[string]any{logging.KeyError: err}) return err } } @@ -104,7 +104,7 @@ func (c TestCase) validate(ctx context.Context, t testing.T) error { if err != nil { err := fmt.Errorf("TestStep %d/%d validation error: %w", stepNumber, len(c.Steps), err) - logging.HelperResourceError(ctx, "TestCase validation error", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceError(ctx, "TestCase validation error", map[string]any{logging.KeyError: err}) return err } } diff --git a/helper/resource/testing.go b/helper/resource/testing.go index 85d5c122..cb92759f 100644 --- a/helper/resource/testing.go +++ b/helper/resource/testing.go @@ -9,6 +9,7 @@ import ( "flag" "fmt" "log" + "maps" "os" "regexp" "strconv" @@ -207,9 +208,7 @@ func filterSweepers(f string, source map[string]*Sweeper) map[string]*Sweeper { for name := range source { for _, s := range filterSlice { if strings.Contains(strings.ToLower(name), s) { - for foundName, foundSweeper := range filterSweeperWithDependencies(name, source) { - sweepers[foundName] = foundSweeper - } + maps.Copy(sweepers, filterSweeperWithDependencies(name, source)) } } } @@ -231,9 +230,7 @@ func filterSweeperWithDependencies(name string, source map[string]*Sweeper) map[ result[name] = currentSweeper for _, dependency := range currentSweeper.Dependencies { - for foundName, foundSweeper := range filterSweeperWithDependencies(dependency, source) { - result[foundName] = foundSweeper - } + maps.Copy(result, filterSweeperWithDependencies(dependency, source)) } return result @@ -936,7 +933,7 @@ func Test(t testing.T, c TestCase) { if err != nil { logging.HelperResourceError(ctx, "Test validation error", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("Test validation error: %s", err) } @@ -984,7 +981,7 @@ func Test(t testing.T, c TestCase) { defer func(helper *plugintest.Helper) { err := helper.Close() if err != nil { - logging.HelperResourceError(ctx, "Unable to clean up temporary test files", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceError(ctx, "Unable to clean up temporary test files", map[string]any{logging.KeyError: err}) } }(helper) @@ -2144,7 +2141,7 @@ func primaryInstanceState(s *terraform.State, name string) (*terraform.InstanceS // string address uses a precalculated TypeSet hash, which are integers and // typically are large and obviously not a list index func indexesIntoTypeSet(key string) bool { - for _, part := range strings.Split(key, ".") { + for part := range strings.SplitSeq(key, ".") { if i, err := strconv.Atoi(part); err == nil && i > 100 { return true } diff --git a/helper/resource/testing_new.go b/helper/resource/testing_new.go index 0faf0589..d0ff7ec3 100644 --- a/helper/resource/testing_new.go +++ b/helper/resource/testing_new.go @@ -77,7 +77,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest if err != nil { logging.HelperResourceError(ctx, "Error retrieving state, there may be dangling resources", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("Error retrieving state, there may be dangling resources: %s", err.Error()) return @@ -88,7 +88,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest if err != nil { logging.HelperResourceError(ctx, "Error running post-test destroy, there may be dangling resources", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("Error running post-test destroy, there may be dangling resources: %s", err.Error()) } @@ -111,7 +111,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest if err != nil { logging.HelperResourceError(ctx, "TestCase error setting provider configuration", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("TestCase error setting provider configuration: %s", err) } @@ -123,7 +123,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest if err != nil { logging.HelperResourceError(ctx, "TestCase error running init", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("TestCase error running init: %s", err.Error()) } @@ -170,7 +170,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest if err != nil { logging.HelperResourceError(ctx, "Error calling TestStep SkipFunc", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("Error calling TestStep SkipFunc: %s", err.Error()) } @@ -190,7 +190,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest if err != nil { logging.HelperResourceError(ctx, "TestStep error tainting resources", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("TestStep %d/%d error tainting resources: %s", stepNumber, len(c.Steps), err) } @@ -201,7 +201,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest if err != nil { logging.HelperResourceError(ctx, "TestStep error checking for providers", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("TestStep %d/%d error checking for providers: %s", stepNumber, len(c.Steps), err) } @@ -221,7 +221,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest if err != nil { logging.HelperResourceError(ctx, "TestStep error determining whether configuration contains provider block", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("TestStep %d/%d error determining whether configuration contains provider block: %s", stepNumber, len(c.Steps), err) } @@ -234,7 +234,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest if err != nil { logging.HelperResourceError(ctx, "TestStep error generating provider configuration", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("TestStep %d/%d error generating provider configuration: %s", stepNumber, len(c.Steps), err) } @@ -261,7 +261,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest if err != nil { logging.HelperResourceError(ctx, "TestStep error setting provider configuration", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("TestStep %d/%d error setting test provider configuration: %s", stepNumber, len(c.Steps), err) } @@ -273,7 +273,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest if err != nil { logging.HelperResourceError(ctx, "TestStep error running init", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("TestStep %d/%d running init: %s", stepNumber, len(c.Steps), err.Error()) return @@ -295,7 +295,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest if !step.ExpectError.MatchString(err.Error()) { logging.HelperResourceError(ctx, fmt.Sprintf("Error running import: expected an error with pattern (%s)", step.ExpectError.String()), - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("Step %d/%d error running import, expected an error with pattern (%s), no match on: %s", stepNumber, len(c.Steps), step.ExpectError.String(), err) } @@ -308,7 +308,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest if err != nil { logging.HelperResourceError(ctx, "Error running import", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("Step %d/%d error running import: %s", stepNumber, len(c.Steps), err) } @@ -334,7 +334,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest 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}, + map[string]any{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) } @@ -347,7 +347,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest if err != nil { logging.HelperResourceError(ctx, "Error running refresh", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("Step %d/%d error running refresh: %s", stepNumber, len(c.Steps), err) } @@ -371,7 +371,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest } if !step.ExpectError.MatchString(err.Error()) { logging.HelperResourceError(ctx, fmt.Sprintf("Error running query: expected an error with pattern (%s)", step.ExpectError.String()), - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("Step %d/%d error running query, expected an error with pattern (%s), no match on: %s", stepNumber, len(c.Steps), step.ExpectError.String(), err) } @@ -383,7 +383,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest } if err != nil { logging.HelperResourceError(ctx, "Error running query", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("Step %d/%d error running query checks: %s", stepNumber, len(c.Steps), err) } @@ -410,7 +410,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest if !step.ExpectError.MatchString(err.Error()) { logging.HelperResourceError(ctx, fmt.Sprintf("Expected an error with pattern (%s)", step.ExpectError.String()), - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("Step %d/%d, expected an error with pattern, no match on: %s", stepNumber, len(c.Steps), err) } @@ -425,7 +425,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest if err != nil { logging.HelperResourceError(ctx, "Unexpected error", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("Step %d/%d error: %s", stepNumber, len(c.Steps), err) } @@ -440,7 +440,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest if err != nil { logging.HelperResourceError(ctx, "Error determining whether configuration contains terraform block", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("Error determining whether configuration contains terraform block: %s", err) } @@ -450,7 +450,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest if err != nil { logging.HelperResourceError(ctx, "Error determining whether configuration contains provider block", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("Error determining whether configuration contains provider block: %s", err) } @@ -461,7 +461,7 @@ func runNewTest(ctx context.Context, t testing.T, c TestCase, helper *plugintest if err != nil { logging.HelperResourceError(ctx, "Error generating merged configuration", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("Error generating merged configuration: %s", err) } @@ -563,7 +563,7 @@ func testIDRefresh(ctx context.Context, t testing.T, c TestCase, wd *plugintest. if err != nil { logging.HelperResourceError(ctx, "Error determining whether configuration contains provider block for import test config", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("Error determining whether configuration contains provider block for import test config: %s", err) } @@ -690,7 +690,7 @@ func copyWorkingDir(ctx context.Context, t testing.T, stepNumber int, wd *plugin if err != nil { logging.HelperResourceError(ctx, "Unexpected error copying working directory files", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("TestStep %d/%d error copying working directory files: %s", stepNumber, err) } diff --git a/helper/resource/testing_new_config.go b/helper/resource/testing_new_config.go index 36d2f13f..25a07283 100644 --- a/helper/resource/testing_new_config.go +++ b/helper/resource/testing_new_config.go @@ -73,7 +73,7 @@ func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugint if err != nil { logging.HelperResourceError(ctx, "Error determining whether configuration contains terraform block", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("Error determining whether configuration contains terraform block: %s", err) } @@ -83,7 +83,7 @@ func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugint if err != nil { logging.HelperResourceError(ctx, "Error determining whether configuration contains provider block", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("Error determining whether configuration contains provider block: %s", err) } @@ -94,7 +94,7 @@ func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugint if err != nil { logging.HelperResourceError(ctx, "Error generating merged configuration", - map[string]interface{}{logging.KeyError: err}, + map[string]any{logging.KeyError: err}, ) t.Fatalf("Error generating merged configuration: %s", err) } diff --git a/helper/resource/testing_new_test.go b/helper/resource/testing_new_test.go index 22f72626..afe33c13 100644 --- a/helper/resource/testing_new_test.go +++ b/helper/resource/testing_new_test.go @@ -170,19 +170,19 @@ func TestShimState(t *testing.T) { Outputs: map[string]*terraform.OutputState{ "empty_list": { Type: "list", - Value: []interface{}{}, + Value: []any{}, Sensitive: false, }, "list_of_strings": { Type: "list", - Value: []interface{}{ + Value: []any{ "first", "second", "third", }, Sensitive: false, }, "map_of_strings": { Type: "map", - Value: map[string]interface{}{ + Value: map[string]any{ "hello": "world", "foo": "bar", }, @@ -190,7 +190,7 @@ func TestShimState(t *testing.T) { }, "list_of_int": { Type: "list", - Value: []interface{}{ + Value: []any{ json.Number("1"), json.Number("4"), json.Number("9"), @@ -199,7 +199,7 @@ func TestShimState(t *testing.T) { }, "list_of_float": { Type: "list", - Value: []interface{}{ + Value: []any{ json.Number("1.2"), json.Number("4.2"), json.Number("9.8"), @@ -208,28 +208,28 @@ func TestShimState(t *testing.T) { }, "list_of_bool": { Type: "list", - Value: []interface{}{ + Value: []any{ true, false, true, }, Sensitive: false, }, "tuple_one": { Type: "list", - Value: []interface{}{ + Value: []any{ true, json.Number("1.23"), "hello world", }, Sensitive: false, }, "tuple_two": { Type: "list", - Value: []interface{}{ + Value: []any{ "hello world", true, json.Number("1.23"), }, Sensitive: false, }, "tuple_three": { Type: "list", - Value: []interface{}{ + Value: []any{ json.Number("1.23"), "hello world", true, }, Sensitive: false, @@ -269,9 +269,9 @@ func TestShimState(t *testing.T) { Outputs: map[string]*terraform.OutputState{ "list_of_lists": { Type: "list", - Value: []interface{}{ - []interface{}{"one", "two"}, - []interface{}{"blue", "green", "red"}, + Value: []any{ + []any{"one", "two"}, + []any{"blue", "green", "red"}, }, Sensitive: false, }, @@ -318,13 +318,13 @@ func TestShimState(t *testing.T) { Outputs: map[string]*terraform.OutputState{ "list_of_maps": { Type: "list", - Value: []interface{}{ - map[string]interface{}{ + Value: []any{ + map[string]any{ "allow_bool": true, "port": json.Number("443"), "rule": "allow", }, - map[string]interface{}{ + map[string]any{ "allow_bool": false, "port": json.Number("80"), "rule": "deny", @@ -369,8 +369,8 @@ func TestShimState(t *testing.T) { Outputs: map[string]*terraform.OutputState{ "map_of_maps": { Type: "map", - Value: map[string]interface{}{ - "hello": map[string]interface{}{ + Value: map[string]any{ + "hello": map[string]any{ "whole": "world", }, "foo": "bar", @@ -441,7 +441,7 @@ func TestShimState(t *testing.T) { Provider: "cloud", Primary: &terraform.InstanceState{ ID: "123999", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 1, }, Attributes: map[string]string{ @@ -517,7 +517,7 @@ func TestShimState(t *testing.T) { Provider: "cloud", Primary: &terraform.InstanceState{ ID: "123999", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 1, }, Attributes: map[string]string{ @@ -623,7 +623,7 @@ func TestShimState(t *testing.T) { Provider: "cloud", Primary: &terraform.InstanceState{ ID: "123999", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 1, }, Attributes: map[string]string{ @@ -710,7 +710,7 @@ func TestShimState(t *testing.T) { Provider: "cloud", Primary: &terraform.InstanceState{ ID: "123999", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -776,7 +776,7 @@ func TestShimState(t *testing.T) { Provider: "cloud", Primary: &terraform.InstanceState{ ID: "123999", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 1, }, Attributes: map[string]string{ @@ -861,7 +861,7 @@ func TestShimState(t *testing.T) { Provider: "cloud", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 1, }, Attributes: map[string]string{ @@ -875,7 +875,7 @@ func TestShimState(t *testing.T) { Provider: "cloud", Primary: &terraform.InstanceState{ ID: "22222", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 1, }, Attributes: map[string]string{ @@ -941,7 +941,7 @@ func TestShimState(t *testing.T) { Provider: "cloud", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -955,7 +955,7 @@ func TestShimState(t *testing.T) { Provider: "cloud", Primary: &terraform.InstanceState{ ID: "22222", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1060,7 +1060,7 @@ func TestShimState(t *testing.T) { Provider: "cloud", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1074,7 +1074,7 @@ func TestShimState(t *testing.T) { Provider: "cloud", Primary: &terraform.InstanceState{ ID: "22222", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ diff --git a/helper/resource/testing_sets.go b/helper/resource/testing_sets.go index 85112220..daa20698 100644 --- a/helper/resource/testing_sets.go +++ b/helper/resource/testing_sets.go @@ -444,7 +444,7 @@ func testCheckTypeSetElemPair(is *terraform.InstanceState, attr, value string) e // in the instance state. Currently, the function accepts a "values" param of type // map[string]string or map[string]*regexp.Regexp. // Returns true if all attributes match, else false. -func testCheckTypeSetElemNestedAttrsInState(is *terraform.InstanceState, attrParts []string, matchCount int, values interface{}) bool { +func testCheckTypeSetElemNestedAttrsInState(is *terraform.InstanceState, attrParts []string, matchCount int, values any) bool { matches := make(map[string]int) for stateKey, stateValue := range is.Attributes { diff --git a/helper/resource/testing_sets_test.go b/helper/resource/testing_sets_test.go index 4d50e7ec..638a4017 100644 --- a/helper/resource/testing_sets_test.go +++ b/helper/resource/testing_sets_test.go @@ -59,7 +59,7 @@ func TestTestCheckTypeSetElemAttr(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -95,7 +95,7 @@ func TestTestCheckTypeSetElemAttr(t *testing.T) { Deposed: []*terraform.InstanceState{ { ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -131,7 +131,7 @@ func TestTestCheckTypeSetElemAttr(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -166,7 +166,7 @@ func TestTestCheckTypeSetElemAttr(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -201,7 +201,7 @@ func TestTestCheckTypeSetElemAttr(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -235,7 +235,7 @@ func TestTestCheckTypeSetElemAttr(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -272,7 +272,7 @@ func TestTestCheckTypeSetElemAttr(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -307,7 +307,7 @@ func TestTestCheckTypeSetElemAttr(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -345,7 +345,7 @@ func TestTestCheckTypeSetElemAttr(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -379,7 +379,7 @@ func TestTestCheckTypeSetElemAttr(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -462,7 +462,7 @@ func TestTestCheckTypeSetElemAttrPair(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "3579", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -502,7 +502,7 @@ func TestTestCheckTypeSetElemAttrPair(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -566,7 +566,7 @@ func TestTestCheckTypeSetElemAttrPair(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "3579", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -606,7 +606,7 @@ func TestTestCheckTypeSetElemAttrPair(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -645,7 +645,7 @@ func TestTestCheckTypeSetElemAttrPair(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -659,7 +659,7 @@ func TestTestCheckTypeSetElemAttrPair(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "3579", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -699,7 +699,7 @@ func TestTestCheckTypeSetElemAttrPair(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -716,7 +716,7 @@ func TestTestCheckTypeSetElemAttrPair(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "3579", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -752,7 +752,7 @@ func TestTestCheckTypeSetElemAttrPair(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -769,7 +769,7 @@ func TestTestCheckTypeSetElemAttrPair(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "3579", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -809,7 +809,7 @@ func TestTestCheckTypeSetElemAttrPair(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -826,7 +826,7 @@ func TestTestCheckTypeSetElemAttrPair(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "3579", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -866,7 +866,7 @@ func TestTestCheckTypeSetElemAttrPair(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -883,7 +883,7 @@ func TestTestCheckTypeSetElemAttrPair(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "3579", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -920,7 +920,7 @@ func TestTestCheckTypeSetElemAttrPair(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -937,7 +937,7 @@ func TestTestCheckTypeSetElemAttrPair(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "3579", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -974,7 +974,7 @@ func TestTestCheckTypeSetElemAttrPair(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -990,7 +990,7 @@ func TestTestCheckTypeSetElemAttrPair(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "3579", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1087,7 +1087,7 @@ func TestTestMatchTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1123,7 +1123,7 @@ func TestTestMatchTypeSetElemNestedAttrs(t *testing.T) { Deposed: []*terraform.InstanceState{ { ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1159,7 +1159,7 @@ func TestTestMatchTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1194,7 +1194,7 @@ func TestTestMatchTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1229,7 +1229,7 @@ func TestTestMatchTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1266,7 +1266,7 @@ func TestTestMatchTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1302,7 +1302,7 @@ func TestTestMatchTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1341,7 +1341,7 @@ func TestTestMatchTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1377,7 +1377,7 @@ func TestTestMatchTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1417,7 +1417,7 @@ func TestTestMatchTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1456,7 +1456,7 @@ func TestTestMatchTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1495,7 +1495,7 @@ func TestTestMatchTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1535,7 +1535,7 @@ func TestTestMatchTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1573,7 +1573,7 @@ func TestTestMatchTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1612,7 +1612,7 @@ func TestTestMatchTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1649,7 +1649,7 @@ func TestTestMatchTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1689,7 +1689,7 @@ func TestTestMatchTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1727,7 +1727,7 @@ func TestTestMatchTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1826,7 +1826,7 @@ func TestTestCheckTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1862,7 +1862,7 @@ func TestTestCheckTypeSetElemNestedAttrs(t *testing.T) { Deposed: []*terraform.InstanceState{ { ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1898,7 +1898,7 @@ func TestTestCheckTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1933,7 +1933,7 @@ func TestTestCheckTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -1968,7 +1968,7 @@ func TestTestCheckTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -2005,7 +2005,7 @@ func TestTestCheckTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -2041,7 +2041,7 @@ func TestTestCheckTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -2080,7 +2080,7 @@ func TestTestCheckTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -2116,7 +2116,7 @@ func TestTestCheckTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -2164,7 +2164,7 @@ func TestTestCheckTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -2215,7 +2215,7 @@ func TestTestCheckTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -2255,7 +2255,7 @@ func TestTestCheckTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -2294,7 +2294,7 @@ func TestTestCheckTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -2333,7 +2333,7 @@ func TestTestCheckTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -2373,7 +2373,7 @@ func TestTestCheckTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -2411,7 +2411,7 @@ func TestTestCheckTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -2450,7 +2450,7 @@ func TestTestCheckTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -2487,7 +2487,7 @@ func TestTestCheckTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -2527,7 +2527,7 @@ func TestTestCheckTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ @@ -2565,7 +2565,7 @@ func TestTestCheckTypeSetElemNestedAttrs(t *testing.T) { Provider: "example", Primary: &terraform.InstanceState{ ID: "11111", - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": 0, }, Attributes: map[string]string{ diff --git a/helper/resource/teststep_providers_test.go b/helper/resource/teststep_providers_test.go index 6ad3c258..6e11706c 100644 --- a/helper/resource/teststep_providers_test.go +++ b/helper/resource/teststep_providers_test.go @@ -2001,14 +2001,14 @@ func TestTest_TestStep_ExternalProvidersAndProviderFactories_NonHashiCorpNamespa return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "null_resource": { - CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + CreateContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { d.SetId("test") return nil }, - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{ @@ -2104,14 +2104,14 @@ func TestTest_TestStep_ExternalProviders_To_ProviderFactories(t *testing.T) { return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "null_resource": { - CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + CreateContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { d.SetId("test") return nil }, - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{ @@ -2154,14 +2154,14 @@ func TestTest_TestStep_ExternalProviders_To_ProviderFactories_StateUpgraders(t * return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "null_resource": { - CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + CreateContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { d.SetId("test") return nil }, - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{ @@ -2179,7 +2179,7 @@ func TestTest_TestStep_ExternalProviders_To_ProviderFactories_StateUpgraders(t * "id": cty.String, "triggers": cty.Map(cty.String), }), - Upgrade: func(ctx context.Context, rawState map[string]interface{}, meta interface{}) (map[string]interface{}, error) { + Upgrade: func(ctx context.Context, rawState map[string]any, meta any) (map[string]any, error) { // null 3.1.3 sets the id attribute to a stringified random integer. // Double check that our resource wasn't created by this TestStep. id, ok := rawState["id"].(string) @@ -2502,14 +2502,14 @@ func TestTest_TestStep_ProviderFactories_To_ExternalProviders(t *testing.T) { return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "null_resource": { - CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + CreateContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { d.SetId("test") return nil }, - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{ @@ -2552,10 +2552,10 @@ func TestTest_TestStep_ProviderFactories_Import_Inline(t *testing.T) { return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "random_password": { - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{ @@ -2576,7 +2576,7 @@ func TestTest_TestStep_ProviderFactories_Import_Inline(t *testing.T) { }, }, Importer: &schema.ResourceImporter{ - StateContext: func(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + StateContext: func(ctx context.Context, d *schema.ResourceData, meta any) ([]*schema.ResourceData, error) { val := d.Id() d.SetId("none") @@ -2623,10 +2623,10 @@ func TestTest_TestStep_ProviderFactories_Import_Inline_WithPersistMatch(t *testi return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "random_password": { - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{ @@ -2647,7 +2647,7 @@ func TestTest_TestStep_ProviderFactories_Import_Inline_WithPersistMatch(t *testi }, }, Importer: &schema.ResourceImporter{ - StateContext: func(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + StateContext: func(ctx context.Context, d *schema.ResourceData, meta any) ([]*schema.ResourceData, error) { val := d.Id() d.SetId("none") @@ -2701,14 +2701,14 @@ func TestTest_TestStep_ProviderFactories_Import_Inline_WithoutPersist(t *testing return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "random_password": { - CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + CreateContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { d.SetId("none") return nil }, - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{ @@ -2729,7 +2729,7 @@ func TestTest_TestStep_ProviderFactories_Import_Inline_WithoutPersist(t *testing }, }, Importer: &schema.ResourceImporter{ - StateContext: func(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + StateContext: func(ctx context.Context, d *schema.ResourceData, meta any) ([]*schema.ResourceData, error) { val := d.Id() d.SetId("none") @@ -3023,7 +3023,7 @@ func TestTest_TestStep_ProviderFactories_Refresh_Inline(t *testing.T) { return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "random_password": { - CreateContext: func(ctx context.Context, d *schema.ResourceData, i interface{}) diag.Diagnostics { + CreateContext: func(ctx context.Context, d *schema.ResourceData, i any) diag.Diagnostics { d.SetId("id") err := d.Set("min_special", 10) if err != nil { @@ -3031,10 +3031,10 @@ func TestTest_TestStep_ProviderFactories_Refresh_Inline(t *testing.T) { } return nil }, - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { err := d.Set("min_special", 2) if err != nil { panic(err) @@ -3094,14 +3094,14 @@ func TestTest_TestStep_ProviderFactories_CopyWorkingDir_EachTestStep(t *testing. return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "random_password": { - CreateContext: func(ctx context.Context, d *schema.ResourceData, i interface{}) diag.Diagnostics { + CreateContext: func(ctx context.Context, d *schema.ResourceData, i any) diag.Diagnostics { d.SetId("id") return nil }, - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{ @@ -3139,7 +3139,7 @@ func TestTest_TestStep_ProviderFactories_RefreshWithPlanModifier_Inline(t *testi ResourcesMap: map[string]*schema.Resource{ "random_password": { CustomizeDiff: customdiff.All( - func(ctx context.Context, d *schema.ResourceDiff, meta interface{}) error { + func(ctx context.Context, d *schema.ResourceDiff, meta any) error { special, ok := d.Get("special").(bool) if !ok { return fmt.Errorf("unexpected type %T for 'special' key", d.Get("special")) @@ -3154,7 +3154,7 @@ func TestTest_TestStep_ProviderFactories_RefreshWithPlanModifier_Inline(t *testi return nil }, ), - CreateContext: func(ctx context.Context, d *schema.ResourceData, i interface{}) diag.Diagnostics { + CreateContext: func(ctx context.Context, d *schema.ResourceData, i any) diag.Diagnostics { d.SetId("id") err := d.Set("special", false) if err != nil { @@ -3162,10 +3162,10 @@ func TestTest_TestStep_ProviderFactories_RefreshWithPlanModifier_Inline(t *testi } return nil }, - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { t := getTimeForTest() if t.After(time.Now().Add(time.Hour * 1)) { err := d.Set("special", true) @@ -3223,7 +3223,7 @@ func TestTest_TestStep_ProviderFactories_Import_Inline_With_Data_Source(t *testi return &schema.Provider{ DataSourcesMap: map[string]*schema.Resource{ "http": { - ReadContext: func(ctx context.Context, d *schema.ResourceData, i interface{}) (diags diag.Diagnostics) { + ReadContext: func(ctx context.Context, d *schema.ResourceData, i any) (diags diag.Diagnostics) { url, ok := d.Get("url").(string) if !ok { return diag.Errorf("unexpected type %T for 'url' key", d.Get("url")) @@ -3264,7 +3264,7 @@ func TestTest_TestStep_ProviderFactories_Import_Inline_With_Data_Source(t *testi return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "random_string": { - CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + CreateContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { d.SetId("none") err := d.Set("length", 4) if err != nil { @@ -3276,10 +3276,10 @@ func TestTest_TestStep_ProviderFactories_Import_Inline_With_Data_Source(t *testi } return nil }, - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{ @@ -3300,7 +3300,7 @@ func TestTest_TestStep_ProviderFactories_Import_Inline_With_Data_Source(t *testi }, }, Importer: &schema.ResourceImporter{ - StateContext: func(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + StateContext: func(ctx context.Context, d *schema.ResourceData, meta any) ([]*schema.ResourceData, error) { val := d.Id() d.SetId(val) @@ -3893,14 +3893,14 @@ func TestTest_TestStep_ProviderFactories_ConfigDirectory_StaticDirectory(t *test return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "random_id": { - CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + CreateContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { d.SetId(time.Now().String()) return nil }, - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{}, @@ -3927,14 +3927,14 @@ func TestTest_TestStep_ProviderFactories_ConfigDirectory_TestNameDirectory(t *te return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "random_id": { - CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + CreateContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { d.SetId(time.Now().String()) return nil }, - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{}, @@ -3961,14 +3961,14 @@ func TestTest_TestStep_ProviderFactories_ConfigDirectory_TestStepDirectory(t *te return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "random_id": { - CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + CreateContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { d.SetId(time.Now().String()) return nil }, - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{}, @@ -4212,14 +4212,14 @@ func TestTest_TestStep_ProviderFactories_ConfigFile_StaticFile(t *testing.T) { return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "random_id": { - CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + CreateContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { d.SetId(time.Now().String()) return nil }, - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{}, @@ -4246,14 +4246,14 @@ func TestTest_TestStep_ProviderFactories_ConfigFile_TestNameFile(t *testing.T) { return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "random_id": { - CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + CreateContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { d.SetId(time.Now().String()) return nil }, - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{}, @@ -4280,14 +4280,14 @@ func TestTest_TestStep_ProviderFactories_ConfigFile_TestStepFile(t *testing.T) { return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "random_id": { - CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + CreateContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { d.SetId(time.Now().String()) return nil }, - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{}, diff --git a/helper/resource/teststep_validate.go b/helper/resource/teststep_validate.go index 8590ca46..754683ff 100644 --- a/helper/resource/teststep_validate.go +++ b/helper/resource/teststep_validate.go @@ -116,51 +116,51 @@ func (s TestStep) validate(ctx context.Context, req testStepValidateRequest) err if req.StepConfiguration == nil && !s.ImportState && !s.RefreshState { err := fmt.Errorf("TestStep missing Config or ConfigDirectory or ConfigFile or ImportState or RefreshState") - logging.HelperResourceError(ctx, "TestStep validation error", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceError(ctx, "TestStep validation error", map[string]any{logging.KeyError: err}) return err } if req.StepConfiguration != nil && s.RefreshState { err := fmt.Errorf("TestStep cannot have Config or ConfigDirectory or ConfigFile and RefreshState") - logging.HelperResourceError(ctx, "TestStep validation error", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceError(ctx, "TestStep validation error", map[string]any{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}) + logging.HelperResourceError(ctx, "TestStep validation error", map[string]any{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}) + logging.HelperResourceError(ctx, "TestStep validation error", map[string]any{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}) + logging.HelperResourceError(ctx, "TestStep validation error", map[string]any{logging.KeyError: err}) return err } for name := range s.ExternalProviders { if _, ok := s.ProviderFactories[name]; ok { err := fmt.Errorf("TestStep provider %q set in both ExternalProviders and ProviderFactories", name) - logging.HelperResourceError(ctx, "TestStep validation error", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceError(ctx, "TestStep validation error", map[string]any{logging.KeyError: err}) return err } } if req.TestCaseHasExternalProviders && req.StepConfiguration != nil && req.StepConfiguration.HasConfigurationFiles() { err := fmt.Errorf("Providers must only be specified within the terraform configuration files when using TestStep.Config") - logging.HelperResourceError(ctx, "TestStep validation error", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceError(ctx, "TestStep validation error", map[string]any{logging.KeyError: err}) return err } if s.hasExternalProviders() && req.StepConfiguration != nil && req.StepConfiguration.HasConfigurationFiles() { err := fmt.Errorf("Providers must only be specified within the terraform configuration files when using TestStep.Config") - logging.HelperResourceError(ctx, "TestStep validation error", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceError(ctx, "TestStep validation error", map[string]any{logging.KeyError: err}) return err } @@ -168,13 +168,13 @@ func (s TestStep) validate(ctx context.Context, req testStepValidateRequest) err hasProviders, err := s.hasProviders(ctx, req.StepNumber-1, req.TestName) if err != nil { - logging.HelperResourceError(ctx, "TestStep error checking for providers", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceError(ctx, "TestStep error checking for providers", map[string]any{logging.KeyError: err}) return err } if req.TestCaseHasProviders && hasProviders { err := fmt.Errorf("Providers must only be specified either at the TestCase or TestStep level") - logging.HelperResourceError(ctx, "TestStep validation error", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceError(ctx, "TestStep validation error", map[string]any{logging.KeyError: err}) return err } @@ -184,21 +184,21 @@ func (s TestStep) validate(ctx context.Context, req testStepValidateRequest) err cfgHasProviderBlock, err = req.StepConfiguration.HasProviderBlock(ctx) if err != nil { - logging.HelperResourceError(ctx, "TestStep error checking for if configuration has provider block", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceError(ctx, "TestStep error checking for if configuration has provider block", map[string]any{logging.KeyError: err}) return err } } if !req.TestCaseHasProviders && !hasProviders && !cfgHasProviderBlock { err := fmt.Errorf("Providers must be specified at the TestCase level, or in all TestStep, or in TestStep.ConfigDirectory or TestStep.ConfigFile") - logging.HelperResourceError(ctx, "TestStep validation error", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceError(ctx, "TestStep validation error", map[string]any{logging.KeyError: err}) return err } if s.ImportState { if s.ImportStateId == "" && s.ImportStateIdFunc == nil && s.ResourceName == "" { err := fmt.Errorf("TestStep ImportState must be specified with ImportStateId, ImportStateIdFunc, or ResourceName") - logging.HelperResourceError(ctx, "TestStep validation error", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceError(ctx, "TestStep validation error", map[string]any{logging.KeyError: err}) return err } } @@ -206,38 +206,38 @@ func (s TestStep) validate(ctx context.Context, req testStepValidateRequest) err if len(s.ConfigPlanChecks.PreApply) > 0 { if req.StepConfiguration == nil { err := fmt.Errorf("TestStep ConfigPlanChecks.PreApply must only be specified with Config, ConfigDirectory or ConfigFile") - logging.HelperResourceError(ctx, "TestStep validation error", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceError(ctx, "TestStep validation error", map[string]any{logging.KeyError: err}) return err } if s.PlanOnly { err := fmt.Errorf("TestStep ConfigPlanChecks.PreApply cannot be run with PlanOnly") - logging.HelperResourceError(ctx, "TestStep validation error", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceError(ctx, "TestStep validation error", map[string]any{logging.KeyError: err}) return err } } if len(s.ConfigPlanChecks.PostApplyPreRefresh) > 0 && req.StepConfiguration == nil { err := fmt.Errorf("TestStep ConfigPlanChecks.PostApplyPreRefresh must only be specified with Config, ConfigDirectory or ConfigFile") - logging.HelperResourceError(ctx, "TestStep validation error", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceError(ctx, "TestStep validation error", map[string]any{logging.KeyError: err}) return err } if len(s.ConfigPlanChecks.PostApplyPostRefresh) > 0 && req.StepConfiguration == nil { err := fmt.Errorf("TestStep ConfigPlanChecks.PostApplyPostRefresh must only be specified with Config, ConfigDirectory or ConfigFile") - logging.HelperResourceError(ctx, "TestStep validation error", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceError(ctx, "TestStep validation error", map[string]any{logging.KeyError: err}) return err } if len(s.RefreshPlanChecks.PostRefresh) > 0 && !s.RefreshState { err := fmt.Errorf("TestStep RefreshPlanChecks.PostRefresh must only be specified with RefreshState") - logging.HelperResourceError(ctx, "TestStep validation error", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceError(ctx, "TestStep validation error", map[string]any{logging.KeyError: err}) return err } if len(s.ConfigStateChecks) > 0 && req.StepConfiguration == nil { err := fmt.Errorf("TestStep ConfigStateChecks must only be specified with Config, ConfigDirectory or ConfigFile") - logging.HelperResourceError(ctx, "TestStep validation error", map[string]interface{}{logging.KeyError: err}) + logging.HelperResourceError(ctx, "TestStep validation error", map[string]any{logging.KeyError: err}) return err } diff --git a/helper/resource/wait.go b/helper/resource/wait.go index 332791bc..874d90c5 100644 --- a/helper/resource/wait.go +++ b/helper/resource/wait.go @@ -29,7 +29,7 @@ func RetryContext(ctx context.Context, timeout time.Duration, f RetryFunc) error Target: []string{"success"}, Timeout: timeout, MinTimeout: 500 * time.Millisecond, - Refresh: func() (interface{}, string, error) { + Refresh: func() (any, string, error) { rerr := f() resultErrMu.Lock() diff --git a/internal/configs/hcl2shim/flatmap.go b/internal/configs/hcl2shim/flatmap.go index 2bad034d..99b7f2c7 100644 --- a/internal/configs/hcl2shim/flatmap.go +++ b/internal/configs/hcl2shim/flatmap.go @@ -327,7 +327,7 @@ func hcl2ValueFromFlatmapList(m map[string]string, prefix string, ty cty.Type) ( } vals = make([]cty.Value, count) - for i := 0; i < count; i++ { + for i := range count { key := prefix + strconv.Itoa(i) val, err := hcl2ValueFromFlatmapValue(m, key, ety) if err != nil { diff --git a/internal/configs/hcl2shim/values.go b/internal/configs/hcl2shim/values.go index 191f1bc7..ef8508cf 100644 --- a/internal/configs/hcl2shim/values.go +++ b/internal/configs/hcl2shim/values.go @@ -35,7 +35,7 @@ const UnknownVariableValue = "74D93920-ED26-11E3-AC10-0800200C9A66" // terraform.ResourceConfig before calling to a legacy provider, since // helper/schema (the old provider SDK) is particularly sensitive to these // subtle differences within its validation code. -func ConfigValueFromHCL2Block(v cty.Value, schema *configschema.Block) map[string]interface{} { +func ConfigValueFromHCL2Block(v cty.Value, schema *configschema.Block) map[string]any { if v.IsNull() { return nil } @@ -47,7 +47,7 @@ func ConfigValueFromHCL2Block(v cty.Value, schema *configschema.Block) map[strin } atys := v.Type().AttributeTypes() - ret := make(map[string]interface{}) + ret := make(map[string]any) for name := range schema.Attributes { if _, exists := atys[name]; !exists { @@ -87,7 +87,7 @@ func ConfigValueFromHCL2Block(v cty.Value, schema *configschema.Block) map[strin continue } - elems := make([]interface{}, 0, l) + elems := make([]any, 0, l) for it := bv.ElementIterator(); it.Next(); { _, ev := it.Element() if !ev.IsKnown() { @@ -104,7 +104,7 @@ func ConfigValueFromHCL2Block(v cty.Value, schema *configschema.Block) map[strin continue } - elems := make(map[string]interface{}) + elems := make(map[string]any) for it := bv.ElementIterator(); it.Next(); { ek, ev := it.Element() if !ev.IsKnown() { @@ -127,7 +127,7 @@ func ConfigValueFromHCL2Block(v cty.Value, schema *configschema.Block) map[strin // This function will transform a cty null value into a Go nil value, which // isn't a possible outcome of the HCL/HIL-based decoder and so callers may // need to detect and reject any null values. -func ConfigValueFromHCL2(v cty.Value) interface{} { +func ConfigValueFromHCL2(v cty.Value) any { if !v.IsKnown() { return UnknownVariableValue } @@ -165,7 +165,7 @@ func ConfigValueFromHCL2(v cty.Value) interface{} { } if v.Type().IsListType() || v.Type().IsSetType() || v.Type().IsTupleType() { - l := make([]interface{}, 0, v.LengthInt()) + l := make([]any, 0, v.LengthInt()) it := v.ElementIterator() for it.Next() { _, ev := it.Element() @@ -175,7 +175,7 @@ func ConfigValueFromHCL2(v cty.Value) interface{} { } if v.Type().IsMapType() || v.Type().IsObjectType() { - l := make(map[string]interface{}) + l := make(map[string]any) it := v.ElementIterator() for it.Next() { ek, ev := it.Element() @@ -196,7 +196,7 @@ func ConfigValueFromHCL2(v cty.Value) interface{} { // HCL2ValueFromConfigValue is the opposite of configValueFromHCL2: it takes // a value as would be returned from the old interpolator and turns it into // a cty.Value so it can be used within, for example, an HCL2 EvalContext. -func HCL2ValueFromConfigValue(v interface{}) cty.Value { +func HCL2ValueFromConfigValue(v any) cty.Value { if v == nil { return cty.NullVal(cty.DynamicPseudoType) } @@ -213,13 +213,13 @@ func HCL2ValueFromConfigValue(v interface{}) cty.Value { return cty.NumberIntVal(int64(tv)) case float64: return cty.NumberFloatVal(tv) - case []interface{}: + case []any: vals := make([]cty.Value, len(tv)) for i, ev := range tv { vals[i] = HCL2ValueFromConfigValue(ev) } return cty.TupleVal(vals) - case map[string]interface{}: + case map[string]any: vals := map[string]cty.Value{} for k, ev := range tv { vals[k] = HCL2ValueFromConfigValue(ev) diff --git a/internal/configs/hcl2shim/values_test.go b/internal/configs/hcl2shim/values_test.go index f14d7688..4450234d 100644 --- a/internal/configs/hcl2shim/values_test.go +++ b/internal/configs/hcl2shim/values_test.go @@ -19,7 +19,7 @@ func TestConfigValueFromHCL2Block(t *testing.T) { tests := []struct { Input cty.Value Schema *configschema.Block - Want map[string]interface{} + Want map[string]any }{ { cty.ObjectVal(map[string]cty.Value{ @@ -51,11 +51,11 @@ func TestConfigValueFromHCL2Block(t *testing.T) { }, }, }, - map[string]interface{}{ + map[string]any{ "name": "Ermintrude", "age": int(19), - "address": map[string]interface{}{ - "street": []interface{}{"421 Shoreham Loop"}, + "address": map[string]any{ + "street": []any{"421 Shoreham Loop"}, "city": "Fridgewater", "state": "MA", "zip": "91037", @@ -92,7 +92,7 @@ func TestConfigValueFromHCL2Block(t *testing.T) { }, }, }, - map[string]interface{}{ + map[string]any{ "name": "Ermintrude", "age": int(19), }, @@ -127,11 +127,11 @@ func TestConfigValueFromHCL2Block(t *testing.T) { }, }, }, - map[string]interface{}{ + map[string]any{ "name": "Ermintrude", "age": int(19), - "address": map[string]interface{}{ - "street": []interface{}{"421 Shoreham Loop"}, + "address": map[string]any{ + "street": []any{"421 Shoreham Loop"}, "city": "Fridgewater", "state": "MA", }, @@ -149,9 +149,9 @@ func TestConfigValueFromHCL2Block(t *testing.T) { }, }, }, - map[string]interface{}{ - "address": []interface{}{ - map[string]interface{}{}, + map[string]any{ + "address": []any{ + map[string]any{}, }, }, }, @@ -167,7 +167,7 @@ func TestConfigValueFromHCL2Block(t *testing.T) { }, }, }, - map[string]interface{}{}, + map[string]any{}, }, { cty.ObjectVal(map[string]cty.Value{ @@ -181,9 +181,9 @@ func TestConfigValueFromHCL2Block(t *testing.T) { }, }, }, - map[string]interface{}{ - "address": []interface{}{ - map[string]interface{}{}, + map[string]any{ + "address": []any{ + map[string]any{}, }, }, }, @@ -199,7 +199,7 @@ func TestConfigValueFromHCL2Block(t *testing.T) { }, }, }, - map[string]interface{}{}, + map[string]any{}, }, { cty.ObjectVal(map[string]cty.Value{ @@ -213,9 +213,9 @@ func TestConfigValueFromHCL2Block(t *testing.T) { }, }, }, - map[string]interface{}{ - "address": map[string]interface{}{ - "foo": map[string]interface{}{}, + map[string]any{ + "address": map[string]any{ + "foo": map[string]any{}, }, }, }, @@ -231,7 +231,7 @@ func TestConfigValueFromHCL2Block(t *testing.T) { }, }, }, - map[string]interface{}{}, + map[string]any{}, }, { cty.NullVal(cty.EmptyObject), @@ -258,7 +258,7 @@ func TestConfigValueFromHCL2(t *testing.T) { tests := []struct { Input cty.Value - Want interface{} + Want any }{ { cty.True, @@ -291,11 +291,11 @@ func TestConfigValueFromHCL2(t *testing.T) { "zip": cty.StringVal("91037"), }), }), - map[string]interface{}{ + map[string]any{ "name": "Ermintrude", "age": int(19), - "address": map[string]interface{}{ - "street": []interface{}{"421 Shoreham Loop"}, + "address": map[string]any{ + "street": []any{"421 Shoreham Loop"}, "city": "Fridgewater", "state": "MA", "zip": "91037", @@ -307,7 +307,7 @@ func TestConfigValueFromHCL2(t *testing.T) { "foo": cty.StringVal("bar"), "bar": cty.StringVal("baz"), }), - map[string]interface{}{ + map[string]any{ "foo": "bar", "bar": "baz", }, @@ -317,7 +317,7 @@ func TestConfigValueFromHCL2(t *testing.T) { cty.StringVal("foo"), cty.True, }), - []interface{}{ + []any{ "foo", true, }, @@ -349,7 +349,7 @@ func TestHCL2ValueFromConfigValue(t *testing.T) { t.Parallel() tests := []struct { - Input interface{} + Input any Want cty.Value }{ { @@ -389,27 +389,27 @@ func TestHCL2ValueFromConfigValue(t *testing.T) { cty.StringVal("\u00D6"), // NFC-normalized on entry into cty }, { - []interface{}{}, + []any{}, cty.EmptyTupleVal, }, { - []interface{}(nil), + []any(nil), cty.EmptyTupleVal, }, { - []interface{}{"hello", "world"}, + []any{"hello", "world"}, cty.TupleVal([]cty.Value{cty.StringVal("hello"), cty.StringVal("world")}), }, { - map[string]interface{}{}, + map[string]any{}, cty.EmptyObjectVal, }, { - map[string]interface{}(nil), + map[string]any(nil), cty.EmptyObjectVal, }, { - map[string]interface{}{ + map[string]any{ "foo": "bar", "bar": "baz", }, diff --git a/internal/logging/context_test.go b/internal/logging/context_test.go index 833b7b54..215eaffe 100644 --- a/internal/logging/context_test.go +++ b/internal/logging/context_test.go @@ -37,7 +37,7 @@ func TestTestNameContext(t *testing.T) { t.Fatalf("unable to read multiple line JSON: %s", err) } - expectedEntries := []map[string]interface{}{ + expectedEntries := []map[string]any{ { "@level": "trace", "@message": "test message", @@ -73,7 +73,7 @@ func TestTestStepNumberContext(t *testing.T) { t.Fatalf("unable to read multiple line JSON: %s", err) } - expectedEntries := []map[string]interface{}{ + expectedEntries := []map[string]any{ { "@level": "trace", "@message": "test message", @@ -109,7 +109,7 @@ func TestTestTerraformPathContext(t *testing.T) { t.Fatalf("unable to read multiple line JSON: %s", err) } - expectedEntries := []map[string]interface{}{ + expectedEntries := []map[string]any{ { "@level": "trace", "@message": "test message", @@ -145,7 +145,7 @@ func TestTestWorkingDirectoryContext(t *testing.T) { t.Fatalf("unable to read multiple line JSON: %s", err) } - expectedEntries := []map[string]interface{}{ + expectedEntries := []map[string]any{ { "@level": "trace", "@message": "test message", diff --git a/internal/logging/helper_resource.go b/internal/logging/helper_resource.go index 1b1459f2..d5d75efe 100644 --- a/internal/logging/helper_resource.go +++ b/internal/logging/helper_resource.go @@ -15,21 +15,21 @@ const ( ) // HelperResourceTrace emits a helper/resource subsystem log at TRACE level. -func HelperResourceTrace(ctx context.Context, msg string, additionalFields ...map[string]interface{}) { +func HelperResourceTrace(ctx context.Context, msg string, additionalFields ...map[string]any) { tfsdklog.SubsystemTrace(ctx, SubsystemHelperResource, msg, additionalFields...) } // HelperResourceDebug emits a helper/resource subsystem log at DEBUG level. -func HelperResourceDebug(ctx context.Context, msg string, additionalFields ...map[string]interface{}) { +func HelperResourceDebug(ctx context.Context, msg string, additionalFields ...map[string]any) { tfsdklog.SubsystemDebug(ctx, SubsystemHelperResource, msg, additionalFields...) } // HelperResourceWarn emits a helper/resource subsystem log at WARN level. -func HelperResourceWarn(ctx context.Context, msg string, additionalFields ...map[string]interface{}) { +func HelperResourceWarn(ctx context.Context, msg string, additionalFields ...map[string]any) { tfsdklog.SubsystemWarn(ctx, SubsystemHelperResource, msg, additionalFields...) } // HelperResourceError emits a helper/resource subsystem log at ERROR level. -func HelperResourceError(ctx context.Context, msg string, additionalFields ...map[string]interface{}) { +func HelperResourceError(ctx context.Context, msg string, additionalFields ...map[string]any) { tfsdklog.SubsystemError(ctx, SubsystemHelperResource, msg, additionalFields...) } diff --git a/internal/logging/helper_resource_test.go b/internal/logging/helper_resource_test.go index ee22cd3f..aa3cf80b 100644 --- a/internal/logging/helper_resource_test.go +++ b/internal/logging/helper_resource_test.go @@ -35,7 +35,7 @@ func TestHelperResourceDebug(t *testing.T) { t.Fatalf("unable to read multiple line JSON: %s", err) } - expectedEntries := []map[string]interface{}{ + expectedEntries := []map[string]any{ { "@level": "debug", "@message": "test message", @@ -68,7 +68,7 @@ func TestHelperResourceError(t *testing.T) { t.Fatalf("unable to read multiple line JSON: %s", err) } - expectedEntries := []map[string]interface{}{ + expectedEntries := []map[string]any{ { "@level": "error", "@message": "test message", @@ -101,7 +101,7 @@ func TestHelperResourceTrace(t *testing.T) { t.Fatalf("unable to read multiple line JSON: %s", err) } - expectedEntries := []map[string]interface{}{ + expectedEntries := []map[string]any{ { "@level": "trace", "@message": "test message", @@ -134,7 +134,7 @@ func TestHelperResourceWarn(t *testing.T) { t.Fatalf("unable to read multiple line JSON: %s", err) } - expectedEntries := []map[string]interface{}{ + expectedEntries := []map[string]any{ { "@level": "warn", "@message": "test message", diff --git a/internal/plugintest/guard.go b/internal/plugintest/guard.go index 77f87398..1b8a0af7 100644 --- a/internal/plugintest/guard.go +++ b/internal/plugintest/guard.go @@ -19,7 +19,7 @@ import ( // test code. type TestControl interface { Helper() - Log(args ...interface{}) + Log(args ...any) FailNow() SkipNow() Name() string @@ -34,18 +34,18 @@ type testingT struct { TestControl } -func (t testingT) Logf(f string, args ...interface{}) { +func (t testingT) Logf(f string, args ...any) { t.Helper() t.Log(fmt.Sprintf(f, args...)) } -func (t testingT) Fatalf(f string, args ...interface{}) { +func (t testingT) Fatalf(f string, args ...any) { t.Helper() t.Log(fmt.Sprintf(f, args...)) t.FailNow() } -func (t testingT) Skipf(f string, args ...interface{}) { +func (t testingT) Skipf(f string, args ...any) { t.Helper() t.Log(fmt.Sprintf(f, args...)) t.SkipNow() diff --git a/internal/plugintest/helper.go b/internal/plugintest/helper.go index 8dbcd40a..2d3628af 100644 --- a/internal/plugintest/helper.go +++ b/internal/plugintest/helper.go @@ -188,7 +188,7 @@ func (h *Helper) NewWorkingDir(ctx context.Context, t TestControl, wd string) (* logging.HelperResourceTrace( ctx, fmt.Sprintf("Setting terraform-exec log level via %s environment variable, if Terraform CLI is version 0.15 or later", EnvTfAccLog), - map[string]interface{}{logging.KeyTestTerraformLogLevel: tfAccLog}, + map[string]any{logging.KeyTestTerraformLogLevel: tfAccLog}, ) err := tf.SetLog(tfAccLog) @@ -198,7 +198,7 @@ func (h *Helper) NewWorkingDir(ctx context.Context, t TestControl, wd string) (* logging.HelperResourceError( ctx, "Unable to set terraform-exec log level", - map[string]interface{}{logging.KeyError: err.Error()}, + map[string]any{logging.KeyError: err.Error()}, ) return nil, fmt.Errorf("unable to set terraform-exec log level (%s): %w", tfAccLog, err) } @@ -206,7 +206,7 @@ func (h *Helper) NewWorkingDir(ctx context.Context, t TestControl, wd string) (* logging.HelperResourceWarn( ctx, fmt.Sprintf("Unable to set terraform-exec log level via %s environment variable, as Terraform CLI is version 0.14 or earlier. It will default to TRACE.", EnvTfAccLog), - map[string]interface{}{logging.KeyTestTerraformLogLevel: "TRACE"}, + map[string]any{logging.KeyTestTerraformLogLevel: "TRACE"}, ) } } @@ -215,7 +215,7 @@ func (h *Helper) NewWorkingDir(ctx context.Context, t TestControl, wd string) (* logging.HelperResourceTrace( ctx, fmt.Sprintf("Setting terraform-exec core log level via %s environment variable, if Terraform CLI is version 0.15 or later", EnvTfLogCore), - map[string]interface{}{ + map[string]any{ logging.KeyTestTerraformLogCoreLevel: tfLogCore, }, ) @@ -226,7 +226,7 @@ func (h *Helper) NewWorkingDir(ctx context.Context, t TestControl, wd string) (* logging.HelperResourceError( ctx, "Unable to set terraform-exec core log level", - map[string]interface{}{logging.KeyError: err.Error()}, + map[string]any{logging.KeyError: err.Error()}, ) return nil, fmt.Errorf("unable to set terraform-exec core log level (%s): %w", tfLogCore, err) } @@ -236,7 +236,7 @@ func (h *Helper) NewWorkingDir(ctx context.Context, t TestControl, wd string) (* logging.HelperResourceTrace( ctx, fmt.Sprintf("Setting terraform-exec provider log level via %s environment variable, if Terraform CLI is version 0.15 or later", EnvTfLogProvider), - map[string]interface{}{ + map[string]any{ logging.KeyTestTerraformLogCoreLevel: tfLogProvider, }, ) @@ -247,7 +247,7 @@ func (h *Helper) NewWorkingDir(ctx context.Context, t TestControl, wd string) (* logging.HelperResourceError( ctx, "Unable to set terraform-exec provider log level", - map[string]interface{}{logging.KeyError: err.Error()}, + map[string]any{logging.KeyError: err.Error()}, ) return nil, fmt.Errorf("unable to set terraform-exec provider log level (%s): %w", tfLogProvider, err) } @@ -274,7 +274,7 @@ func (h *Helper) NewWorkingDir(ctx context.Context, t TestControl, wd string) (* logging.HelperResourceTrace( ctx, fmt.Sprintf("Setting terraform-exec log path via %s environment variable", logPathEnvVar), - map[string]interface{}{logging.KeyTestTerraformLogPath: logPath}, + map[string]any{logging.KeyTestTerraformLogPath: logPath}, ) if err := tf.SetLogPath(logPath); err != nil { diff --git a/internal/plugintest/util.go b/internal/plugintest/util.go index be187a01..01606372 100644 --- a/internal/plugintest/util.go +++ b/internal/plugintest/util.go @@ -159,7 +159,7 @@ func CopyDir(src, dest, baseDirName string) error { func TestExpectTFatal(t *testing.T, testLogic func()) { t.Helper() - var recoverIface interface{} + var recoverIface any func() { defer func() { diff --git a/internal/plugintest/working_dir.go b/internal/plugintest/working_dir.go index 01b43d9f..a2259156 100644 --- a/internal/plugintest/working_dir.go +++ b/internal/plugintest/working_dir.go @@ -76,7 +76,7 @@ func (wd *WorkingDir) Close() error { } func (wd *WorkingDir) SetReattachInfo(ctx context.Context, reattachInfo tfexec.ReattachInfo) { - logging.HelperResourceTrace(ctx, "Setting Terraform CLI reattach configuration", map[string]interface{}{"tf_reattach_config": reattachInfo}) + logging.HelperResourceTrace(ctx, "Setting Terraform CLI reattach configuration", map[string]any{"tf_reattach_config": reattachInfo}) wd.reattachInfo = reattachInfo } diff --git a/internal/plugintest/working_dir_json_test.go b/internal/plugintest/working_dir_json_test.go index f29c0fed..e1a7df84 100644 --- a/internal/plugintest/working_dir_json_test.go +++ b/internal/plugintest/working_dir_json_test.go @@ -57,7 +57,7 @@ func tstProvider() *schema.Provider { } } -func resourceTstTCreate(ctx context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { +func resourceTstTCreate(ctx context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { strVal, ok := d.Get("s").(string) if !ok { return diag.Errorf("unexpected type %T for 's' key", d.Get("s")) @@ -66,14 +66,14 @@ func resourceTstTCreate(ctx context.Context, d *schema.ResourceData, _ interface return nil } -func resourceTstTRead(ctx context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { +func resourceTstTRead(ctx context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { if err := d.Set("s", d.Id()); err != nil { return diag.FromErr(err) } return nil } -func resourceTstTDelete(ctx context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { +func resourceTstTDelete(ctx context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { d.SetId("") return nil } diff --git a/plancheck/expect_sensitive_value_test.go b/plancheck/expect_sensitive_value_test.go index 1976d5b8..c3b7831b 100644 --- a/plancheck/expect_sensitive_value_test.go +++ b/plancheck/expect_sensitive_value_test.go @@ -238,17 +238,17 @@ func testProviderSensitive() *schema.Provider { return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "test_resource": { - CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + CreateContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { d.SetId("test") return nil }, - UpdateContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + UpdateContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{ diff --git a/plancheck/expect_unknown_value_test.go b/plancheck/expect_unknown_value_test.go index fd2b1c78..c7b6421e 100644 --- a/plancheck/expect_unknown_value_test.go +++ b/plancheck/expect_unknown_value_test.go @@ -414,17 +414,17 @@ func testProvider() *schema.Provider { return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "test_resource": { - CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + CreateContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { d.SetId("test") return nil }, - UpdateContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + UpdateContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{ diff --git a/statecheck/expect_known_value_test.go b/statecheck/expect_known_value_test.go index 18cc0790..74d5611d 100644 --- a/statecheck/expect_known_value_test.go +++ b/statecheck/expect_known_value_test.go @@ -1543,7 +1543,7 @@ func testProvider() *schema.Provider { return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "test_resource": { - CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + CreateContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { d.SetId("test") err := d.Set("string_computed_attribute", "computed") @@ -1553,13 +1553,13 @@ func testProvider() *schema.Provider { return nil }, - UpdateContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + UpdateContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{ diff --git a/statecheck/expect_sensitive_value_test.go b/statecheck/expect_sensitive_value_test.go index 55a44840..d698310b 100644 --- a/statecheck/expect_sensitive_value_test.go +++ b/statecheck/expect_sensitive_value_test.go @@ -224,17 +224,17 @@ func testProviderSensitive() *schema.Provider { return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{ "test_resource": { - CreateContext: func(_ context.Context, d *schema.ResourceData, _ interface{}) diag.Diagnostics { + CreateContext: func(_ context.Context, d *schema.ResourceData, _ any) diag.Diagnostics { d.SetId("test") return nil }, - UpdateContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + UpdateContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + DeleteContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, - ReadContext: func(_ context.Context, _ *schema.ResourceData, _ interface{}) diag.Diagnostics { + ReadContext: func(_ context.Context, _ *schema.ResourceData, _ any) diag.Diagnostics { return nil }, Schema: map[string]*schema.Schema{ diff --git a/terraform/diff.go b/terraform/diff.go index f70e46e4..e19c666b 100644 --- a/terraform/diff.go +++ b/terraform/diff.go @@ -6,6 +6,7 @@ package terraform import ( "fmt" "log" + "maps" "reflect" "regexp" "sort" @@ -54,7 +55,7 @@ type InstanceDiff struct { // plans but otherwise is completely ignored by Terraform core. It is // meant to be used for additional data a resource may want to pass through. // The value here must only contain Go primitives and collections. - Meta map[string]interface{} + Meta map[string]any } // Deprecated: This method is unintentionally exported by this Go module and not @@ -501,7 +502,7 @@ func (d *InstanceDiff) applyCollectionDiff(path []string, attrs map[string]strin if count != "" && count != hcl2shim.UnknownVariableValue && attrSchema.Type.Equals(cty.List(cty.String)) { // insert empty strings into missing indexes - for i := 0; i < length; i++ { + for i := range length { key := fmt.Sprintf("%s.%d", name, i) if _, ok := result[key]; !ok { result[key] = "" @@ -628,13 +629,13 @@ func countFlatmapContainerValues(key string, attrs map[string]string) string { // supported for external consumption. It will be removed in the next major // version. type ResourceAttrDiff struct { - Old string // Old Value - New string // New Value - NewComputed bool // True if new value is computed (unknown currently) - NewRemoved bool // True if this attribute is being removed - NewExtra interface{} // Extra information for the provider - RequiresNew bool // True if change requires new resource - Sensitive bool // True if the data should not be displayed in UI output + Old string // Old Value + New string // New Value + NewComputed bool // True if new value is computed (unknown currently) + NewRemoved bool // True if this attribute is being removed + NewExtra any // Extra information for the provider + RequiresNew bool // True if change requires new resource + Sensitive bool // True if the data should not be displayed in UI output Type diffAttrType } @@ -811,9 +812,7 @@ func (d *InstanceDiff) CopyAttributes() map[string]*ResourceAttrDiff { defer d.mu.Unlock() attrs := make(map[string]*ResourceAttrDiff) - for k, v := range d.Attributes { - attrs[k] = v - } + maps.Copy(attrs, d.Attributes) return attrs } diff --git a/terraform/resource.go b/terraform/resource.go index e5887b53..105f6eae 100644 --- a/terraform/resource.go +++ b/terraform/resource.go @@ -5,6 +5,7 @@ package terraform import ( "fmt" + "maps" "reflect" "sort" "strconv" @@ -44,8 +45,8 @@ type InstanceInfo struct { // version. type ResourceConfig struct { ComputedKeys []string - Raw map[string]interface{} - Config map[string]interface{} + Raw map[string]any + Config map[string]any } // NewResourceConfigRaw constructs a ResourceConfig whose content is exactly @@ -58,7 +59,7 @@ type ResourceConfig struct { // Deprecated: This function is unintentionally exported by this Go module and // not supported for external consumption. It will be removed in the next major // version. Use real Terraform configuration instead. -func NewResourceConfigRaw(raw map[string]interface{}) *ResourceConfig { +func NewResourceConfigRaw(raw map[string]any) *ResourceConfig { v := hcl2shim.HCL2ValueFromConfigValue(raw) // This is a little weird but we round-trip the value through the hcl2shim @@ -69,7 +70,7 @@ func NewResourceConfigRaw(raw map[string]interface{}) *ResourceConfig { // config maps were always distinct, and thus you could in principle mutate // one without affecting the other. (I sure hope nobody was doing that, though!) //nolint:forcetypeassert - cfg := hcl2shim.ConfigValueFromHCL2(v).(map[string]interface{}) + cfg := hcl2shim.ConfigValueFromHCL2(v).(map[string]any) return &ResourceConfig{ Raw: raw, @@ -110,7 +111,7 @@ func NewResourceConfigShimmed(val cty.Value, schema *configschema.Block) *Resour // a child block can be partially unknown. ret.ComputedKeys = newResourceConfigShimmedComputedKeys(val, "") } else { - ret.Config = make(map[string]interface{}) + ret.Config = make(map[string]any) } ret.Raw = ret.Config @@ -186,17 +187,13 @@ func (c *ResourceConfig) DeepCopy() *ResourceConfig { if c.Config != nil { copied.Config = make(map[string]any, len(c.Config)) - for key, value := range c.Config { - copied.Config[key] = value - } + maps.Copy(copied.Config, c.Config) } if c.Raw != nil { copied.Raw = make(map[string]any, len(c.Raw)) - for key, value := range c.Raw { - copied.Raw[key] = value - } + maps.Copy(copied.Raw, c.Raw) } return copied @@ -217,7 +214,7 @@ func (c *ResourceConfig) Equal(c2 *ResourceConfig) bool { // We don't compare "raw" because it is never used again after // initialization and for all intents and purposes they are equal // if the exported properties are equal. - check := [][2]interface{}{ + check := [][2]any{ {c.ComputedKeys, c2.ComputedKeys}, {c.Raw, c2.Raw}, {c.Config, c2.Config}, @@ -240,7 +237,7 @@ func (c *ResourceConfig) Equal(c2 *ResourceConfig) bool { // Deprecated: This method is unintentionally exported by this Go module and not // supported for external consumption. It will be removed in the next major // version. -func (c *ResourceConfig) Get(k string) (interface{}, bool) { +func (c *ResourceConfig) Get(k string) (any, bool) { // We aim to get a value from the configuration. If it is computed, // then we return the pure raw value. source := c.Config @@ -260,7 +257,7 @@ func (c *ResourceConfig) Get(k string) (interface{}, bool) { // Deprecated: This method is unintentionally exported by this Go module and not // supported for external consumption. It will be removed in the next major // version. -func (c *ResourceConfig) GetRaw(k string) (interface{}, bool) { +func (c *ResourceConfig) GetRaw(k string) (any, bool) { return c.get(k, c.Raw) } @@ -287,14 +284,14 @@ func (c *ResourceConfig) IsComputed(k string) bool { } func (c *ResourceConfig) get( - k string, raw map[string]interface{}) (interface{}, bool) { + k string, raw map[string]any) (any, bool) { parts := strings.Split(k, ".") if len(parts) == 1 && parts[0] == "" { parts = nil } - var current interface{} = raw - var previous interface{} = nil + var current any = raw + var previous any = nil for i, part := range parts { if current == nil { return nil, false @@ -347,7 +344,7 @@ func (c *ResourceConfig) get( // This happens when map keys contain "." and have a common // prefix so were split as path components above. actualKey := strings.Join(parts[i-1:], ".") - if prevMap, ok := previous.(map[string]interface{}); ok { + if prevMap, ok := previous.(map[string]any); ok { v, ok := prevMap[actualKey] return v, ok } diff --git a/terraform/resource_test.go b/terraform/resource_test.go index baccc425..36795ee8 100644 --- a/terraform/resource_test.go +++ b/terraform/resource_test.go @@ -32,7 +32,7 @@ func TestResourceConfigGet(t *testing.T) { Config cty.Value Schema *configschema.Block Key string - Value interface{} + Value any }{ { Config: cty.ObjectVal(map[string]cty.Value{ @@ -299,8 +299,8 @@ func TestNewResourceConfigShimmed(t *testing.T) { }, }, Expected: &ResourceConfig{ - Raw: map[string]interface{}{}, - Config: map[string]interface{}{}, + Raw: map[string]any{}, + Config: map[string]any{}, }, }, { @@ -317,10 +317,10 @@ func TestNewResourceConfigShimmed(t *testing.T) { }, }, Expected: &ResourceConfig{ - Raw: map[string]interface{}{ + Raw: map[string]any{ "foo": "bar", }, - Config: map[string]interface{}{ + Config: map[string]any{ "foo": "bar", }, }, @@ -339,8 +339,8 @@ func TestNewResourceConfigShimmed(t *testing.T) { }, }, Expected: &ResourceConfig{ - Raw: map[string]interface{}{}, - Config: map[string]interface{}{}, + Raw: map[string]any{}, + Config: map[string]any{}, }, }, { @@ -358,10 +358,10 @@ func TestNewResourceConfigShimmed(t *testing.T) { }, Expected: &ResourceConfig{ ComputedKeys: []string{"foo"}, - Raw: map[string]interface{}{ + Raw: map[string]any{ "foo": hcl2shim.UnknownVariableValue, }, - Config: map[string]interface{}{ + Config: map[string]any{ "foo": hcl2shim.UnknownVariableValue, }, }, @@ -386,11 +386,11 @@ func TestNewResourceConfigShimmed(t *testing.T) { }, Expected: &ResourceConfig{ ComputedKeys: []string{"bar", "baz"}, - Raw: map[string]interface{}{ + Raw: map[string]any{ "bar": hcl2shim.UnknownVariableValue, "baz": hcl2shim.UnknownVariableValue, }, - Config: map[string]interface{}{ + Config: map[string]any{ "bar": hcl2shim.UnknownVariableValue, "baz": hcl2shim.UnknownVariableValue, }, @@ -415,8 +415,8 @@ func TestNewResourceConfigShimmed(t *testing.T) { }, }, Expected: &ResourceConfig{ - Raw: map[string]interface{}{}, - Config: map[string]interface{}{}, + Raw: map[string]any{}, + Config: map[string]any{}, }, }, { @@ -439,11 +439,11 @@ func TestNewResourceConfigShimmed(t *testing.T) { }, Expected: &ResourceConfig{ ComputedKeys: []string{"bar", "baz"}, - Raw: map[string]interface{}{ + Raw: map[string]any{ "bar": hcl2shim.UnknownVariableValue, "baz": hcl2shim.UnknownVariableValue, }, - Config: map[string]interface{}{ + Config: map[string]any{ "bar": hcl2shim.UnknownVariableValue, "baz": hcl2shim.UnknownVariableValue, }, @@ -485,16 +485,16 @@ func TestNewResourceConfigShimmed(t *testing.T) { }, Expected: &ResourceConfig{ ComputedKeys: []string{"bar.0.baz.0.list"}, - Raw: map[string]interface{}{ - "bar": []interface{}{map[string]interface{}{ - "baz": []interface{}{map[string]interface{}{ + Raw: map[string]any{ + "bar": []any{map[string]any{ + "baz": []any{map[string]any{ "list": "74D93920-ED26-11E3-AC10-0800200C9A66", }}, }}, }, - Config: map[string]interface{}{ - "bar": []interface{}{map[string]interface{}{ - "baz": []interface{}{map[string]interface{}{ + Config: map[string]any{ + "bar": []any{map[string]any{ + "baz": []any{map[string]any{ "list": "74D93920-ED26-11E3-AC10-0800200C9A66", }}, }}, @@ -527,13 +527,13 @@ func TestNewResourceConfigShimmed(t *testing.T) { }, Expected: &ResourceConfig{ ComputedKeys: []string{"bar.0.val"}, - Raw: map[string]interface{}{ - "bar": []interface{}{map[string]interface{}{ + Raw: map[string]any{ + "bar": []any{map[string]any{ "val": "74D93920-ED26-11E3-AC10-0800200C9A66", }}, }, - Config: map[string]interface{}{ - "bar": []interface{}{map[string]interface{}{ + Config: map[string]any{ + "bar": []any{map[string]any{ "val": "74D93920-ED26-11E3-AC10-0800200C9A66", }}, }, @@ -578,32 +578,32 @@ func TestNewResourceConfigShimmed(t *testing.T) { }, Expected: &ResourceConfig{ ComputedKeys: []string{"bar.0.val", "baz.0.obj.attr", "baz.1.obj"}, - Raw: map[string]interface{}{ - "bar": []interface{}{map[string]interface{}{ + Raw: map[string]any{ + "bar": []any{map[string]any{ "val": "74D93920-ED26-11E3-AC10-0800200C9A66", }}, - "baz": []interface{}{ - map[string]interface{}{ - "obj": map[string]interface{}{ + "baz": []any{ + map[string]any{ + "obj": map[string]any{ "attr": "74D93920-ED26-11E3-AC10-0800200C9A66", }, }, - map[string]interface{}{ + map[string]any{ "obj": "74D93920-ED26-11E3-AC10-0800200C9A66", }, }, }, - Config: map[string]interface{}{ - "bar": []interface{}{map[string]interface{}{ + Config: map[string]any{ + "bar": []any{map[string]any{ "val": "74D93920-ED26-11E3-AC10-0800200C9A66", }}, - "baz": []interface{}{ - map[string]interface{}{ - "obj": map[string]interface{}{ + "baz": []any{ + map[string]any{ + "obj": map[string]any{ "attr": "74D93920-ED26-11E3-AC10-0800200C9A66", }, }, - map[string]interface{}{ + map[string]any{ "obj": "74D93920-ED26-11E3-AC10-0800200C9A66", }, }, @@ -629,8 +629,8 @@ func TestNewResourceConfigShimmed(t *testing.T) { }, }, Expected: &ResourceConfig{ - Raw: map[string]interface{}{}, - Config: map[string]interface{}{}, + Raw: map[string]any{}, + Config: map[string]any{}, }, }, } { diff --git a/terraform/state.go b/terraform/state.go index 68267757..9cf68d7d 100644 --- a/terraform/state.go +++ b/terraform/state.go @@ -10,6 +10,7 @@ import ( "errors" "fmt" "log" + "maps" "os" "reflect" "sort" @@ -401,7 +402,7 @@ func (s *State) Remove(addr ...string) error { } // Go through each result and grab what we need - removed := make(map[interface{}]struct{}) + removed := make(map[any]struct{}) for _, r := range results { // Convert the path to our own type path := append([]string{"root"}, r.Path...) @@ -657,9 +658,7 @@ func (s *State) DeepCopy() *State { if s.Remote.Config != nil { copied.Remote.Config = make(map[string]string, len(s.Remote.Config)) - for key, value := range s.Remote.Config { - copied.Remote.Config[key] = value - } + maps.Copy(copied.Remote.Config, s.Remote.Config) } } @@ -889,7 +888,7 @@ type OutputState struct { Type string `json:"type"` // Value contains the value of the output, in the structure described // by the Type field. - Value interface{} `json:"value"` + Value any `json:"value"` mu sync.Mutex } @@ -950,7 +949,7 @@ type ModuleState struct { // Locals are kept only transiently in-memory, because we can always // re-compute them. - Locals map[string]interface{} `json:"-"` + Locals map[string]any `json:"-"` // Outputs declared by the module and maintained for each module // even though only the root module technically needs to be kept. @@ -1187,9 +1186,9 @@ func (m *ModuleState) String() string { switch vTyped := v.Value.(type) { case string: buf.WriteString(fmt.Sprintf("%s = %s\n", k, vTyped)) - case []interface{}: + case []any: buf.WriteString(fmt.Sprintf("%s = %s\n", k, vTyped)) - case map[string]interface{}: + case map[string]any: var mapKeys []string for key := range vTyped { mapKeys = append(mapKeys, key) @@ -1463,7 +1462,7 @@ type InstanceState struct { // ignored by Terraform core. It's meant to be used for accounting by // external client code. The value here must only contain Go primitives // and collections. - Meta map[string]interface{} `json:"meta"` + Meta map[string]any `json:"meta"` ProviderMeta cty.Value @@ -1495,7 +1494,7 @@ func (s *InstanceState) init() { s.Attributes = make(map[string]string) } if s.Meta == nil { - s.Meta = make(map[string]interface{}) + s.Meta = make(map[string]any) } s.Ephemeral.init() } @@ -1514,7 +1513,7 @@ func NewInstanceStateShimmedFromValue(state cty.Value, schemaVersion int) *Insta return &InstanceState{ ID: attrs["id"], Attributes: attrs, - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": schemaVersion, }, } @@ -1596,9 +1595,7 @@ func (s *InstanceState) DeepCopy() *InstanceState { if s.Attributes != nil { copied.Attributes = make(map[string]string, len(s.Attributes)) - for k, v := range s.Attributes { - copied.Attributes[k] = v - } + maps.Copy(copied.Attributes, s.Attributes) } // Best effort single level copy is fine; this is not used by this Go module @@ -1606,9 +1603,7 @@ func (s *InstanceState) DeepCopy() *InstanceState { if s.Meta != nil { copied.Meta = make(map[string]any, len(s.Meta)) - for k, v := range s.Meta { - copied.Meta[k] = v - } + maps.Copy(copied.Meta, s.Meta) } return copied @@ -1710,9 +1705,7 @@ func (s *InstanceState) MergeDiff(d *InstanceDiff) *InstanceState { if s != nil { s.Lock() defer s.Unlock() - for k, v := range s.Attributes { - result.Attributes[k] = v - } + maps.Copy(result.Attributes, s.Attributes) } if d != nil { for k, diff := range d.CopyAttributes() { @@ -1806,10 +1799,7 @@ func (r resourceNameSort) Less(i, j int) bool { iParts := strings.Split(r[i], ".") jParts := strings.Split(r[j], ".") - end := len(iParts) - if len(jParts) < end { - end = len(jParts) - } + end := min(len(jParts), len(iParts)) for idx := 0; idx < end; idx++ { if iParts[idx] == jParts[idx] { diff --git a/terraform/state_filter.go b/terraform/state_filter.go index caf2c796..662aaf4b 100644 --- a/terraform/state_filter.go +++ b/terraform/state_filter.go @@ -171,7 +171,7 @@ func (f *stateFilter) filterSingle(a *resourceAddress) []*stateFilterResult { } // relevant checks for relevance of this address against the given value. -func (f *stateFilter) relevant(addr *resourceAddress, raw interface{}) bool { +func (f *stateFilter) relevant(addr *resourceAddress, raw any) bool { switch v := raw.(type) { case *ModuleState: path := v.Path[1:] @@ -226,7 +226,7 @@ type stateFilterResult struct { // Value is the actual value. This must be type switched on. It can be // any data structures that `State` can hold: `ModuleState`, // `ResourceState`, `InstanceState`. - Value interface{} + Value any } func (r *stateFilterResult) String() string { diff --git a/terraform/state_test.go b/terraform/state_test.go index 41c53685..1f3614d6 100644 --- a/terraform/state_test.go +++ b/terraform/state_test.go @@ -148,7 +148,7 @@ func TestStateDeepCopy(t *testing.T) { Resources: map[string]*ResourceState{ "test_instance.foo": { Primary: &InstanceState{ - Meta: map[string]interface{}{}, + Meta: map[string]any{}, }, }, }, @@ -168,7 +168,7 @@ func TestStateDeepCopy(t *testing.T) { Resources: map[string]*ResourceState{ "test_instance.foo": { Primary: &InstanceState{ - Meta: map[string]interface{}{}, + Meta: map[string]any{}, }, Deposed: []*InstanceState{ {ID: "test"}, @@ -270,7 +270,7 @@ func TestStateEqual(t *testing.T) { Resources: map[string]*ResourceState{ "test_instance.foo": { Primary: &InstanceState{ - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": "1", }, }, @@ -286,7 +286,7 @@ func TestStateEqual(t *testing.T) { Resources: map[string]*ResourceState{ "test_instance.foo": { Primary: &InstanceState{ - Meta: map[string]interface{}{ + Meta: map[string]any{ "schema_version": "2", }, }, @@ -308,8 +308,8 @@ func TestStateEqual(t *testing.T) { Resources: map[string]*ResourceState{ "test_instance.foo": { Primary: &InstanceState{ - Meta: map[string]interface{}{ - "timeouts": map[string]interface{}{ + Meta: map[string]any{ + "timeouts": map[string]any{ "create": 42, "read": "27", }, @@ -327,8 +327,8 @@ func TestStateEqual(t *testing.T) { Resources: map[string]*ResourceState{ "test_instance.foo": { Primary: &InstanceState{ - Meta: map[string]interface{}{ - "timeouts": map[string]interface{}{ + Meta: map[string]any{ + "timeouts": map[string]any{ "create": 42, "read": "27", }, @@ -352,8 +352,8 @@ func TestStateEqual(t *testing.T) { Resources: map[string]*ResourceState{ "test_instance.foo": { Primary: &InstanceState{ - Meta: map[string]interface{}{ - "timeouts": map[string]interface{}{ + Meta: map[string]any{ + "timeouts": map[string]any{ "create": int(42), "read": "27", }, @@ -371,8 +371,8 @@ func TestStateEqual(t *testing.T) { Resources: map[string]*ResourceState{ "test_instance.foo": { Primary: &InstanceState{ - Meta: map[string]interface{}{ - "timeouts": map[string]interface{}{ + Meta: map[string]any{ + "timeouts": map[string]any{ "create": float64(42), "read": "27", },