From 48344b001aa06be26863161a815a3029e9ed3a43 Mon Sep 17 00:00:00 2001 From: Lucas Maxwell Date: Tue, 1 Sep 2026 01:42:20 +0000 Subject: [PATCH 01/33] backport of commit f84a20b5077a89d24d33e81bfe922b4beb30db96 --- internal/cloud/backend_tfPolicyEvaluation.go | 2 +- .../cloud/backend_tfPolicyEvaluation_test.go | 46 +++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/internal/cloud/backend_tfPolicyEvaluation.go b/internal/cloud/backend_tfPolicyEvaluation.go index 2326e386a97f..0e6dc162adf4 100644 --- a/internal/cloud/backend_tfPolicyEvaluation.go +++ b/internal/cloud/backend_tfPolicyEvaluation.go @@ -35,7 +35,7 @@ func (b *Cloud) renderTFPolicyEvaluations(stopCtx context.Context, r *tfe.Run, s }) if err != nil { // Older TFE versions don't know this include; nothing to render. - if strings.HasSuffix(err.Error(), "Invalid include parameter") { + if err == tfe.ErrInvalidIncludeValue { return nil } return b.generalError("Failed to retrieve Terraform policy evaluations", err) diff --git a/internal/cloud/backend_tfPolicyEvaluation_test.go b/internal/cloud/backend_tfPolicyEvaluation_test.go index a4e5dcec38e4..3f7c6d36634a 100644 --- a/internal/cloud/backend_tfPolicyEvaluation_test.go +++ b/internal/cloud/backend_tfPolicyEvaluation_test.go @@ -5,6 +5,7 @@ package cloud import ( "context" + "errors" "strings" "testing" @@ -268,3 +269,48 @@ func TestTFPolicyStageLabel(t *testing.T) { } } } + +type runsWithReadError struct { + *MockRuns + err error +} + +func (r *runsWithReadError) ReadWithOptions(_ context.Context, _ string, _ *tfe.RunReadOptions) (*tfe.Run, error) { + return nil, r.err +} + +func TestCloud_renderTFPolicyEvaluations_invalidInclude(t *testing.T) { + b, bCleanup := testBackendWithName(t) + t.Cleanup(bCleanup) + + stream, _ := terminal.StreamsForTesting(t) + b.renderer = &jsonformat.Renderer{Streams: stream, Colorize: mockColorize()} + + b.client.Runs = &runsWithReadError{ + MockRuns: b.client.Runs.(*MockRuns), + err: tfe.ErrInvalidIncludeValue, + } + + run := &tfe.Run{ID: "run-invalid-include"} + if err := b.renderTFPolicyEvaluations(context.Background(), run); err != nil { + t.Errorf("expected nil error for invalid include value, got: %v", err) + } +} + +func TestCloud_renderTFPolicyEvaluations_error(t *testing.T) { + b, bCleanup := testBackendWithName(t) + t.Cleanup(bCleanup) + + stream, _ := terminal.StreamsForTesting(t) + b.renderer = &jsonformat.Renderer{Streams: stream, Colorize: mockColorize()} + + b.client.Runs = &runsWithReadError{ + MockRuns: b.client.Runs.(*MockRuns), + err: errors.New("error"), + } + + run := &tfe.Run{ID: "run-error"} + if err := b.renderTFPolicyEvaluations(context.Background(), run); err == nil { + t.Error("expected an error, got nil") + } +} From f8adf059ed4daeb31182abda78f015143601606f Mon Sep 17 00:00:00 2001 From: Lucas Maxwell Date: Tue, 1 Sep 2026 01:57:38 +0000 Subject: [PATCH 02/33] backport of commit 74721eea4e52d3c49a1405e2a0314694caf95107 --- .changes/v1.16/BUG FIXES-20260901-115602.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changes/v1.16/BUG FIXES-20260901-115602.yaml diff --git a/.changes/v1.16/BUG FIXES-20260901-115602.yaml b/.changes/v1.16/BUG FIXES-20260901-115602.yaml new file mode 100644 index 000000000000..5590a5d27084 --- /dev/null +++ b/.changes/v1.16/BUG FIXES-20260901-115602.yaml @@ -0,0 +1,5 @@ +kind: BUG FIXES +body: Fixed an issue where Terraform fails when rendering policy evaluation outcomes for older versions of Terraform Enterprise +time: 2026-09-01T11:56:02.703071+10:00 +custom: + Issue: "39095" From e30a20e109a282ba68e5455d4cab5a285186b316 Mon Sep 17 00:00:00 2001 From: Sebastian Rivera Date: Tue, 8 Sep 2026 13:43:53 -0400 Subject: [PATCH 03/33] chore: polish policy help and v1.17 release notes Document repeatable policy paths and query policy results without experimental build requirements. Preserve runtime behavior and cover parsing, validation, help, and mock-backed output with experiments disabled. --- .changes/footer-with-experiments.md | 1 - .../v1.17/NEW FEATURES-20260810-122653.yaml | 2 +- internal/command/arguments/query.go | 1 - internal/command/arguments/query_test.go | 12 +++++ internal/command/query.go | 5 +++ internal/command/query_test.go | 45 ++++++++----------- 6 files changed, 36 insertions(+), 30 deletions(-) diff --git a/.changes/footer-with-experiments.md b/.changes/footer-with-experiments.md index c692e8d86e8e..4ba366912e37 100644 --- a/.changes/footer-with-experiments.md +++ b/.changes/footer-with-experiments.md @@ -7,7 +7,6 @@ Experiments are only enabled in alpha releases of Terraform CLI. The following f - `terraform test`: `backend` blocks and `skip_cleanup` attributes: - Test authors can now specify `backend` blocks within `run` blocks in Terraform Test files. Run blocks with `backend` blocks will load state from the specified backend instead of starting from empty state on every execution. This allows test authors to keep long-running test infrastructure alive between test operations, saving time during regular test operations. - Test authors can now specify `skip_cleanup` attributes within test files and within run blocks. The `skip_cleanup` attribute tells `terraform test` not to clean up state files produced by run blocks with this attribute set to true. The state files for affected run blocks will be written to disk within the `.terraform` directory, where they can then be cleaned up manually using the also experimental `terraform test cleanup` command. -- `terraform query`: The experimental `-policies` flag permits specifying one or more policy set directory paths to evaluate policies against resources discovered by list blocks during a query operation. ## Previous Releases diff --git a/.changes/v1.17/NEW FEATURES-20260810-122653.yaml b/.changes/v1.17/NEW FEATURES-20260810-122653.yaml index 2bb0d618686b..3bbbf1919451 100644 --- a/.changes/v1.17/NEW FEATURES-20260810-122653.yaml +++ b/.changes/v1.17/NEW FEATURES-20260810-122653.yaml @@ -1,5 +1,5 @@ kind: NEW FEATURES -body: 'policy: Terraform Policy is now generally available. The `-policies` flag for `plan`, `apply`, and `init` no longer requires the `-allow-experimental-features` flag. See https://developer.hashicorp.com/terraform/policy for more information.' +body: 'policy: Terraform Policy is now generally available. The `-policies` flag for `plan`, `apply`, and `query` no longer requires an experimental build or the `-allow-experimental-features` flag. Query policies evaluate resources discovered by list blocks and report human-readable or JSON results. See https://developer.hashicorp.com/terraform/policy for more information.' time: 2026-08-10T12:26:53.000000+00:00 custom: Issue: "38970" diff --git a/internal/command/arguments/query.go b/internal/command/arguments/query.go index b33096aa5432..e5f06ebe0392 100644 --- a/internal/command/arguments/query.go +++ b/internal/command/arguments/query.go @@ -22,7 +22,6 @@ type Query struct { // be written to. GenerateConfigPath string - // EXPERIMENTAL // PolicyPaths contains optional paths to policy set directories that should // be evaluated during this query operation. PolicyPaths []string diff --git a/internal/command/arguments/query_test.go b/internal/command/arguments/query_test.go index c44d54d0ba2d..426fc4b7cd3a 100644 --- a/internal/command/arguments/query_test.go +++ b/internal/command/arguments/query_test.go @@ -30,6 +30,18 @@ func TestParseQuery_policies(t *testing.T) { args: []string{"-policies=/path/one", "-policies=/path/two"}, wantPolicies: []string{"/path/one", "/path/two"}, }, + "double dash equals syntax": { + args: []string{"--policies=/some/path"}, + wantPolicies: []string{"/some/path"}, + }, + "double dash space syntax": { + args: []string{"--policies", "/some/path"}, + wantPolicies: []string{"/some/path"}, + }, + "mixed spellings preserve path order": { + args: []string{"--policies=/path/one", "-policies", "/path/two", "--policies", "/path/one"}, + wantPolicies: []string{"/path/one", "/path/two", "/path/one"}, + }, } for name, tc := range testCases { diff --git a/internal/command/query.go b/internal/command/query.go index e6b1adcff466..efd57ef9bea4 100644 --- a/internal/command/query.go +++ b/internal/command/query.go @@ -34,6 +34,11 @@ Query Customization Options: The following options customize how Terraform will run the query. + -policies=path Evaluate policies from a policy set directory against + resources discovered by the query. Use this option more + than once to include multiple policy set paths. + The equivalent --policies=path spelling is also supported. + -var 'foo=bar' Set a value for one of the input variables in the query file of the configuration. Use this option more than once to set more than one variable. diff --git a/internal/command/query_test.go b/internal/command/query_test.go index a69c99c8854b..51826ba9021d 100644 --- a/internal/command/query_test.go +++ b/internal/command/query_test.go @@ -315,30 +315,24 @@ func TestQueryCommand_Validate(t *testing.T) { missingPath := filepath.Join(t.TempDir(), "does-not-exist") tests := []struct { - name string - policyPaths []string - allowExperiments bool - wantDiags tfdiags.Diagnostics + name string + policyPaths []string + wantDiags tfdiags.Diagnostics }{ { - name: "no policies, flag omitted", - policyPaths: nil, - allowExperiments: true, + name: "no policies, flag omitted", }, { - name: "single valid path", - policyPaths: []string{td}, - allowExperiments: true, + name: "single valid path", + policyPaths: []string{td}, }, { - name: "multiple valid paths", - policyPaths: []string{td, td2}, - allowExperiments: true, + name: "multiple valid paths", + policyPaths: []string{td, td2}, }, { - name: "non-existent path", - policyPaths: []string{missingPath}, - allowExperiments: true, + name: "non-existent path", + policyPaths: []string{missingPath}, wantDiags: tfdiags.Diagnostics{ tfdiags.Sourceless( tfdiags.Error, @@ -351,7 +345,7 @@ func TestQueryCommand_Validate(t *testing.T) { for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - cmd := &QueryCommand{Meta: Meta{AllowExperimentalFeatures: tc.allowExperiments}} + cmd := &QueryCommand{} got := cmd.Validate(&arguments.Query{PolicyPaths: tc.policyPaths}) if tc.wantDiags == nil { tfdiags.AssertNoDiagnostics(t, got) @@ -398,8 +392,7 @@ func TestQueryCommand_policyClientRouting(t *testing.T) { client := policy.NewTestMockClient(t) cmd := &QueryCommand{Meta: Meta{ - AllowExperimentalFeatures: true, - testingOverrides: &testingOverrides{PolicyClient: client}, + testingOverrides: &testingOverrides{PolicyClient: client}, }} op := &backendrun.Operation{PolicyPaths: tc.policyPaths} stop := cmd.configureQueryPolicyClient(be, op) @@ -672,10 +665,9 @@ func TestQueryPolicyStatusReporting(t *testing.T) { overrides.PolicyClient = policyClient view, done := testView(t) meta := Meta{ - testingOverrides: overrides, - View: view, - AllowExperimentalFeatures: true, - ProviderSource: providerSource, + testingOverrides: overrides, + View: view, + ProviderSource: providerSource, } init := &InitCommand{Meta: meta} @@ -788,10 +780,9 @@ func TestQueryPolicyStatusReporting_NoPoliciesArgument(t *testing.T) { overrides.PolicyClient = policyClient view, done := testView(t) meta := Meta{ - testingOverrides: overrides, - View: view, - AllowExperimentalFeatures: true, - ProviderSource: providerSource, + testingOverrides: overrides, + View: view, + ProviderSource: providerSource, } init := &InitCommand{Meta: meta} From 75f75e6b8debd5ce01987def01a443fcbcd61830 Mon Sep 17 00:00:00 2001 From: hc-github-team-tf-core <82990137+hc-github-team-tf-core@users.noreply.github.com> Date: Wed, 9 Sep 2026 17:13:47 +0100 Subject: [PATCH 04/33] Prepare before 1.17.0-beta1 release (#39167) Co-authored-by: hc-github-team-tf-core --- CHANGELOG.md | 23 ++++++++++------------- version/VERSION | 2 +- 2 files changed, 11 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd6a3cacd975..71e7b2309793 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,21 @@ -## 1.17.0 (Unreleased) +## 1.17.0-beta1 (September 09, 2026) NEW FEATURES: +* Terraform now supports variables and locals in provider requirements ([#39153](https://github.com/hashicorp/terraform/issues/39153)) + * A new `-minimal-refresh` planning option has been added, which will only refresh resources that have proposed changes. ([#35290](https://github.com/hashicorp/terraform/issues/35290)) +* policy: Terraform Policy is now generally available. The `-policies` flag for `plan`, `apply`, and `init` no longer requires the `-allow-experimental-features` flag. See https://developer.hashicorp.com/terraform/policy for more information. ([#38970](https://github.com/hashicorp/terraform/issues/38970)) + ENHANCEMENTS: * command/init: Enrich log messages with provider versions ([#38918](https://github.com/hashicorp/terraform/issues/38918)) +* test: Add mock_provider support for ephemeral resources ([#38928](https://github.com/hashicorp/terraform/issues/38928)) + * command/login: display warning after successful login if user is subject to an organization's TTL policy @@ -19,7 +25,9 @@ BUG FIXES: * ephemeral: Terraform will now use and display diagnostics raised when _renewing_ an ephemeral resource. This may cause warnings to appear that previously were lost. We expect that any error diagnostics that were previously lost would have caused confusing downstream errors, so we do not anticipate this change to be breaking. ([#38989](https://github.com/hashicorp/terraform/issues/38989)) -* Fix panic when import identity references sensitive value ([#39013](https://github.com/hashicorp/terraform/issues/39013)) +* test: Deterministic dependency ordering in cleanup graph ([#38247](https://github.com/hashicorp/terraform/issues/38247)) + +* query: report Unknown and N/A results for policy evaluations of discovered resources ([#39058](https://github.com/hashicorp/terraform/issues/39058)) NOTES: @@ -27,17 +35,6 @@ NOTES: * version: JSON output now includes a new `format_version` field, which will enable safer future changes of the command's JSON output format. It is assumed existing tooling ignores unknown fields and therefore this change should not be breaking in itself but we advice consumers to pay attention to `format_version` in future releases and/or use latest version of hashicorp/terraform-json & hashicorp/terraform-exec which does. ([#38930](https://github.com/hashicorp/terraform/issues/38930)) -EXPERIMENTS: - -Experiments are only enabled in alpha releases of Terraform CLI. The following features are not yet available in stable releases. - -- The experimental "deferred actions" feature, enabled by passing the `-allow-deferral` option to `terraform plan`, permits `count` and `for_each` arguments in `module`, `resource`, and `data` blocks to have unknown values and allows providers to react more flexibly to unknown values. -- `terraform test cleanup`: The experimental `test cleanup` command. In experimental builds of Terraform, a manifest file and state files for each failed cleanup operation during test operations are saved within the `.terraform` local directory. The `test cleanup` command will attempt to clean up the local state files left behind automatically, without requiring manual intervention. -- `terraform test`: `backend` blocks and `skip_cleanup` attributes: - - Test authors can now specify `backend` blocks within `run` blocks in Terraform Test files. Run blocks with `backend` blocks will load state from the specified backend instead of starting from empty state on every execution. This allows test authors to keep long-running test infrastructure alive between test operations, saving time during regular test operations. - - Test authors can now specify `skip_cleanup` attributes within test files and within run blocks. The `skip_cleanup` attribute tells `terraform test` not to clean up state files produced by run blocks with this attribute set to true. The state files for affected run blocks will be written to disk within the `.terraform` directory, where they can then be cleaned up manually using the also experimental `terraform test cleanup` command. -- `terraform query`: The experimental `-policies` flag permits specifying one or more policy set directory paths to evaluate policies against resources discovered by list blocks during a query operation. - ## Previous Releases For information on prior major and minor releases, refer to their changelogs: diff --git a/version/VERSION b/version/VERSION index ee8855caa4a7..cedb0c425411 100644 --- a/version/VERSION +++ b/version/VERSION @@ -1 +1 @@ -1.17.0-dev +1.17.0-beta1 From 754ba996cd7ff5233f3566c222d5af61f67d7ee3 Mon Sep 17 00:00:00 2001 From: hc-github-team-tf-core <82990137+hc-github-team-tf-core@users.noreply.github.com> Date: Wed, 9 Sep 2026 18:57:09 +0100 Subject: [PATCH 05/33] Cleanup after 1.17.0-beta1 release (#39168) Co-authored-by: hc-github-team-tf-core --- CHANGELOG.md | 13 ++++++++++++- version/VERSION | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71e7b2309793..d0d72ba56c09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.17.0-beta1 (September 09, 2026) +## 1.17.0 (Unreleased) NEW FEATURES: @@ -35,6 +35,17 @@ NOTES: * version: JSON output now includes a new `format_version` field, which will enable safer future changes of the command's JSON output format. It is assumed existing tooling ignores unknown fields and therefore this change should not be breaking in itself but we advice consumers to pay attention to `format_version` in future releases and/or use latest version of hashicorp/terraform-json & hashicorp/terraform-exec which does. ([#38930](https://github.com/hashicorp/terraform/issues/38930)) +EXPERIMENTS: + +Experiments are only enabled in alpha releases of Terraform CLI. The following features are not yet available in stable releases. + +- The experimental "deferred actions" feature, enabled by passing the `-allow-deferral` option to `terraform plan`, permits `count` and `for_each` arguments in `module`, `resource`, and `data` blocks to have unknown values and allows providers to react more flexibly to unknown values. +- `terraform test cleanup`: The experimental `test cleanup` command. In experimental builds of Terraform, a manifest file and state files for each failed cleanup operation during test operations are saved within the `.terraform` local directory. The `test cleanup` command will attempt to clean up the local state files left behind automatically, without requiring manual intervention. +- `terraform test`: `backend` blocks and `skip_cleanup` attributes: + - Test authors can now specify `backend` blocks within `run` blocks in Terraform Test files. Run blocks with `backend` blocks will load state from the specified backend instead of starting from empty state on every execution. This allows test authors to keep long-running test infrastructure alive between test operations, saving time during regular test operations. + - Test authors can now specify `skip_cleanup` attributes within test files and within run blocks. The `skip_cleanup` attribute tells `terraform test` not to clean up state files produced by run blocks with this attribute set to true. The state files for affected run blocks will be written to disk within the `.terraform` directory, where they can then be cleaned up manually using the also experimental `terraform test cleanup` command. +- `terraform query`: The experimental `-policies` flag permits specifying one or more policy set directory paths to evaluate policies against resources discovered by list blocks during a query operation. + ## Previous Releases For information on prior major and minor releases, refer to their changelogs: diff --git a/version/VERSION b/version/VERSION index cedb0c425411..ee8855caa4a7 100644 --- a/version/VERSION +++ b/version/VERSION @@ -1 +1 @@ -1.17.0-beta1 +1.17.0-dev From a1806d3f1cd0bbaaefefebecbcf944b3af536c79 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 9 Sep 2026 19:03:29 +0000 Subject: [PATCH 06/33] backport of commit c239d42d8d4053b1266d957e1bd960d93fc9f21b --- internal/plans/action.go | 3 ++- internal/plans/action_string.go | 12 +++++---- internal/plans/changes.go | 4 +-- internal/plans/planfile/tfplan.go | 8 ++++-- internal/plans/planfile/tfplan_test.go | 33 +++++++++++++++++++++++++ internal/plans/planproto/convert.go | 8 ++++++ internal/plans/planproto/planfile.pb.go | 27 +++++++++++--------- internal/plans/planproto/planfile.proto | 1 + 8 files changed, 75 insertions(+), 21 deletions(-) diff --git a/internal/plans/action.go b/internal/plans/action.go index 1dfc871886ff..6904646f57d3 100644 --- a/internal/plans/action.go +++ b/internal/plans/action.go @@ -14,6 +14,7 @@ const ( CreateThenDelete Action = '±' Delete Action = '-' Forget Action = '.' + ForgetThenCreate Action = '∔' CreateThenForget Action = '⨥' Open Action = '⟃' Renew Action = '⟳' @@ -25,5 +26,5 @@ const ( // IsReplace returns true if the action is one of the actions that // represent replacing an existing object with a new object. func (a Action) IsReplace() bool { - return a == DeleteThenCreate || a == CreateThenDelete || a == CreateThenForget + return a == DeleteThenCreate || a == CreateThenDelete || a == ForgetThenCreate || a == CreateThenForget } diff --git a/internal/plans/action_string.go b/internal/plans/action_string.go index 35f6c13e6918..16683db5384a 100644 --- a/internal/plans/action_string.go +++ b/internal/plans/action_string.go @@ -16,13 +16,14 @@ func _() { _ = x[CreateThenDelete-177] _ = x[Delete-45] _ = x[Forget-46] + _ = x[ForgetThenCreate-8724] _ = x[CreateThenForget-10789] _ = x[Open-10179] _ = x[Renew-10227] _ = x[Close-10959] } -const _Action_name = "NoOpCreateDeleteForgetUpdateCreateThenDeleteReadDeleteThenCreateOpenRenewCreateThenForgetClose" +const _Action_name = "NoOpCreateDeleteForgetUpdateCreateThenDeleteReadDeleteThenCreateForgetThenCreateOpenRenewCreateThenForgetClose" var _Action_map = map[Action]string{ 0: _Action_name[0:4], @@ -33,10 +34,11 @@ var _Action_map = map[Action]string{ 177: _Action_name[28:44], 8592: _Action_name[44:48], 8723: _Action_name[48:64], - 10179: _Action_name[64:68], - 10227: _Action_name[68:73], - 10789: _Action_name[73:89], - 10959: _Action_name[89:94], + 8724: _Action_name[64:80], + 10179: _Action_name[80:84], + 10227: _Action_name[84:89], + 10789: _Action_name[89:105], + 10959: _Action_name[105:110], } func (i Action) String() string { diff --git a/internal/plans/changes.go b/internal/plans/changes.go index 1715de582b96..3cde7d5e98b7 100644 --- a/internal/plans/changes.go +++ b/internal/plans/changes.go @@ -455,7 +455,7 @@ func (rc *ResourceInstanceChange) Simplify(destroying bool) *ResourceInstanceCha switch rc.Action { case Delete: // We'll fall out and just return rc verbatim, then. - case CreateThenDelete, DeleteThenCreate, CreateThenForget: + case CreateThenDelete, DeleteThenCreate, ForgetThenCreate, CreateThenForget: return &ResourceInstanceChange{ Addr: rc.Addr, DeposedKey: rc.DeposedKey, @@ -506,7 +506,7 @@ func (rc *ResourceInstanceChange) Simplify(destroying bool) *ResourceInstanceCha GeneratedConfig: rc.GeneratedConfig, }, } - case CreateThenDelete, DeleteThenCreate, CreateThenForget: + case CreateThenDelete, DeleteThenCreate, ForgetThenCreate, CreateThenForget: return &ResourceInstanceChange{ Addr: rc.Addr, DeposedKey: rc.DeposedKey, diff --git a/internal/plans/planfile/tfplan.go b/internal/plans/planfile/tfplan.go index 65fb6091177e..96c65d8339c1 100644 --- a/internal/plans/planfile/tfplan.go +++ b/internal/plans/planfile/tfplan.go @@ -407,6 +407,8 @@ func ActionFromProto(rawAction planproto.Action) (plans.Action, error) { return plans.DeleteThenCreate, nil case planproto.Action_FORGET: return plans.Forget, nil + case planproto.Action_FORGET_THEN_CREATE: + return plans.ForgetThenCreate, nil case planproto.Action_CREATE_THEN_FORGET: return plans.CreateThenForget, nil default: @@ -453,7 +455,7 @@ func changeFromTfplan(rawChange *planproto.Change) (*plans.ChangeSrc, error) { afterIdx = 1 case plans.Forget: beforeIdx = 0 - case plans.CreateThenForget: + case plans.ForgetThenCreate, plans.CreateThenForget: beforeIdx = 0 afterIdx = 1 default: @@ -934,6 +936,8 @@ func ActionToProto(action plans.Action) (planproto.Action, error) { return planproto.Action_CREATE_THEN_DELETE, nil case plans.Forget: return planproto.Action_FORGET, nil + case plans.ForgetThenCreate: + return planproto.Action_FORGET_THEN_CREATE, nil case plans.CreateThenForget: return planproto.Action_CREATE_THEN_FORGET, nil default: @@ -1001,7 +1005,7 @@ func changeToTfplan(change *plans.ChangeSrc) (*planproto.Change, error) { ret.Values = []*planproto.DynamicValue{before, after} case planproto.Action_FORGET: ret.Values = []*planproto.DynamicValue{before} - case planproto.Action_CREATE_THEN_FORGET: + case planproto.Action_FORGET_THEN_CREATE, planproto.Action_CREATE_THEN_FORGET: ret.Values = []*planproto.DynamicValue{before, after} default: return nil, fmt.Errorf("invalid change action %s", change.Action) diff --git a/internal/plans/planfile/tfplan_test.go b/internal/plans/planfile/tfplan_test.go index 3270633e2b2f..5382f1759ece 100644 --- a/internal/plans/planfile/tfplan_test.go +++ b/internal/plans/planfile/tfplan_test.go @@ -23,6 +23,39 @@ import ( "github.com/hashicorp/terraform/internal/states" ) +func TestActionProtoRoundTrip_forgetThenCreate(t *testing.T) { + before, err := plans.NewDynamicValue(cty.StringVal("before"), cty.String) + if err != nil { + t.Fatal(err) + } + after, err := plans.NewDynamicValue(cty.StringVal("after"), cty.String) + if err != nil { + t.Fatal(err) + } + + raw, err := changeToTfplan(&plans.ChangeSrc{ + Action: plans.ForgetThenCreate, + Before: before, + After: after, + }) + if err != nil { + t.Fatal(err) + } + got, err := changeFromTfplan(raw) + if err != nil { + t.Fatal(err) + } + if got.Action != plans.ForgetThenCreate { + t.Fatalf("wrong action after round trip: got %s, want %s", got.Action, plans.ForgetThenCreate) + } + if !bytes.Equal(got.Before, before) { + t.Fatalf("wrong before value after round trip") + } + if !bytes.Equal(got.After, after) { + t.Fatalf("wrong after value after round trip") + } +} + // TestTFPlanRoundTrip writes a plan to a planfile, reads the contents of the planfile, // and asserts that the read data matches the written data. func TestTFPlanRoundTrip(t *testing.T) { diff --git a/internal/plans/planproto/convert.go b/internal/plans/planproto/convert.go index f1fe0bc741a4..987664b7240e 100644 --- a/internal/plans/planproto/convert.go +++ b/internal/plans/planproto/convert.go @@ -77,6 +77,10 @@ func NewAction(action plans.Action) Action { return Action_CREATE_THEN_DELETE case plans.Forget: return Action_FORGET + case plans.ForgetThenCreate: + return Action_FORGET_THEN_CREATE + case plans.CreateThenForget: + return Action_CREATE_THEN_FORGET default: // The above should be exhaustive for all possible actions panic(fmt.Sprintf("unsupported change action %s", action)) @@ -101,6 +105,10 @@ func FromAction(protoAction Action) (plans.Action, error) { return plans.CreateThenDelete, nil case Action_FORGET: return plans.Forget, nil + case Action_FORGET_THEN_CREATE: + return plans.ForgetThenCreate, nil + case Action_CREATE_THEN_FORGET: + return plans.CreateThenForget, nil default: return plans.NoOp, fmt.Errorf("unsupported action %s", protoAction) } diff --git a/internal/plans/planproto/planfile.pb.go b/internal/plans/planproto/planfile.pb.go index f0942ef62d53..dade2bdecc27 100644 --- a/internal/plans/planproto/planfile.pb.go +++ b/internal/plans/planproto/planfile.pb.go @@ -88,20 +88,22 @@ const ( Action_CREATE_THEN_DELETE Action = 7 Action_FORGET Action = 8 Action_CREATE_THEN_FORGET Action = 9 + Action_FORGET_THEN_CREATE Action = 10 ) // Enum value maps for Action. var ( Action_name = map[int32]string{ - 0: "NOOP", - 1: "CREATE", - 2: "READ", - 3: "UPDATE", - 5: "DELETE", - 6: "DELETE_THEN_CREATE", - 7: "CREATE_THEN_DELETE", - 8: "FORGET", - 9: "CREATE_THEN_FORGET", + 0: "NOOP", + 1: "CREATE", + 2: "READ", + 3: "UPDATE", + 5: "DELETE", + 6: "DELETE_THEN_CREATE", + 7: "CREATE_THEN_DELETE", + 8: "FORGET", + 9: "CREATE_THEN_FORGET", + 10: "FORGET_THEN_CREATE", } Action_value = map[string]int32{ "NOOP": 0, @@ -113,6 +115,7 @@ var ( "CREATE_THEN_DELETE": 7, "FORGET": 8, "CREATE_THEN_FORGET": 9, + "FORGET_THEN_CREATE": 10, } ) @@ -2441,7 +2444,7 @@ const file_planfile_proto_rawDesc = "" + "\n" + "\x06NORMAL\x10\x00\x12\v\n" + "\aDESTROY\x10\x01\x12\x10\n" + - "\fREFRESH_ONLY\x10\x02*\x94\x01\n" + + "\fREFRESH_ONLY\x10\x02*\xac\x01\n" + "\x06Action\x12\b\n" + "\x04NOOP\x10\x00\x12\n" + "\n" + @@ -2455,7 +2458,9 @@ const file_planfile_proto_rawDesc = "" + "\x12CREATE_THEN_DELETE\x10\a\x12\n" + "\n" + "\x06FORGET\x10\b\x12\x16\n" + - "\x12CREATE_THEN_FORGET\x10\t*\xc8\x03\n" + + "\x12CREATE_THEN_FORGET\x10\t\x12\x16\n" + + "\x12FORGET_THEN_CREATE\x10\n" + + "*\xc8\x03\n" + "\x1cResourceInstanceActionReason\x12\b\n" + "\x04NONE\x10\x00\x12\x1b\n" + "\x17REPLACE_BECAUSE_TAINTED\x10\x01\x12\x16\n" + diff --git a/internal/plans/planproto/planfile.proto b/internal/plans/planproto/planfile.proto index 56e38d34803e..8bc75dc52975 100644 --- a/internal/plans/planproto/planfile.proto +++ b/internal/plans/planproto/planfile.proto @@ -184,6 +184,7 @@ enum Action { CREATE_THEN_DELETE = 7; FORGET = 8; CREATE_THEN_FORGET = 9; + FORGET_THEN_CREATE = 10; } // Change represents a change made to some object, transforming it from an old From 73261450f1c3afbcce04fb2b89a39bd8853ff123 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 9 Sep 2026 19:04:38 +0000 Subject: [PATCH 07/33] backport of commit 567e33121b93c4e0080a957306018306155e0fd0 --- internal/stacks/stackruntime/hooks/component_instance.go | 2 +- .../stacks/stackruntime/internal/stackeval/applying.go | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/internal/stacks/stackruntime/hooks/component_instance.go b/internal/stacks/stackruntime/hooks/component_instance.go index 6005b8f03ca5..6866917eb2ca 100644 --- a/internal/stacks/stackruntime/hooks/component_instance.go +++ b/internal/stacks/stackruntime/hooks/component_instance.go @@ -88,7 +88,7 @@ func (cic *ComponentInstanceChange) CountNewAction(action plans.Action) { cic.Remove++ case plans.Forget: cic.Forget++ - case plans.CreateThenForget: + case plans.ForgetThenCreate, plans.CreateThenForget: cic.Add++ cic.Forget++ } diff --git a/internal/stacks/stackruntime/internal/stackeval/applying.go b/internal/stacks/stackruntime/internal/stackeval/applying.go index 060ca891bc5e..85fc2f94e04b 100644 --- a/internal/stacks/stackruntime/internal/stackeval/applying.go +++ b/internal/stacks/stackruntime/internal/stackeval/applying.go @@ -297,6 +297,11 @@ func ApplyComponentPlan(ctx context.Context, main *Main, plan *plans.Plan, requi for _, rioAddr := range applied { action := tfHook.ResourceInstanceObjectAppliedAction(rioAddr) cic.CountNewAction(action) + if change, ok := stackPlan.ResourceInstancePlanned.GetOk(rioAddr); ok { + if change.Action == plans.ForgetThenCreate || change.Action == plans.CreateThenForget { + cic.Forget++ + } + } } // The state management actions (move, import, forget) don't emit @@ -332,7 +337,7 @@ func ApplyComponentPlan(ctx context.Context, main *Main, plan *plans.Plan, requi if change.Moved() { cic.Move++ } - case plans.Forget: + case plans.Forget, plans.ForgetThenCreate: cic.Forget++ } } From dec52714057d645df8fb075de6cb986fb13bbbfe Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 9 Sep 2026 19:05:42 +0000 Subject: [PATCH 08/33] backport of commit 1b00966453c269e698b05cdf7b017ce10c1eed4f --- internal/rpcapi/terraform1/stacks/conversion.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/rpcapi/terraform1/stacks/conversion.go b/internal/rpcapi/terraform1/stacks/conversion.go index 4d87fdfe5827..5207ec27079d 100644 --- a/internal/rpcapi/terraform1/stacks/conversion.go +++ b/internal/rpcapi/terraform1/stacks/conversion.go @@ -39,6 +39,8 @@ func ChangeTypesForPlanAction(action plans.Action) ([]ChangeType, error) { return []ChangeType{ChangeType_CREATE, ChangeType_DELETE}, nil case plans.Forget: return []ChangeType{ChangeType_FORGET}, nil + case plans.ForgetThenCreate: + return []ChangeType{ChangeType_FORGET, ChangeType_CREATE}, nil case plans.CreateThenForget: return []ChangeType{ChangeType_CREATE, ChangeType_FORGET}, nil default: From 75f0466a83dab1ba1c1f35d6be71a964c3f0d5b4 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 9 Sep 2026 19:06:05 +0000 Subject: [PATCH 09/33] backport of commit 2dce9e423fec6e49665dbf7837531eba7fc712fd --- internal/command/format/format.go | 2 ++ internal/command/jsonformat/plan.go | 14 ++++++++++-- internal/command/jsonformat/plan_test.go | 27 ++++++++++++++++++++++++ internal/command/jsonplan/plan.go | 6 ++++++ internal/command/views/hook_count.go | 4 ++++ internal/command/views/json/change.go | 2 +- internal/command/views/json/hook.go | 6 +++--- internal/command/views/operation.go | 2 ++ 8 files changed, 57 insertions(+), 6 deletions(-) diff --git a/internal/command/format/format.go b/internal/command/format/format.go index 9a79763a216e..704371ce4dc3 100644 --- a/internal/command/format/format.go +++ b/internal/command/format/format.go @@ -20,6 +20,8 @@ func DiffActionSymbol(action plans.Action) string { switch action { case plans.DeleteThenCreate: return "[red]-[reset]/[green]+[reset]" + case plans.ForgetThenCreate: + return "[red].[reset]/[green]+[reset]" case plans.CreateThenDelete: return "[green]+[reset]/[red]-[reset]" case plans.Create: diff --git a/internal/command/jsonformat/plan.go b/internal/command/jsonformat/plan.go index e9624c2fc48e..7a45017bfc5a 100644 --- a/internal/command/jsonformat/plan.go +++ b/internal/command/jsonformat/plan.go @@ -220,6 +220,12 @@ func (plan Plan) renderHuman(renderer Renderer, mode plans.Mode, opts ...plans.Q if counts[plans.CreateThenDelete] > 0 { renderer.Streams.Println(renderer.Colorize.Color(actionDescription(plans.CreateThenDelete))) } + if counts[plans.ForgetThenCreate] > 0 { + renderer.Streams.Println(renderer.Colorize.Color(actionDescription(plans.ForgetThenCreate))) + } + if counts[plans.CreateThenForget] > 0 { + renderer.Streams.Println(renderer.Colorize.Color(actionDescription(plans.CreateThenForget))) + } if counts[plans.Read] > 0 { renderer.Streams.Println(renderer.Colorize.Color(actionDescription(plans.Read))) } @@ -246,7 +252,7 @@ func (plan Plan) renderHuman(renderer Renderer, mode plans.Mode, opts ...plans.Q buf.WriteString(fmt.Sprintf("%d to import, ", importingCount)) } buf.WriteString(fmt.Sprintf("%d to add, %d to change, %d to destroy.", - counts[plans.Create]+counts[plans.DeleteThenCreate]+counts[plans.CreateThenDelete]+counts[plans.CreateThenForget], + counts[plans.Create]+counts[plans.DeleteThenCreate]+counts[plans.CreateThenDelete]+counts[plans.ForgetThenCreate]+counts[plans.CreateThenForget], counts[plans.Update], counts[plans.Delete]+counts[plans.DeleteThenCreate]+counts[plans.CreateThenDelete]), ) @@ -563,7 +569,7 @@ func resourceChangeComment(resource jsonplan.ResourceChange, action plans.Action default: buf.WriteString(fmt.Sprintf("[bold] # %s[reset] must be [bold][red]replaced[reset]", dispAddr)) } - case plans.CreateThenForget: + case plans.ForgetThenCreate, plans.CreateThenForget: buf.WriteString(fmt.Sprintf("[bold] # %s[reset] must be replaced, but the existing object will not be destroyed", dispAddr)) buf.WriteString("\n # (destroy = false is set in the configuration)") case plans.Forget: @@ -692,6 +698,10 @@ func actionDescription(action plans.Action) string { return "[green]+[reset]/[red]-[reset] create replacement and then destroy" case plans.DeleteThenCreate: return "[red]-[reset]/[green]+[reset] destroy and then create replacement" + case plans.ForgetThenCreate: + return "[red].[reset]/[green]+[reset] forget and then create replacement" + case plans.CreateThenForget: + return "[green]+[reset]/[red].[reset] create replacement and then forget" case plans.Read: return " [cyan]<=[reset] read (data resources)" default: diff --git a/internal/command/jsonformat/plan_test.go b/internal/command/jsonformat/plan_test.go index 9acb39b45bbd..16997e81eb52 100644 --- a/internal/command/jsonformat/plan_test.go +++ b/internal/command/jsonformat/plan_test.go @@ -884,6 +884,33 @@ func TestResourceChange_primitiveTypes(t *testing.T) { +/. resource "test_instance" "example" { ~ ami = "ami-BEFORE" -> "ami-AFTER" # forces replacement ~ id = "i-02ae66f368e8518a9" -> "i-02999999999999999" + }`, + }, + "forget-then-create": { + Action: plans.ForgetThenCreate, + Mode: addrs.ManagedResourceMode, + Before: cty.ObjectVal(map[string]cty.Value{ + "id": cty.StringVal("i-02ae66f368e8518a9"), + "ami": cty.StringVal("ami-BEFORE"), + }), + After: cty.ObjectVal(map[string]cty.Value{ + "id": cty.StringVal("i-02999999999999999"), + "ami": cty.StringVal("ami-AFTER"), + }), + Schema: &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "id": {Type: cty.String, Computed: true}, + "ami": {Type: cty.String, Optional: true}, + }, + }, + RequiredReplace: cty.NewPathSet(cty.Path{ + cty.GetAttrStep{Name: "ami"}, + }), + ExpectedOutput: ` # test_instance.example must be replaced, but the existing object will not be destroyed + # (destroy = false is set in the configuration) +./+ resource "test_instance" "example" { + ~ ami = "ami-BEFORE" -> "ami-AFTER" # forces replacement + ~ id = "i-02ae66f368e8518a9" -> "i-02999999999999999" }`, }, "string in-place update": { diff --git a/internal/command/jsonplan/plan.go b/internal/command/jsonplan/plan.go index 64d52c86e56f..fbefe31eeea0 100644 --- a/internal/command/jsonplan/plan.go +++ b/internal/command/jsonplan/plan.go @@ -991,6 +991,8 @@ func actionString(action string) []string { return []string{"delete", "create"} case action == "Forget": return []string{"forget"} + case action == "ForgetThenCreate": + return []string{"forget", "create"} case action == "CreateThenForget": return []string{"create", "forget"} default: @@ -1012,6 +1014,10 @@ func UnmarshalActions(actions []string) plans.Action { if actions[0] == "create" && actions[1] == "forget" { return plans.CreateThenForget } + + if actions[0] == "forget" && actions[1] == "create" { + return plans.ForgetThenCreate + } } if len(actions) == 1 { diff --git a/internal/command/views/hook_count.go b/internal/command/views/hook_count.go index 8d5b579f4b22..a858a3cb537f 100644 --- a/internal/command/views/hook_count.go +++ b/internal/command/views/hook_count.go @@ -63,6 +63,8 @@ func (h *countHook) PostApply(id terraform.HookResourceIdentity, dk addrs.Depose case plans.CreateThenDelete, plans.DeleteThenCreate: h.Added++ h.Removed++ + case plans.ForgetThenCreate, plans.CreateThenForget: + h.Added++ case plans.Create: h.Added++ case plans.Delete: @@ -94,6 +96,8 @@ func (h *countHook) PostDiff(id terraform.HookResourceIdentity, dk addrs.Deposed switch action { case plans.CreateThenDelete, plans.DeleteThenCreate: h.ToRemoveAndAdd += 1 + case plans.ForgetThenCreate, plans.CreateThenForget: + h.ToAdd += 1 case plans.Create: h.ToAdd += 1 case plans.Delete: diff --git a/internal/command/views/json/change.go b/internal/command/views/json/change.go index e44496d44df0..09d5c5cdac30 100644 --- a/internal/command/views/json/change.go +++ b/internal/command/views/json/change.go @@ -134,7 +134,7 @@ func changeAction(action plans.Action) ChangeAction { return ActionRead case plans.Update: return ActionUpdate - case plans.DeleteThenCreate, plans.CreateThenDelete, plans.CreateThenForget: + case plans.DeleteThenCreate, plans.CreateThenDelete, plans.ForgetThenCreate, plans.CreateThenForget: return ActionReplace case plans.Delete: return ActionDelete diff --git a/internal/command/views/json/hook.go b/internal/command/views/json/hook.go index 261be10c2d3e..b878793ab019 100644 --- a/internal/command/views/json/hook.go +++ b/internal/command/views/json/hook.go @@ -549,7 +549,7 @@ func startActionVerb(action plans.Action) string { return "Destroying" case plans.Read: return "Refreshing" - case plans.CreateThenDelete, plans.DeleteThenCreate, plans.CreateThenForget: + case plans.CreateThenDelete, plans.DeleteThenCreate, plans.ForgetThenCreate, plans.CreateThenForget: // This is not currently possible to reach, as we receive separate // passes for create and delete return "Replacing" @@ -583,7 +583,7 @@ func progressActionVerb(action plans.Action) string { return "destroying" case plans.Read: return "refreshing" - case plans.CreateThenDelete, plans.CreateThenForget, plans.DeleteThenCreate: + case plans.CreateThenDelete, plans.CreateThenForget, plans.DeleteThenCreate, plans.ForgetThenCreate: // This is not currently possible to reach, as we receive separate // passes for create and delete return "replacing" @@ -620,7 +620,7 @@ func actionNoun(action plans.Action) string { return "Destruction" case plans.Read: return "Refresh" - case plans.CreateThenDelete, plans.DeleteThenCreate, plans.CreateThenForget: + case plans.CreateThenDelete, plans.DeleteThenCreate, plans.ForgetThenCreate, plans.CreateThenForget: // This is not currently possible to reach, as we receive separate // passes for create and delete return "Replacement" diff --git a/internal/command/views/operation.go b/internal/command/views/operation.go index d211159bac0d..30f2aa547ed9 100644 --- a/internal/command/views/operation.go +++ b/internal/command/views/operation.go @@ -261,6 +261,8 @@ func (v *OperationJSON) Plan(plan *plans.Plan, schemas *terraform.Schemas) { case plans.CreateThenDelete, plans.DeleteThenCreate: cs.Add++ cs.Remove++ + case plans.ForgetThenCreate, plans.CreateThenForget: + cs.Add++ } if change.Action != plans.NoOp || !change.Addr.Equal(change.PrevRunAddr) || change.Importing != nil { From b1f4dbbb1e1ba8a8522b6bdc49a5029b856ed77c Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 9 Sep 2026 19:07:13 +0000 Subject: [PATCH 10/33] backport of commit dce44bddf9059606e6e2f8c29c8378ff62a5666b --- internal/terraform/context_apply2_test.go | 265 +++++++++++++++++- internal/terraform/context_plan.go | 2 +- internal/terraform/eval_context_builtin.go | 4 +- internal/terraform/node_policy_resource.go | 2 +- .../node_resource_abstract_instance.go | 18 +- .../terraform/node_resource_apply_instance.go | 3 +- .../node_resource_destroy_deposed.go | 20 +- internal/terraform/transform_diff.go | 22 +- 8 files changed, 311 insertions(+), 25 deletions(-) diff --git a/internal/terraform/context_apply2_test.go b/internal/terraform/context_apply2_test.go index 82feb4c540b7..5925f3793aec 100644 --- a/internal/terraform/context_apply2_test.go +++ b/internal/terraform/context_apply2_test.go @@ -5197,7 +5197,7 @@ resource test_object default {} if !strings.Contains(diags.ErrWithWarnings().Error(), "Some objects will no longer be managed by Terraform") { t.Fatal("missing expected diagnostic") } - assertPlan(t, plan, forget, plans.CreateThenForget) + assertPlan(t, plan, forget, plans.ForgetThenCreate) state, applyDiags := ctx.Apply(plan, m, nil) assertNoDiagnostics(t, applyDiags) @@ -5403,3 +5403,266 @@ resource "test_object" "r3" { assertNoDiagnostics(t, applyDiags) }) } + +func TestContext2Apply_forget_createBeforeDestroy(t *testing.T) { + tests := map[string]string{ + "explicit": ` +resource "test_object" "forget" { + lifecycle { + destroy = false + create_before_destroy = true + } +} +`, + "propagated": ` +resource "test_object" "forget" { + lifecycle { + destroy = false + } +} + +resource "test_object" "dependent" { + depends_on = [test_object.forget] + + lifecycle { + create_before_destroy = true + } +} +`, + } + + for name, config := range tests { + t.Run(name, func(t *testing.T) { + m := testModuleInline(t, map[string]string{ + "main.tf": config, + }) + + p := simpleMockProvider() + createCalls := 0 + p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) (resp providers.ApplyResourceChangeResponse) { + if req.PlannedState.IsNull() { + t.Fatal("provider was asked to destroy an object") + } + + if req.PriorState.IsNull() { + createCalls++ + } + resp.NewState = req.PlannedState + return resp + } + ctx := testContext2(t, &ContextOpts{ + Providers: map[addrs.Provider]providers.Factory{ + addrs.NewDefaultProvider("test"): testProviderFuncFixed(p), + }, + }) + + forget := mustResourceInstanceAddr("test_object.forget") + state := states.NewState() + root := state.EnsureModule(addrs.RootModuleInstance) + root.SetResourceInstanceCurrent( + forget.Resource, + &states.ResourceInstanceObjectSrc{ + Status: states.ObjectTainted, + AttrsJSON: []byte(`{"test_string":"old"}`), + }, + mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`), + ) + if name == "propagated" { + root.SetResourceInstanceCurrent( + mustResourceInstanceAddr("test_object.dependent").Resource, + &states.ResourceInstanceObjectSrc{ + Status: states.ObjectReady, + AttrsJSON: []byte(`{}`), + }, + mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`), + ) + } + + plan, diags := ctx.Plan(m, state, nil) + tfdiags.AssertNoErrors(t, diags) + change := plan.Changes.ResourceInstance(forget) + if change == nil { + t.Fatal("expected a change") + } + if got, want := change.Action, plans.CreateThenForget; got != want { + t.Fatalf("wrong change type for %s: got %s, want %s", forget, got, want) + } + + state, diags = ctx.Apply(plan, m, nil) + tfdiags.AssertNoErrors(t, diags) + if got, want := createCalls, 1; got != want { + t.Fatalf("wrong number of provider create calls: got %d, want %d", got, want) + } + + instance := state.ResourceInstance(forget) + if instance == nil || instance.Current == nil { + t.Fatalf("%s has no current object after replacement", forget) + } + if got := len(instance.Deposed); got != 0 { + t.Fatalf("%s has %d deposed objects after replacement; want none", forget, got) + } + }) + } +} + +func TestContext2Apply_forget_createBeforeDestroyInvalidResult(t *testing.T) { + initialConfig := testModuleInline(t, map[string]string{ + "main.tf": ` +resource "test_object" "forget" { + test_string = "old" + + lifecycle { + destroy = false + create_before_destroy = true + } +} +`, + }) + + replacementConfig := testModuleInline(t, map[string]string{ + "main.tf": ` +resource "test_object" "forget" { + test_string = "new" + + lifecycle { + destroy = false + create_before_destroy = true + } +} +`, + }) + + p := simpleMockProvider() + p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) { + resp.PlannedState = req.ProposedNewState + if req.PriorState.IsNull() || req.ProposedNewState.IsNull() { + return resp + } + if !req.PriorState.GetAttr("test_string").RawEquals(req.ProposedNewState.GetAttr("test_string")) { + resp.RequiresReplace = []cty.Path{cty.GetAttrPath("test_string")} + } + return resp + } + createCalls := 0 + p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) (resp providers.ApplyResourceChangeResponse) { + if req.PlannedState.IsNull() { + t.Fatal("provider was asked to destroy an object") + } + if req.PriorState.IsNull() { + createCalls++ + } + resp.NewState = req.PlannedState + return resp + } + + ctx := testContext2(t, &ContextOpts{ + Providers: map[addrs.Provider]providers.Factory{ + addrs.NewDefaultProvider("test"): testProviderFuncFixed(p), + }, + }) + + plan, diags := ctx.Plan(initialConfig, states.NewState(), nil) + tfdiags.AssertNoErrors(t, diags) + state, diags := ctx.Apply(plan, initialConfig, nil) + tfdiags.AssertNoErrors(t, diags) + if got, want := createCalls, 1; got != want { + t.Fatalf("wrong number of provider create calls after initial apply: got %d, want %d", got, want) + } + + plan, diags = ctx.Plan(replacementConfig, state, nil) + tfdiags.AssertNoErrors(t, diags) + _, diags = ctx.Apply(plan, replacementConfig, nil) + tfdiags.AssertNoErrors(t, diags) + if got, want := createCalls, 2; got != want { + t.Fatalf("wrong total number of provider create calls: got %d, want %d", got, want) + } +} + +func TestContext2Apply_forget_replace(t *testing.T) { + // https://github.com/hashicorp/terraform/issues/39088 + // we have a resource in state that needs replacing, and forget statement, but we're doing a replace + // don't be weird about it + m := testModuleInline(t, map[string]string{ + "main.tf": ` +resource "test_object" "forget" { + test_string = "hello" + lifecycle { + destroy = false + } +} +`}) + + p := simpleMockProvider() + + hook := new(MockHook) + ctx := testContext2(t, &ContextOpts{ + Hooks: []Hook{hook}, + Providers: map[addrs.Provider]providers.Factory{ + addrs.NewDefaultProvider("test"): testProviderFuncFixed(p), + }, + }) + forget := mustResourceInstanceAddr("test_object.forget") + + state := states.NewState() + root := state.EnsureModule(addrs.RootModuleInstance) + root.SetResourceInstanceCurrent( + forget.Resource, + &states.ResourceInstanceObjectSrc{ + Status: states.ObjectReady, + AttrsJSON: []byte(`{"test_string":"hi"}`), + }, + mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`), + ) + + // need the provider to return a requires_replace (or otherwise force replace) + p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) (resp providers.PlanResourceChangeResponse) { + obj := req.ProposedNewState.AsValueMap() + + if req.Config.IsNull() { + t.Fatal("should not plan a destroy") + } + + if !req.PriorState.IsNull() { + if req.PriorState.GetAttr("test_string").AsString() != "hello" { + resp.RequiresReplace = append(resp.RequiresReplace, cty.GetAttrPath("test_string")) + } + } + + resp.PlannedState = cty.ObjectVal(obj) + return resp + } + + p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) (resp providers.ApplyResourceChangeResponse) { + if req.PlannedState.IsNull() { + t.Fatal("should not be applying a destroy") + } + + resp.NewState = req.PlannedState + return resp + } + + plan, diags := ctx.Plan(m, state, nil) + if !diags.HasWarnings() { // forgetting emits a warning, but there should be no errors. + t.Errorf("missing expected forget warning") + } + assertNoDiagnostics(t, diags.ErrorsOnly()) + change := plan.Changes.ResourceInstance(forget) + if change == nil { + t.Fatal("expected a change") + } + if got, want := change.Action, plans.ForgetThenCreate; got != want { + t.Fatalf("wrong change type for %s: got %s, want %s", forget, got, want) + } + + state, applyDiags := ctx.Apply(plan, m, nil) + assertNoDiagnostics(t, applyDiags) + + replaced := state.Resources(forget.ConfigResource()) + if len(replaced) != 1 { + t.Fatal("expected one resource in state") + } + + if len(replaced[0].Instances[addrs.NoKey].Deposed) != 0 { + t.Fatal("should be no deposed instances") + } +} diff --git a/internal/terraform/context_plan.go b/internal/terraform/context_plan.go index b77dad9a6811..de467e272408 100644 --- a/internal/terraform/context_plan.go +++ b/internal/terraform/context_plan.go @@ -894,7 +894,7 @@ func (c *Context) planWalk(config *configs.Config, prevRunState *states.State, o var forgottenResources []string for _, rc := range changes.Resources { - if rc.Action == plans.Forget || rc.Action == plans.CreateThenForget { + if rc.Action == plans.Forget || rc.Action == plans.ForgetThenCreate || rc.Action == plans.CreateThenForget { // TODO KEM display resource ids forgottenResources = append(forgottenResources, fmt.Sprintf(" - %s", rc.Addr)) } diff --git a/internal/terraform/eval_context_builtin.go b/internal/terraform/eval_context_builtin.go index edb26852e62c..831c8385f84e 100644 --- a/internal/terraform/eval_context_builtin.go +++ b/internal/terraform/eval_context_builtin.go @@ -427,7 +427,7 @@ func (ctx *BuiltinEvalContext) EvaluateReplaceTriggeredBy(expr hcl.Expression, r for _, c := range changes { switch c.Change.Action { // Only immediate changes to the resource will trigger replacement. - case plans.Update, plans.DeleteThenCreate, plans.CreateThenDelete: + case plans.Update, plans.DeleteThenCreate, plans.CreateThenDelete, plans.ForgetThenCreate, plans.CreateThenForget: return ref, true, diags } } @@ -443,7 +443,7 @@ func (ctx *BuiltinEvalContext) EvaluateReplaceTriggeredBy(expr hcl.Expression, r // Make sure the change is actionable. A create or delete action will have // a change in value, but are not valid for our purposes here. switch change.Change.Action { - case plans.Update, plans.DeleteThenCreate, plans.CreateThenDelete: + case plans.Update, plans.DeleteThenCreate, plans.CreateThenDelete, plans.ForgetThenCreate, plans.CreateThenForget: // OK default: return nil, false, diags diff --git a/internal/terraform/node_policy_resource.go b/internal/terraform/node_policy_resource.go index ab41dd832cf6..fe1ecea4201b 100644 --- a/internal/terraform/node_policy_resource.go +++ b/internal/terraform/node_policy_resource.go @@ -126,7 +126,7 @@ func policyNodesFromChange(change *plans.ResourceInstanceChange) []*nodeResource After: cty.NilVal, }, } - case plans.CreateThenForget: + case plans.ForgetThenCreate, plans.CreateThenForget: return []*nodeResourcePolicy{ { ResourceAddr: change.Addr, diff --git a/internal/terraform/node_resource_abstract_instance.go b/internal/terraform/node_resource_abstract_instance.go index c484148813a9..cc140a143874 100644 --- a/internal/terraform/node_resource_abstract_instance.go +++ b/internal/terraform/node_resource_abstract_instance.go @@ -212,7 +212,7 @@ func (n *NodeAbstractResourceInstance) checkPreventDestroy(change *plans.Resourc preventDestroy := n.Config.Managed.PreventDestroy && !n.overridePreventDestroy - if (change.Action == plans.Delete || change.Action.IsReplace()) && preventDestroy { + if (change.Action == plans.Delete || change.Action == plans.DeleteThenCreate || change.Action == plans.CreateThenDelete) && preventDestroy { var diags tfdiags.Diagnostics diags = diags.Append(&hcl.Diagnostic{ Severity: hcl.DiagError, @@ -880,7 +880,8 @@ func (n *NodeAbstractResourceInstance) plan( var plannedPrivate []byte if plannedChange != nil { // If we already planned the action, we stick to that plan - createBeforeDestroy = plannedChange.Action == plans.CreateThenDelete + createBeforeDestroy = plannedChange.Action == plans.CreateThenDelete || + plannedChange.Action == plans.CreateThenForget plannedPrivate = plannedChange.Private } @@ -1341,8 +1342,10 @@ func (n *NodeAbstractResourceInstance) plan( forget := resourceLifecycleForget(n.Config) if action == plans.Create && !priorValTainted.IsNull() { switch { - case forget: + case forget && createBeforeDestroy: action = plans.CreateThenForget + case forget: + action = plans.ForgetThenCreate case createBeforeDestroy: action = plans.CreateThenDelete default: @@ -1352,6 +1355,15 @@ func (n *NodeAbstractResourceInstance) plan( actionReason = plans.ResourceInstanceReplaceBecauseTainted } + if forget { + switch action { + case plans.CreateThenDelete: + action = plans.CreateThenForget + case plans.DeleteThenCreate: + action = plans.ForgetThenCreate + } + } + // If we plan to change the sensitivity on some portion of the value, this // is an Update action even when the values are otherwise equal. // diff --git a/internal/terraform/node_resource_apply_instance.go b/internal/terraform/node_resource_apply_instance.go index 8795492c52fe..f5e2f4830142 100644 --- a/internal/terraform/node_resource_apply_instance.go +++ b/internal/terraform/node_resource_apply_instance.go @@ -193,7 +193,8 @@ func (n *NodeApplyableResourceInstance) managedResourceExecute(ctx EvalContext) destroy := (diffApply.Action == plans.Delete || diffApply.Action.IsReplace()) // Get the stored action for CBD if we have a plan already - createBeforeDestroyEnabled = diffApply.Change.Action == plans.CreateThenDelete + createBeforeDestroyEnabled = diffApply.Change.Action == plans.CreateThenDelete || + diffApply.Change.Action == plans.CreateThenForget if destroy && n.CreateBeforeDestroy() { createBeforeDestroyEnabled = true diff --git a/internal/terraform/node_resource_destroy_deposed.go b/internal/terraform/node_resource_destroy_deposed.go index 377480bd710b..b41a50305460 100644 --- a/internal/terraform/node_resource_destroy_deposed.go +++ b/internal/terraform/node_resource_destroy_deposed.go @@ -287,14 +287,7 @@ func (n *NodeDestroyDeposedResourceInstanceObject) Execute(ctx EvalContext, op w return diags } - var change *plans.ResourceInstanceChange - var destroyPlanDiags tfdiags.Diagnostics - var deferred *providers.Deferred - if resourceLifecycleForget(n.Config) { - change, destroyPlanDiags = n.planForget(ctx, state, n.DeposedKey) - } else { - change, deferred, destroyPlanDiags = n.planDestroy(ctx, state, n.DeposedKey) - } + change, deferred, destroyPlanDiags := n.planDestroy(ctx, state, n.DeposedKey) diags = diags.Append(destroyPlanDiags) if diags.HasErrors() { return diags @@ -359,6 +352,7 @@ var ( _ GraphNodeDeposedResourceInstanceObject = (*NodeForgetDeposedResourceInstanceObject)(nil) _ GraphNodeConfigResource = (*NodeForgetDeposedResourceInstanceObject)(nil) _ GraphNodeResourceInstance = (*NodeForgetDeposedResourceInstanceObject)(nil) + _ GraphNodeCreateBeforeDestroy = (*NodeForgetDeposedResourceInstanceObject)(nil) _ GraphNodeReferenceable = (*NodeForgetDeposedResourceInstanceObject)(nil) _ GraphNodeReferencer = (*NodeForgetDeposedResourceInstanceObject)(nil) _ GraphNodeExecutable = (*NodeForgetDeposedResourceInstanceObject)(nil) @@ -375,6 +369,16 @@ func (n *NodeForgetDeposedResourceInstanceObject) DestroyAddr() *addrs.AbsResour return &n.Addr } +func (n *NodeForgetDeposedResourceInstanceObject) CreateBeforeDestroy() bool { + // A deposed instance is always CreateBeforeDestroy by definition, since + // we use deposed only to handle create-before-destroy. + return true +} + +func (n *NodeForgetDeposedResourceInstanceObject) ForceCreateBeforeDestroy() { + // noop because deposed instances are always CBD +} + func (n *NodeForgetDeposedResourceInstanceObject) DeposedInstanceObjectKey() states.DeposedKey { return n.DeposedKey } diff --git a/internal/terraform/transform_diff.go b/internal/terraform/transform_diff.go index fece1c13d7d3..32a59270445a 100644 --- a/internal/terraform/transform_diff.go +++ b/internal/terraform/transform_diff.go @@ -112,13 +112,20 @@ func (t *DiffTransformer) Transform(g *Graph) error { case plans.Delete: delete = true - case plans.DeleteThenCreate, plans.CreateThenDelete: + case plans.DeleteThenCreate: update = true delete = true - createBeforeDestroy = (rc.Action == plans.CreateThenDelete) + case plans.CreateThenDelete: + update = true + delete = true + createBeforeDestroy = true case plans.CreateThenForget: update = true forget = true + createBeforeDestroy = true + case plans.ForgetThenCreate: + update = true + forget = true case plans.Forget: forget = true default: @@ -137,12 +144,11 @@ func (t *DiffTransformer) Transform(g *Graph) error { continue } - // If we're going to do a create_before_destroy Replace operation then - // we need to allocate a DeposedKey to use to retain the - // not-yet-destroyed prior object, so that the delete node can destroy - // _that_ rather than the newly-created node, which will be current - // by the time the delete node is visited. - if update && delete && createBeforeDestroy { + // If we're going to do a create-before-remove replacement then we need + // to allocate a DeposedKey to retain the prior object, so that the + // removal node acts on that rather than the newly-created current + // object. + if update && (delete || forget) && createBeforeDestroy { // In this case, variable dk will be the _pre-assigned_ DeposedKey // that must be used if the update graph node deposes the current // instance, which will then align with the same key we pass From a6d4287f292ffdffcc607e3f5eb8f0b98aa457db Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 9 Sep 2026 19:24:40 +0000 Subject: [PATCH 11/33] backport of commit d2b63a3d79291bc0c416fe8bf7c73843ccac1303 --- .changes/v1.16/BUG FIXES-20260909-152256.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changes/v1.16/BUG FIXES-20260909-152256.yaml diff --git a/.changes/v1.16/BUG FIXES-20260909-152256.yaml b/.changes/v1.16/BUG FIXES-20260909-152256.yaml new file mode 100644 index 000000000000..d2abd6dd9b72 --- /dev/null +++ b/.changes/v1.16/BUG FIXES-20260909-152256.yaml @@ -0,0 +1,5 @@ +kind: BUG FIXES +body: Fix handling of destroy=false around create_before_destroy instances +time: 2026-09-09T15:22:56.069683-04:00 +custom: + Issue: "39169" From 583c20b1b407cc85af370e9dc92aff1a2ef99e3c Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 9 Sep 2026 20:49:44 +0000 Subject: [PATCH 12/33] backport of commit aa1d8e38492a22b80199774e476a7f61b11a55b8 --- internal/lang/function_results.go | 33 ++++++++++++++++++++----- internal/lang/function_results_test.go | 34 ++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/internal/lang/function_results.go b/internal/lang/function_results.go index 0b091cc30fde..58e33cf3ceb8 100644 --- a/internal/lang/function_results.go +++ b/internal/lang/function_results.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "log" + "sort" "sync" "github.com/hashicorp/terraform/internal/addrs" @@ -57,7 +58,7 @@ func (f *FunctionResults) CheckPriorProvider(provider addrs.Provider, name strin // gracefully throughout the evaluation system, whereas invalid data is // harder to trace back to the source since it's usually only visible due to // unexpected side-effects. - if !result.IsKnown() { + if !result.IsWhollyKnown() { return nil } @@ -69,17 +70,14 @@ func (f *FunctionResults) CheckPriorProvider(provider addrs.Provider, name strin io.WriteString(argSum, name) for _, arg := range args { - // cty.Values have a Hash method, but it is not collision resistant. We - // are going to rely on the GoString formatting instead, which gives - // detailed results for all values. - io.WriteString(argSum, "|"+arg.GoString()) + io.WriteString(argSum, "|"+ctyHashString(arg)) } f.mu.Lock() defer f.mu.Unlock() argHash := [sha256.Size]byte(argSum.Sum(nil)) - resHash := sha256.Sum256([]byte(result.GoString())) + resHash := sha256.Sum256([]byte(ctyHashString(result))) res, ok := f.results[argHash] if !ok { @@ -142,3 +140,26 @@ func (f *FunctionResults) GetHashes() []FunctionResultHash { } return res } + +// ctyHashString returns a stable string for hashing a cty value. cty.Values +// have a Hash method, but it is not collision resistant. We are going to rely +// on the GoString formatting instead, which gives detailed results for all +// values. Marks however are iterated over from a map, so we need to account for +// those separately. +func ctyHashString(v cty.Value) string { + unmarked, pathMarks := v.UnmarkDeepWithPaths() + if len(pathMarks) == 0 { + return v.GoString() + } + + marks := make([]string, 0, len(pathMarks)) + for _, pathMark := range pathMarks { + path := fmt.Sprintf("%#v", pathMark.Path) + for mark := range pathMark.Marks { + marks = append(marks, fmt.Sprintf("<%s:%#v>", path, mark)) + } + } + sort.Strings(marks) + + return fmt.Sprintf("%#v|%#v", unmarked, marks) +} diff --git a/internal/lang/function_results_test.go b/internal/lang/function_results_test.go index 1cbb01a20447..832f36984f61 100644 --- a/internal/lang/function_results_test.go +++ b/internal/lang/function_results_test.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/hashicorp/terraform/internal/addrs" + "github.com/hashicorp/terraform/internal/lang/marks" "github.com/zclconf/go-cty/cty" // set the correct global logger for tests @@ -17,6 +18,8 @@ import ( func TestFunctionCache(t *testing.T) { testAddr := addrs.NewDefaultProvider("test") + deprecated := marks.NewDeprecation("test deprecation", "test") + type testCall struct { provider addrs.Provider name string @@ -157,6 +160,37 @@ func TestFunctionCache(t *testing.T) { }, // OK because args changed from unknown to known }, + { + first: testCall{ + provider: testAddr, + name: "fun", + args: []cty.Value{cty.NumberIntVal(2)}, + result: cty.True.Mark(deprecated).Mark(marks.Sensitive), + }, + second: testCall{ + provider: testAddr, + name: "fun", + args: []cty.Value{cty.NumberIntVal(2)}, + result: cty.True.Mark(deprecated).Mark(marks.Sensitive), + }, + }, + + { + first: testCall{ + provider: testAddr, + name: "fun", + args: []cty.Value{cty.NumberIntVal(2).Mark(marks.Ephemeral).Mark(marks.Sensitive)}, + result: cty.True, + }, + second: testCall{ + provider: testAddr, + name: "fun", + args: []cty.Value{cty.NumberIntVal(2).Mark(marks.Ephemeral).Mark(marks.Sensitive)}, + result: cty.False, + }, + // make sure the arg marks always evaluate as equal + expectErr: true, + }, } for i, test := range tests { From 19c1fed898d1cad981cc7cd1ac9efd28a6b60da9 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 9 Sep 2026 21:05:04 +0000 Subject: [PATCH 13/33] backport of commit 3cc456ece13ec539a00b63e3d702525dadfddba8 --- .changes/v1.16/BUG FIXES-20260909-170426.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changes/v1.16/BUG FIXES-20260909-170426.yaml diff --git a/.changes/v1.16/BUG FIXES-20260909-170426.yaml b/.changes/v1.16/BUG FIXES-20260909-170426.yaml new file mode 100644 index 000000000000..9f67b2ce3619 --- /dev/null +++ b/.changes/v1.16/BUG FIXES-20260909-170426.yaml @@ -0,0 +1,5 @@ +kind: BUG FIXES +body: Fix function result comparison when there are multiple marks +time: 2026-09-09T17:04:26.18364-04:00 +custom: + Issue: "39170" From 3f597dc5d158f9a96ee2ad1cda4baa15d1fb76b1 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 9 Sep 2026 22:46:21 +0000 Subject: [PATCH 14/33] backport of commit f763bbbc72c38184076e99501e3885d744315c56 --- internal/lang/marks/paths.go | 46 +++++++++++++++++-------------- internal/lang/marks/paths_test.go | 22 +++------------ 2 files changed, 30 insertions(+), 38 deletions(-) diff --git a/internal/lang/marks/paths.go b/internal/lang/marks/paths.go index af50556373c5..351d293c8aec 100644 --- a/internal/lang/marks/paths.go +++ b/internal/lang/marks/paths.go @@ -28,28 +28,31 @@ func PathsWithMark(pvms []cty.PathValueMarks, wantMark any) (withWanted []cty.Pa return nil, nil } + wanted := func(mark any) bool { + switch wantMark.(type) { + case valueMark, string: + return mark == wantMark + + // For data marks we check if a mark of the type exists + case DeprecationMark: + _, ok := mark.(DeprecationMark) + return ok + + default: + panic(fmt.Sprintf("unexpected mark type %T", wantMark)) + } + } + for _, pvm := range pvms { pathHasMark := false - pathHasOtherMarks := false + otherMarks := []any{} for mark := range pvm.Marks { - switch wantMark.(type) { - case valueMark, string: - if mark == wantMark { - pathHasMark = true - } else { - pathHasOtherMarks = true - } - - // For data marks we check if a mark of the type exists - case DeprecationMark: - if _, ok := mark.(DeprecationMark); ok { - pathHasMark = true - } else { - pathHasOtherMarks = true - } + if wanted(mark) { + // record the path outside the loop so we don't get multiples + pathHasMark = true - default: - panic(fmt.Sprintf("unexpected mark type %T", wantMark)) + } else { + otherMarks = append(otherMarks, mark) } } @@ -57,8 +60,11 @@ func PathsWithMark(pvms []cty.PathValueMarks, wantMark any) (withWanted []cty.Pa withWanted = append(withWanted, pvm.Path) } - if pathHasOtherMarks { - withOthers = append(withOthers, pvm) + if len(otherMarks) > 0 { + withOthers = append(withOthers, cty.PathValueMarks{ + Path: pvm.Path, + Marks: cty.NewValueMarks(otherMarks...), + }) } } diff --git a/internal/lang/marks/paths_test.go b/internal/lang/marks/paths_test.go index a9fb674d4ecb..b7ea1810c1d1 100644 --- a/internal/lang/marks/paths_test.go +++ b/internal/lang/marks/paths_test.go @@ -57,13 +57,7 @@ func TestPathsWithMark(t *testing.T) { }, { Path: cty.GetAttrPath("both"), - Marks: cty.NewValueMarks("sensitive", "other"), - // Note that this intentionally preserves the fact that the - // attribute was both sensitive _and_ had another mark, since - // that gives the caller the most possible information to - // potentially handle this combination in a special way in - // an error message, or whatever. It also conveniently avoids - // allocating a new mark set, which is nice. + Marks: cty.NewValueMarks("other"), }, { Path: cty.GetAttrPath("neither"), @@ -79,7 +73,7 @@ func TestPathsWithMark(t *testing.T) { }, { Path: cty.GetAttrPath("multipleDeprecationsAndSensitive"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", ""), NewDeprecation("this is also deprecated", ""), "sensitive"), + Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", ""), NewDeprecation("this is also deprecated", "")), }, } @@ -90,7 +84,7 @@ func TestPathsWithMark(t *testing.T) { t.Errorf("wrong set of entries with other marks\n%s", diff) } - gotPaths, gotOthers = PathsWithMark(input, Deprecation) + gotPaths, gotOthers = PathsWithMark(gotOthers, Deprecation) wantPaths = []cty.Path{ cty.GetAttrPath("deprecated"), @@ -98,26 +92,18 @@ func TestPathsWithMark(t *testing.T) { cty.GetAttrPath("multipleDeprecationsAndSensitive"), } wantOthers = []cty.PathValueMarks{ - { - Path: cty.GetAttrPath("sensitive"), - Marks: cty.NewValueMarks("sensitive"), - }, { Path: cty.GetAttrPath("other"), Marks: cty.NewValueMarks("other"), }, { Path: cty.GetAttrPath("both"), - Marks: cty.NewValueMarks("sensitive", "other"), + Marks: cty.NewValueMarks("other"), }, { Path: cty.GetAttrPath("neither"), Marks: cty.NewValueMarks("x", "y"), }, - { - Path: cty.GetAttrPath("multipleDeprecationsAndSensitive"), - Marks: cty.NewValueMarks(NewDeprecation("this is deprecated", ""), NewDeprecation("this is also deprecated", ""), "sensitive"), - }, } if diff := cmp.Diff(wantPaths, gotPaths, ctydebug.CmpOptions); diff != "" { From c63c283dd2f596b68da3804b09ef78deaa7d5764 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Wed, 9 Sep 2026 23:01:16 +0000 Subject: [PATCH 15/33] backport of commit 313d9a5457de1d40bd5f6629d531af70946da878 --- .changes/v1.16/BUG FIXES-20260909-190037.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changes/v1.16/BUG FIXES-20260909-190037.yaml diff --git a/.changes/v1.16/BUG FIXES-20260909-190037.yaml b/.changes/v1.16/BUG FIXES-20260909-190037.yaml new file mode 100644 index 000000000000..abf624207284 --- /dev/null +++ b/.changes/v1.16/BUG FIXES-20260909-190037.yaml @@ -0,0 +1,5 @@ +kind: BUG FIXES +body: Filter logic for marks could cause values with multiple marks to erroneously fail validations +time: 2026-09-09T19:00:37.342225-04:00 +custom: + Issue: "39171" From 458ceb89e69f783ea067fe44537dee133ae622f9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 10 Sep 2026 14:05:56 +0000 Subject: [PATCH 16/33] Backport of test: Using PSS in combination with dynamic provider sources into v1.17 (#39178) * backport of commit 138f5f999fdb1f848e8b2bd9c46225b4ac2c6379 * backport of commit e5c7830a525bbe39c0dc0298da49d24e1241bdbd * backport of commit 601bde7e21770a8c07f5dcd2ce245bccb2fb9b9d * backport of commit a63bc5ba6c75ee177b10d0a45526beaf43922639 * backport of commit 207c1fbf7788717da4b2ad6d49982cacee0427b7 * backport of commit c0638e6ba18bdb96f279f769ccb0ed806c6b41e0 --------- Co-authored-by: Sarah French Co-authored-by: Daniel Banck --- internal/command/e2etest/primary_test.go | 121 ++++++++++++++++++ .../main.tf | 38 ++++++ internal/command/init2_test.go | 120 +++++++++++++++++ internal/command/init_test.go | 28 ++-- internal/command/query_test.go | 6 + .../main.tf | 34 +++++ .../query.tfquery.hcl | 7 + 7 files changed, 343 insertions(+), 11 deletions(-) create mode 100644 internal/command/e2etest/testdata/full-workflow-with-dyn-sourced-state-store-fs/main.tf create mode 100644 internal/command/testdata/dynamic-provider-sources/combined-with-pluggable-state-storage/main.tf create mode 100644 internal/command/testdata/dynamic-provider-sources/combined-with-pluggable-state-storage/query.tfquery.hcl diff --git a/internal/command/e2etest/primary_test.go b/internal/command/e2etest/primary_test.go index d2b540a8bbcc..c0737df512ba 100644 --- a/internal/command/e2etest/primary_test.go +++ b/internal/command/e2etest/primary_test.go @@ -16,6 +16,7 @@ import ( "github.com/hashicorp/terraform/internal/addrs" "github.com/hashicorp/terraform/internal/command" "github.com/hashicorp/terraform/internal/command/clistate" + "github.com/hashicorp/terraform/internal/depsfile" "github.com/hashicorp/terraform/internal/e2e" "github.com/hashicorp/terraform/internal/getproviders" "github.com/hashicorp/terraform/internal/plans" @@ -937,3 +938,123 @@ func TestPrimary_stateStore_swapProviderSupplyMode_betweenSuccessiveInits(t *tes } }) } + +// Test using dynamic provider sources in combination with pluggable state storage for multiple commands: +// - init +// - plan +// - apply +// - refresh +// - query +func TestPrimary_stateStore_dynamicProviderSources(t *testing.T) { + t.Parallel() + if !canRunGoBuild { + // We're running in a separate-build-then-run context, so we can't + // currently execute this test which depends on being able to build + // new executable at runtime. + // + // (See the comment on canRunGoBuild's declaration for more information.) + t.Skip("can't run without building a new provider executable") + } + + fixturePath := filepath.Join("testdata", "full-workflow-with-dyn-sourced-state-store-fs") + + tf := e2e.NewBinary(t, experimentalTerraformBin, fixturePath) + + // Build the simple6 provider binary and supply it to `init` via the -plugin-dir flag. + simple6Provider := filepath.Join(tf.WorkDir(), "terraform-provider-simple6") + simple6ProviderExe := e2e.GoBuild("github.com/hashicorp/terraform/internal/provider-simple-v6/main", simple6Provider) + platform := getproviders.CurrentPlatform.String() + hashiDir := "cache/registry.terraform.io/hashicorp/" + if err := os.MkdirAll(tf.Path(hashiDir, "simple6/0.0.1/", platform), os.ModePerm); err != nil { + t.Fatal(err) + } + if err := os.Rename(simple6ProviderExe, tf.Path(hashiDir, "simple6/0.0.1/", platform, "terraform-provider-simple6")); err != nil { + t.Fatal(err) + } + + // INIT + stdout, stderr, err := tf.Run( + "init", + "-enable-pluggable-state-storage-experiment", + "-plugin-dir=cache", + "-var", "provider_source=registry.terraform.io/hashicorp/simple6", + "-var", "provider_version=0.0.1", + ) + if err != nil { + t.Fatalf("unexpected error: %s\nstderr:\n%q", err, stderr) + } + + expectedMsg := `Finding hashicorp/simple6 versions matching "0.0.1"...` + if !strings.Contains(stdout, expectedMsg) { + t.Fatalf("expected output %q, got %q", expectedMsg, stdout) + } + + // Verify the lockfile includes expected provider and version + lockPath := filepath.Join(tf.WorkDir(), depsfile.LockFilePath) + locks, diags := depsfile.LoadLocksFromFile(lockPath) + if len(diags) > 0 { + t.Fatalf("unexpected diagnostics: %s", diags) + } + pAddr := addrs.MustParseProviderSourceString("hashicorp/simple6") + pLock := locks.Provider(pAddr) + + expectedVersion := getproviders.MustParseVersion("0.0.1") + givenVersion := pLock.Version() + if expectedVersion.String() != givenVersion.String() { + t.Fatalf("mismatching version, expected %s, given %s", expectedVersion, givenVersion) + } + + // PLAN + _, stderr, err = tf.Run( + "plan", + "-var", "provider_source=registry.terraform.io/hashicorp/simple6", + "-var", "provider_version=0.0.1", + ) + if err != nil { + t.Fatalf("unexpected error: %s\nstderr:\n%q", err, stderr) + } + + // APPLY + _, stderr, err = tf.Run( + "apply", + "-var", "provider_source=registry.terraform.io/hashicorp/simple6", + "-var", "provider_version=0.0.1", + "-auto-approve", + ) + if err != nil { + t.Fatalf("unexpected error: %s\nstderr:\n%q", err, stderr) + } + + // REFRESH + _, stderr, err = tf.Run( + "refresh", + "-var", "provider_source=registry.terraform.io/hashicorp/simple6", + "-var", "provider_version=0.0.1", + ) + if err != nil { + t.Fatalf("unexpected error: %s\nstderr:\n%q", err, stderr) + } + + // QUERY + // TODO: Need to check if the provider implements necessary logic for performing a query. + + // Add a .tfquery.hcl file and then run the query command + queryFilePath := tf.Path("main.tfquery.hcl") + os.WriteFile(queryFilePath, []byte(` +list "simple_resource" "test" { + provider = simple6 + include_resource = true + config { + value = "dynamic_value" + } +} +`), 0644) + _, stderr, err = tf.Run( + "query", + "-var", "provider_source=registry.terraform.io/hashicorp/simple6", + "-var", "provider_version=0.0.1", + ) + if err != nil { + t.Fatalf("unexpected error: %s\nstderr:\n%q", err, stderr) + } +} diff --git a/internal/command/e2etest/testdata/full-workflow-with-dyn-sourced-state-store-fs/main.tf b/internal/command/e2etest/testdata/full-workflow-with-dyn-sourced-state-store-fs/main.tf new file mode 100644 index 000000000000..c707c5aab8ee --- /dev/null +++ b/internal/command/e2etest/testdata/full-workflow-with-dyn-sourced-state-store-fs/main.tf @@ -0,0 +1,38 @@ +terraform { + required_providers { + simple6 = { + source = var.provider_source + version = var.provider_version + } + } + + state_store "simple6_fs" { + provider "simple6" {} + + workspace_dir = "states" + } +} + +variable "provider_source" { + default = "invalid source string" // If the default value is used it will cause an error + type = string + const = true +} + +variable "provider_version" { + default = "invalid version string" // If the default value is used it will cause an error + type = string + const = true +} + +variable "name" { + default = "world" +} + +resource "terraform_data" "my-data" { + input = "hello ${var.name}" +} + +output "greeting" { + value = resource.terraform_data.my-data.output +} diff --git a/internal/command/init2_test.go b/internal/command/init2_test.go index 26c83c75d297..3338971ca649 100644 --- a/internal/command/init2_test.go +++ b/internal/command/init2_test.go @@ -10,6 +10,7 @@ import ( "testing" "github.com/hashicorp/terraform/internal/command/views" + "github.com/hashicorp/terraform/internal/configs/configschema" "github.com/hashicorp/terraform/internal/modsdir" "github.com/hashicorp/terraform/internal/terminal" ) @@ -949,3 +950,122 @@ func TestPlan_dynamicModuleVersionMismatch(t *testing.T) { t.Fatalf("wrong error\ngot:\n%s\n\nwant: containing %q", got, want) } } + +func TestPrimaryWorkflow_dynamicProviderSource_pluggableStateStorage(t *testing.T) { + td := t.TempDir() + testCopyDir(t, testFixturePath(filepath.Join("dynamic-provider-sources", "combined-with-pluggable-state-storage")), td) + t.Chdir(td) + + mockProvider := mockPluggableStateStorageProvider(mockSingleStateStoreSchema("test_store")) + // Make the mock provider have an empty schema body, matching the mock used below for the query command. + // Without this, Terraform will detect the change in the provider schema and think the state store configuration has changed. + mockProvider.GetProviderSchemaResponse.Provider.Body = &configschema.Block{ + Attributes: map[string]*configschema.Attribute{}, + BlockTypes: map[string]*configschema.NestedBlock{}, + } + providerSource := newMockProviderSource(t, map[string][]string{ + "hashicorp/test": {"1.0.0"}, + }) + + varArgs := []string{ + "-var", "provider_source=registry.terraform.io/hashicorp/test", + "-var", "provider_version=1.0.0", + } + + // INIT + ui := testUiWrapped(t) + view, done := testView(t) + initCmd := &InitCommand{ + Meta: Meta{ + testingOverrides: metaOverridesForProvider(mockProvider), + Ui: ui, + View: view, + ProviderSource: providerSource, + AllowExperimentalFeatures: true, + }, + } + + code := initCmd.Run(append([]string{"-enable-pluggable-state-storage-experiment"}, varArgs...)) + testOutput := done(t) + if code != 0 { + t.Fatalf("got exit status %d; want 0\nstderr:\n%s\n\nstdout:\n%s", code, testOutput.Stderr(), testOutput.Stdout()) + } + expectedMsg := `Finding hashicorp/test versions matching "1.0.0"...` + if !strings.Contains(testOutput.All(), expectedMsg) { + t.Fatalf("expected output to contain %q\n, got:\n%s", expectedMsg, testOutput.All()) + } + + // PLAN + ui = testUiWrapped(t) + view, done = testView(t) + planCmd := &PlanCommand{ + Meta: Meta{ + testingOverrides: metaOverridesForProvider(mockProvider), + Ui: ui, + View: view, + ProviderSource: providerSource, + AllowExperimentalFeatures: true, + }, + } + code = planCmd.Run(varArgs) + testOutput = done(t) + if code != 0 { + t.Fatalf("got exit status %d; want 0\nstderr:\n%s\n\nstdout:\n%s", code, testOutput.Stderr(), testOutput.Stdout()) + } + + // APPLY + ui = testUiWrapped(t) + view, done = testView(t) + applyCmd := &ApplyCommand{ + Meta: Meta{ + testingOverrides: metaOverridesForProvider(mockProvider), + Ui: ui, + View: view, + ProviderSource: providerSource, + AllowExperimentalFeatures: true, + }, + } + code = applyCmd.Run(append([]string{"-auto-approve"}, varArgs...)) + testOutput = done(t) + if code != 0 { + t.Fatalf("got exit status %d; want 0\nstderr:\n%s\n\nstdout:\n%s", code, testOutput.Stderr(), testOutput.Stdout()) + } + + // REFRESH + ui = testUiWrapped(t) + view, done = testView(t) + refreshCmd := &RefreshCommand{ + Meta: Meta{ + testingOverrides: metaOverridesForProvider(mockProvider), + Ui: ui, + View: view, + ProviderSource: providerSource, + AllowExperimentalFeatures: true, + }, + } + code = refreshCmd.Run(varArgs) + testOutput = done(t) + if code != 0 { + t.Fatalf("got exit status %d; want 0\nstderr:\n%s\n\nstdout:\n%s", code, testOutput.Stderr(), testOutput.Stdout()) + } + + // QUERY + queryMockProvider := queryFixtureProvider() + queryMockProvider = addPluggableStateStoreToMockProvider(queryMockProvider, mockSingleStateStoreSchema("test_store")) // Update the query-specific mock to also include a state store. + ui = testUiWrapped(t) + view, done = testView(t) + queryCmd := &QueryCommand{ + Meta: Meta{ + testingOverrides: metaOverridesForProvider(queryMockProvider), + Ui: ui, + View: view, + ProviderSource: providerSource, + AllowExperimentalFeatures: true, + }, + } + code = queryCmd.Run(varArgs) + testOutput = done(t) + if code != 0 { + t.Fatalf("got exit status %d; want 0\nstderr:\n%s\n\nstdout:\n%s", code, testOutput.Stderr(), testOutput.Stdout()) + } +} diff --git a/internal/command/init_test.go b/internal/command/init_test.go index 1671764dc059..ab100891c631 100644 --- a/internal/command/init_test.go +++ b/internal/command/init_test.go @@ -8614,10 +8614,16 @@ func mockPluggableStateStorageProvider(schemas map[string]providers.Schema) *tes StateStores: schemas, }, } + return addPluggableStateStoreToMockProvider(&mock, schemas) +} + +func addPluggableStateStoreToMockProvider(p *testing_provider.MockProvider, schemas map[string]providers.Schema) *testing_provider.MockProvider { + p.GetProviderSchemaResponse.StateStores = schemas + typeNames := slices.Sorted(maps.Keys(schemas)) - mock.MockStates = testing_provider.NewMockStateBytesWithTypes(typeNames) - mock.GetStatesFn = func(req providers.GetStatesRequest) (resp providers.GetStatesResponse) { - stateIds, err := mock.MockStates.StateIds(req.TypeName) + p.MockStates = testing_provider.NewMockStateBytesWithTypes(typeNames) + p.GetStatesFn = func(req providers.GetStatesRequest) (resp providers.GetStatesResponse) { + stateIds, err := p.MockStates.StateIds(req.TypeName) if err != nil { resp.Diagnostics = resp.Diagnostics.Append(err) } @@ -8625,24 +8631,24 @@ func mockPluggableStateStorageProvider(schemas map[string]providers.Schema) *tes return resp } - mock.ConfigureStateStoreFn = func(req providers.ConfigureStateStoreRequest) providers.ConfigureStateStoreResponse { + p.ConfigureStateStoreFn = func(req providers.ConfigureStateStoreRequest) providers.ConfigureStateStoreResponse { return providers.ConfigureStateStoreResponse{ Capabilities: providers.StateStoreServerCapabilities{ ChunkSize: 1234, // arbitrary number that isn't 0 }, } } - mock.WriteStateBytesFn = func(req providers.WriteStateBytesRequest) (resp providers.WriteStateBytesResponse) { + p.WriteStateBytesFn = func(req providers.WriteStateBytesRequest) (resp providers.WriteStateBytesResponse) { // Workspaces exist once the artefact representing it is written - err := mock.MockStates.Write(req.TypeName, req.StateId, req.Bytes) + err := p.MockStates.Write(req.TypeName, req.StateId, req.Bytes) if err != nil { resp.Diagnostics = resp.Diagnostics.Append(err) } return resp } - mock.ReadStateBytesFn = func(req providers.ReadStateBytesRequest) (resp providers.ReadStateBytesResponse) { - b, err := mock.MockStates.Read(req.TypeName, req.StateId) + p.ReadStateBytesFn = func(req providers.ReadStateBytesRequest) (resp providers.ReadStateBytesResponse) { + b, err := p.MockStates.Read(req.TypeName, req.StateId) if err != nil { if errors.Is(err, testing_provider.StateNotFoundErr{TypeName: req.TypeName, StateId: req.StateId}) { warn := tfdiags.SimpleWarning(err.Error()) @@ -8655,14 +8661,14 @@ func mockPluggableStateStorageProvider(schemas map[string]providers.Schema) *tes return resp } - mock.DeleteStateFn = func(req providers.DeleteStateRequest) (resp providers.DeleteStateResponse) { - err := mock.MockStates.Delete(req.TypeName, req.StateId) + p.DeleteStateFn = func(req providers.DeleteStateRequest) (resp providers.DeleteStateResponse) { + err := p.MockStates.Delete(req.TypeName, req.StateId) if err != nil { resp.Diagnostics = resp.Diagnostics.Append(err) } return resp } - return &mock + return p } func assertLockfileContents(t *testing.T, path string, expected string) { diff --git a/internal/command/query_test.go b/internal/command/query_test.go index a69c99c8854b..f6dbaac77832 100644 --- a/internal/command/query_test.go +++ b/internal/command/query_test.go @@ -471,6 +471,12 @@ func queryFixtureProvider() *testing_provider.MockProvider { }, } p.GetProviderSchemaResponse = &providers.GetProviderSchemaResponse{ + Provider: providers.Schema{ + Body: &configschema.Block{ + Attributes: map[string]*configschema.Attribute{}, + BlockTypes: map[string]*configschema.NestedBlock{}, + }, + }, ResourceTypes: map[string]providers.Schema{ "test_instance": { Body: &configschema.Block{ diff --git a/internal/command/testdata/dynamic-provider-sources/combined-with-pluggable-state-storage/main.tf b/internal/command/testdata/dynamic-provider-sources/combined-with-pluggable-state-storage/main.tf new file mode 100644 index 000000000000..a5d3bfd7accb --- /dev/null +++ b/internal/command/testdata/dynamic-provider-sources/combined-with-pluggable-state-storage/main.tf @@ -0,0 +1,34 @@ +terraform { + required_providers { + test = { + source = var.provider_source + version = var.provider_version + } + } + + state_store "test_store" { + provider "test" {} + + value = "foobar" + } +} + +variable "provider_source" { + default = "invalid source string" // If the default value is used it will cause an error + type = string + const = true +} + +variable "provider_version" { + default = "invalid version string" // If the default value is used it will cause an error + type = string + const = true +} + +variable "name" { + default = "world" +} + +output "greeting" { + value = "hello ${var.name}" +} diff --git a/internal/command/testdata/dynamic-provider-sources/combined-with-pluggable-state-storage/query.tfquery.hcl b/internal/command/testdata/dynamic-provider-sources/combined-with-pluggable-state-storage/query.tfquery.hcl new file mode 100644 index 000000000000..a55128eafb4b --- /dev/null +++ b/internal/command/testdata/dynamic-provider-sources/combined-with-pluggable-state-storage/query.tfquery.hcl @@ -0,0 +1,7 @@ +list "test_instance" "example" { + provider = test + + config { + ami = "ami-12345" + } +} From 1a56951bb4683a6a31a2871087a63df247d3ee94 Mon Sep 17 00:00:00 2001 From: Kristin Laemmert Date: Thu, 10 Sep 2026 16:07:50 +0000 Subject: [PATCH 17/33] backport of commit 5e07d425b9e8285544ee12fdaffc896f871f2097 --- .changes/v1.16/BUG FIXES-20260910-121207.yaml | 5 ++ .../terraform/context_plan_import_test.go | 80 +++++++++++++++++++ internal/terraform/node_resource_abstract.go | 13 +-- 3 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 .changes/v1.16/BUG FIXES-20260910-121207.yaml diff --git a/.changes/v1.16/BUG FIXES-20260910-121207.yaml b/.changes/v1.16/BUG FIXES-20260910-121207.yaml new file mode 100644 index 000000000000..a91f782c6e29 --- /dev/null +++ b/.changes/v1.16/BUG FIXES-20260910-121207.yaml @@ -0,0 +1,5 @@ +kind: BUG FIXES +body: Fix issue with import provider resolution +time: 2026-09-10T12:12:07.068649-04:00 +custom: + Issue: "39185" diff --git a/internal/terraform/context_plan_import_test.go b/internal/terraform/context_plan_import_test.go index cce43fa2b520..b9bdac1ceb96 100644 --- a/internal/terraform/context_plan_import_test.go +++ b/internal/terraform/context_plan_import_test.go @@ -2465,6 +2465,86 @@ import { }) } +func TestContext2Plan_importResourceConfigGenWithProviderLocalName_implicit(t *testing.T) { + // regression reported in https://github.com/hashicorp/terraform/issues/39144 + addr := mustResourceInstanceAddr("test_object.a") + m := testModuleInline(t, map[string]string{ + "main.tf": ` +terraform { + required_providers { + test = { + source = "example.com/foo/test" + } + } +} + +provider "test" {} + +import { + to = test_object.a + id = "123" +} +`, + }) + + p := simpleMockProvider() + providerAddr := addrs.MustParseProviderSourceString("example.com/foo/test") + ctx := testContext2(t, &ContextOpts{ + Providers: map[addrs.Provider]providers.Factory{ + providerAddr: testProviderFuncFixed(p), + }, + }) + p.ReadResourceResponse = &providers.ReadResourceResponse{ + NewState: cty.ObjectVal(map[string]cty.Value{ + "test_string": cty.StringVal("foo"), + }), + } + p.ImportResourceStateResponse = &providers.ImportResourceStateResponse{ + ImportedResources: []providers.ImportedResource{ + { + TypeName: "test_object", + State: cty.ObjectVal(map[string]cty.Value{ + "test_string": cty.StringVal("foo"), + }), + }, + }, + } + + diags := ctx.Validate(m, &ValidateOpts{}) + if diags.HasErrors() { + t.Fatalf("unexpected errors\n%s", diags.Err().Error()) + } + + plan, diags := ctx.Plan(m, states.NewState(), &PlanOpts{ + Mode: plans.NormalMode, + GenerateConfigPath: "generated.tf", // Actual value here doesn't matter, as long as it is not empty. + }) + if diags.HasErrors() { + t.Fatalf("unexpected errors\n%s", diags.Err().Error()) + } + + t.Run(addr.String(), func(t *testing.T) { + instPlan := plan.Changes.ResourceInstance(addr) + if instPlan == nil { + t.Fatalf("no plan for %s at all", addr) + } + if got := instPlan.ProviderAddr.Provider; got != providerAddr { + t.Errorf("wrong provider\ngot: %s\nwant: %s", got, providerAddr) + } + want := `resource "test_object" "a" { + test_bool = null + test_list = null + test_map = null + test_number = null + test_string = "foo" +}` + got := instPlan.GeneratedConfig + if diff := cmp.Diff(want, got); len(diff) > 0 { + t.Errorf("got:\n%s\nwant:\n%s\ndiff:\n%s", got, want, diff) + } + }) +} + func TestContext2Plan_importDeferredResource(t *testing.T) { addr := mustResourceInstanceAddr("test_object.a") m := testModuleInline(t, map[string]string{ diff --git a/internal/terraform/node_resource_abstract.go b/internal/terraform/node_resource_abstract.go index 9a5731bd8904..0da707011e90 100644 --- a/internal/terraform/node_resource_abstract.go +++ b/internal/terraform/node_resource_abstract.go @@ -7,6 +7,8 @@ import ( "fmt" "log" + "github.com/zclconf/go-cty/cty" + "github.com/hashicorp/terraform/internal/addrs" "github.com/hashicorp/terraform/internal/configs" "github.com/hashicorp/terraform/internal/configs/configschema" @@ -16,7 +18,6 @@ import ( "github.com/hashicorp/terraform/internal/providers" "github.com/hashicorp/terraform/internal/states" "github.com/hashicorp/terraform/internal/tfdiags" - "github.com/zclconf/go-cty/cty" ) // ConcreteResourceNodeFunc is a callback type used to convert an @@ -364,16 +365,18 @@ func (n *NodeAbstractResource) Provider() ProviderRef { // The import targets should either all be defined via config or none // of them should be. They should also all have the same provider, so it // shouldn't matter which we check here, as they'll all give the same. - if n.importTargets[0].Config != nil && n.importTargets[0].Config.ProviderConfigRef != nil { + if n.importTargets[0].Config != nil { + imp := n.importTargets[0].Config ref := ProviderRef{ Addr: addrs.AbsProviderConfig{ - Provider: n.importTargets[0].Config.Provider, - Alias: n.importTargets[0].Config.ProviderConfigRef.Alias, + Provider: imp.Provider, Module: n.ModulePath(), }, } - ref.Addr.Alias = n.importTargets[0].Config.ProviderConfigRef.Alias + if imp.ProviderConfigRef != nil { + ref.Addr.Alias = imp.ProviderConfigRef.Alias + } return ref } } From 058b8d05608a507a5bb89b29ca2b9c174380053c Mon Sep 17 00:00:00 2001 From: Kristin Laemmert Date: Fri, 11 Sep 2026 08:43:35 -0400 Subject: [PATCH 18/33] remove changelog entry for backport --- .changes/v1.16/BUG FIXES-20260910-121207.yaml | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .changes/v1.16/BUG FIXES-20260910-121207.yaml diff --git a/.changes/v1.16/BUG FIXES-20260910-121207.yaml b/.changes/v1.16/BUG FIXES-20260910-121207.yaml deleted file mode 100644 index a91f782c6e29..000000000000 --- a/.changes/v1.16/BUG FIXES-20260910-121207.yaml +++ /dev/null @@ -1,5 +0,0 @@ -kind: BUG FIXES -body: Fix issue with import provider resolution -time: 2026-09-10T12:12:07.068649-04:00 -custom: - Issue: "39185" From b3d51ddf11c9f36c07cd6c48950b67c6eba0aa56 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 15 Sep 2026 10:09:33 -0400 Subject: [PATCH 19/33] backport of commit 61864b5bc22487fb6c081070db4dc3155d1f67ec (#39210) Co-authored-by: Austin Valle --- internal/backend/remote/backend_apply.go | 4 ++-- internal/backend/remote/backend_plan.go | 4 ++-- internal/cloud/backend_apply.go | 4 ++-- internal/cloud/backend_plan.go | 4 ++-- internal/terraform/node_resource_plan_instance.go | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/internal/backend/remote/backend_apply.go b/internal/backend/remote/backend_apply.go index 1fa6c1fae655..e9197abc9bf5 100644 --- a/internal/backend/remote/backend_apply.go +++ b/internal/backend/remote/backend_apply.go @@ -163,8 +163,8 @@ func (b *Remote) opApply(stopCtx, cancelCtx context.Context, op *backendrun.Oper if op.PlanMinimalRefresh { diags = diags.Append(tfdiags.Sourceless( tfdiags.Error, - "Minimal refresh mode is currently not supported", - `The "remote" backend does not support -minimal-refresh mode for `+ + "Minimal refresh planning option is currently not supported", + `The "remote" backend does not support the -minimal-refresh option for `+ `remote plans at this time.`, )) } diff --git a/internal/backend/remote/backend_plan.go b/internal/backend/remote/backend_plan.go index f37b238cb563..8d7afbc5ac24 100644 --- a/internal/backend/remote/backend_plan.go +++ b/internal/backend/remote/backend_plan.go @@ -179,8 +179,8 @@ func (b *Remote) opPlan(stopCtx, cancelCtx context.Context, op *backendrun.Opera if op.PlanMinimalRefresh { diags = diags.Append(tfdiags.Sourceless( tfdiags.Error, - "Minimal refresh mode is currently not supported", - `The "remote" backend does not support -minimal-refresh mode for `+ + "Minimal refresh planning option is currently not supported", + `The "remote" backend does not support the -minimal-refresh option for `+ `remote plans at this time.`, )) } diff --git a/internal/cloud/backend_apply.go b/internal/cloud/backend_apply.go index b8b08bed341c..0c6e99b8936c 100644 --- a/internal/cloud/backend_apply.go +++ b/internal/cloud/backend_apply.go @@ -80,8 +80,8 @@ func (b *Cloud) opApply(stopCtx, cancelCtx context.Context, op *backendrun.Opera if op.PlanMinimalRefresh { diags = diags.Append(tfdiags.Sourceless( tfdiags.Error, - "Minimal refresh mode is currently not supported", - fmt.Sprintf("%s does not support -minimal-refresh mode for ", b.appName)+ + "Minimal refresh planning option is currently not supported", + fmt.Sprintf("%s does not support the -minimal-refresh option for ", b.appName)+ "plans at this time.", )) } diff --git a/internal/cloud/backend_plan.go b/internal/cloud/backend_plan.go index f3a0817b8c83..812d39098012 100644 --- a/internal/cloud/backend_plan.go +++ b/internal/cloud/backend_plan.go @@ -90,8 +90,8 @@ func (b *Cloud) opPlan(stopCtx, cancelCtx context.Context, op *backendrun.Operat if op.PlanMinimalRefresh { diags = diags.Append(tfdiags.Sourceless( tfdiags.Error, - "Minimal refresh mode is currently not supported", - fmt.Sprintf("%s does not support -minimal-refresh mode for ", b.appName)+ + "Minimal refresh planning option is currently not supported", + fmt.Sprintf("%s does not support the -minimal-refresh option for ", b.appName)+ "plans at this time.", )) } diff --git a/internal/terraform/node_resource_plan_instance.go b/internal/terraform/node_resource_plan_instance.go index 9f26a7d34cc5..73a11479c1cc 100644 --- a/internal/terraform/node_resource_plan_instance.go +++ b/internal/terraform/node_resource_plan_instance.go @@ -385,7 +385,7 @@ func (n *NodePlannableResourceInstance) managedResourceExecute(ctx EvalContext) } if change.Action == plans.NoOp { - log.Printf("[DEBUG] Minimal refresh mode: skipping refresh as the initial plan is a no-op for %s", addr) + log.Printf("[DEBUG] Minimal refresh: skipping refresh as the initial plan is a no-op for %s", addr) if updatedCBD { // CreateBeforeDestroy must be set correctly in the state which is used @@ -412,12 +412,12 @@ func (n *NodePlannableResourceInstance) managedResourceExecute(ctx EvalContext) return diags.Append(initialPlanDiags) } else { - log.Printf("[DEBUG] Minimal refresh mode: refreshing resource as the initial plan produced a %s change for %s", change.Action, addr) + log.Printf("[DEBUG] Minimal refresh: refreshing resource as the initial plan produced a %s change for %s", change.Action, addr) } } if n.minimalRefresh && resourceDataUpgraded { - log.Printf("[DEBUG] Minimal refresh mode: refreshing resource as the schema version for either the state or identity has been updated for %s", addr) + log.Printf("[DEBUG] Minimal refresh: refreshing resource as the schema version for either the state or identity has been updated for %s", addr) } // Refresh, maybe From ee21cc14dc5274bde8f26dd8784db2b7566c38bb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 15 Sep 2026 14:17:00 -0400 Subject: [PATCH 20/33] backport of commit e2a9fb6e30c749c3a69e20ca9cabe089ab7bf196 (#39222) Co-authored-by: Austin Valle --- .go-version | 2 +- go.mod | 2 +- internal/backend/remote-state/azure/go.mod | 2 +- internal/backend/remote-state/consul/go.mod | 2 +- internal/backend/remote-state/cos/go.mod | 2 +- internal/backend/remote-state/gcs/go.mod | 2 +- internal/backend/remote-state/kubernetes/go.mod | 2 +- internal/backend/remote-state/oci/go.mod | 2 +- internal/backend/remote-state/oss/go.mod | 2 +- internal/backend/remote-state/pg/go.mod | 2 +- internal/backend/remote-state/s3/go.mod | 2 +- internal/legacy/go.mod | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.go-version b/.go-version index ea0928cedf0d..25691b4f1d0e 100644 --- a/.go-version +++ b/.go-version @@ -1 +1 @@ -1.26.4 +1.26.8 diff --git a/go.mod b/go.mod index a57453fdac3b..91a55446decf 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/terraform -go 1.26.4 +go 1.26.8 godebug winsymlink=0 diff --git a/internal/backend/remote-state/azure/go.mod b/internal/backend/remote-state/azure/go.mod index b0e7dc870318..894ceeee6e9e 100644 --- a/internal/backend/remote-state/azure/go.mod +++ b/internal/backend/remote-state/azure/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/terraform/internal/backend/remote-state/azure -go 1.26.4 +go 1.26.8 require ( github.com/hashicorp/go-azure-helpers v0.72.0 diff --git a/internal/backend/remote-state/consul/go.mod b/internal/backend/remote-state/consul/go.mod index b3a498e1706b..f7f9c748e664 100644 --- a/internal/backend/remote-state/consul/go.mod +++ b/internal/backend/remote-state/consul/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/terraform/internal/backend/remote-state/consul -go 1.26.4 +go 1.26.8 require ( github.com/hashicorp/consul/api v1.32.1 diff --git a/internal/backend/remote-state/cos/go.mod b/internal/backend/remote-state/cos/go.mod index 0fbbbc1d0b05..339aa7b5dac3 100644 --- a/internal/backend/remote-state/cos/go.mod +++ b/internal/backend/remote-state/cos/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/terraform/internal/backend/remote-state/cos -go 1.26.4 +go 1.26.8 require ( github.com/hashicorp/terraform v0.0.0-00010101000000-000000000000 diff --git a/internal/backend/remote-state/gcs/go.mod b/internal/backend/remote-state/gcs/go.mod index 1a113cf3f05b..8dc0fdb372dc 100644 --- a/internal/backend/remote-state/gcs/go.mod +++ b/internal/backend/remote-state/gcs/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/terraform/internal/backend/remote-state/gcs -go 1.26.4 +go 1.26.8 require ( cloud.google.com/go/kms v1.25.0 diff --git a/internal/backend/remote-state/kubernetes/go.mod b/internal/backend/remote-state/kubernetes/go.mod index 147216b8347b..f3a082cbf421 100644 --- a/internal/backend/remote-state/kubernetes/go.mod +++ b/internal/backend/remote-state/kubernetes/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/terraform/internal/backend/remote-state/kubernetes -go 1.26.4 +go 1.26.8 require ( github.com/hashicorp/terraform v0.0.0-00010101000000-000000000000 diff --git a/internal/backend/remote-state/oci/go.mod b/internal/backend/remote-state/oci/go.mod index d5f0b12aa573..d05358ae91d5 100644 --- a/internal/backend/remote-state/oci/go.mod +++ b/internal/backend/remote-state/oci/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/terraform/internal/backend/remote-state/oci -go 1.26.4 +go 1.26.8 require ( github.com/google/go-cmp v0.7.0 diff --git a/internal/backend/remote-state/oss/go.mod b/internal/backend/remote-state/oss/go.mod index da124f848639..9334e0536a32 100644 --- a/internal/backend/remote-state/oss/go.mod +++ b/internal/backend/remote-state/oss/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/terraform/internal/backend/remote-state/oss -go 1.26.4 +go 1.26.8 require ( github.com/aliyun/alibaba-cloud-sdk-go v1.61.1501 diff --git a/internal/backend/remote-state/pg/go.mod b/internal/backend/remote-state/pg/go.mod index a693b9f6e59c..a1e70a80f4ce 100644 --- a/internal/backend/remote-state/pg/go.mod +++ b/internal/backend/remote-state/pg/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/terraform/internal/backend/remote-state/pg -go 1.26.4 +go 1.26.8 require ( github.com/hashicorp/go-uuid v1.0.3 diff --git a/internal/backend/remote-state/s3/go.mod b/internal/backend/remote-state/s3/go.mod index 742f426b1496..af1902246dd8 100644 --- a/internal/backend/remote-state/s3/go.mod +++ b/internal/backend/remote-state/s3/go.mod @@ -1,6 +1,6 @@ module github.com/hashicorp/terraform/internal/backend/remote-state/s3 -go 1.26.4 +go 1.26.8 require ( github.com/aws/aws-sdk-go-v2 v1.41.5 diff --git a/internal/legacy/go.mod b/internal/legacy/go.mod index cf7917aa2b4f..76fcb1314189 100644 --- a/internal/legacy/go.mod +++ b/internal/legacy/go.mod @@ -2,7 +2,7 @@ module github.com/hashicorp/terraform/internal/legacy replace github.com/hashicorp/terraform => ../.. -go 1.26.4 +go 1.26.8 require ( github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc From f9891820088cf1ad1bfdf077bb4621a56988ff7d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 17 Sep 2026 17:49:37 -0400 Subject: [PATCH 21/33] Backport of provider: Add client capabilities to partial plan + open ephemeral resource RPC calls into v1.17 (#39241) --- .../terraform/context_apply_deferred_test.go | 111 +++++++++++++++--- internal/terraform/node_resource_ephemeral.go | 5 +- .../node_resource_plan_partialexp.go | 13 +- 3 files changed, 100 insertions(+), 29 deletions(-) diff --git a/internal/terraform/context_apply_deferred_test.go b/internal/terraform/context_apply_deferred_test.go index 5d394d8510c7..491eae967f9c 100644 --- a/internal/terraform/context_apply_deferred_test.go +++ b/internal/terraform/context_apply_deferred_test.go @@ -3916,23 +3916,6 @@ func TestContextApply_deferredActions(t *testing.T) { for ix, stage := range test.stages { t.Run(fmt.Sprintf("round-%d", ix), func(t *testing.T) { - provider := &deferredActionsProvider{ - plannedChanges: &deferredActionsChanges{ - changes: make(map[string]cty.Value), - }, - appliedChanges: &deferredActionsChanges{ - changes: make(map[string]cty.Value), - }, - } - other := simpleMockProvider() - - ctx := testContext2(t, &ContextOpts{ - Providers: map[addrs.Provider]providers.Factory{ - addrs.NewDefaultProvider("test"): testProviderFuncFixed(provider.Provider()), - addrs.NewDefaultProvider("other"): testProviderFuncFixed(other), - }, - }) - opts := &PlanOpts{ Mode: plans.NormalMode, DeferralAllowed: true, @@ -3952,6 +3935,25 @@ func TestContextApply_deferredActions(t *testing.T) { stage.buildOpts(opts) } + provider := &deferredActionsProvider{ + t: t, + deferralAllowed: opts.DeferralAllowed, + plannedChanges: &deferredActionsChanges{ + changes: make(map[string]cty.Value), + }, + appliedChanges: &deferredActionsChanges{ + changes: make(map[string]cty.Value), + }, + } + other := simpleMockProvider() + + ctx := testContext2(t, &ContextOpts{ + Providers: map[addrs.Provider]providers.Factory{ + addrs.NewDefaultProvider("test"): testProviderFuncFixed(provider.Provider()), + addrs.NewDefaultProvider("other"): testProviderFuncFixed(other), + }, + }) + var plan *plans.Plan t.Run("plan", func(t *testing.T) { var diags tfdiags.Diagnostics @@ -4098,8 +4100,10 @@ func (d *deferredActionsChanges) Test(t *testing.T, expected map[string]cty.Valu // deferredActionsProvider is a wrapper around the mock provider that keeps // track of its own planned changes. type deferredActionsProvider struct { - plannedChanges *deferredActionsChanges - appliedChanges *deferredActionsChanges + t *testing.T + deferralAllowed bool + plannedChanges *deferredActionsChanges + appliedChanges *deferredActionsChanges } func (provider *deferredActionsProvider) Provider() providers.Interface { @@ -4158,7 +4162,32 @@ func (provider *deferredActionsProvider) Provider() providers.Interface { }, }, }, + ConfigureProviderFn: func(req providers.ConfigureProviderRequest) providers.ConfigureProviderResponse { + // client capabilities should always be set + want := providers.ClientCapabilities{ + DeferralAllowed: provider.deferralAllowed, + WriteOnlyAttributesAllowed: true, + StorePlannedPrivate: true, + ComputedBlocksAllowed: true, + } + if diff := cmp.Diff(want, req.ClientCapabilities); diff != "" { + provider.t.Errorf("wrong client capabilities sent to provider in ConfigureProvider: \n%s", diff) + } + + return providers.ConfigureProviderResponse{} + }, ReadResourceFn: func(req providers.ReadResourceRequest) providers.ReadResourceResponse { + // client capabilities should always be set + want := providers.ClientCapabilities{ + DeferralAllowed: provider.deferralAllowed, + WriteOnlyAttributesAllowed: true, + StorePlannedPrivate: true, + ComputedBlocksAllowed: true, + } + if diff := cmp.Diff(want, req.ClientCapabilities); diff != "" { + provider.t.Errorf("wrong client capabilities sent to provider in ReadResource: \n%s", diff) + } + if key := req.PriorState.GetAttr("name"); key.IsKnown() && key.AsString() == "deferred_read" { return providers.ReadResourceResponse{ NewState: req.PriorState, @@ -4173,6 +4202,17 @@ func (provider *deferredActionsProvider) Provider() providers.Interface { } }, ReadDataSourceFn: func(req providers.ReadDataSourceRequest) providers.ReadDataSourceResponse { + // client capabilities should always be set + want := providers.ClientCapabilities{ + DeferralAllowed: provider.deferralAllowed, + WriteOnlyAttributesAllowed: true, + StorePlannedPrivate: true, + ComputedBlocksAllowed: true, + } + if diff := cmp.Diff(want, req.ClientCapabilities); diff != "" { + provider.t.Errorf("wrong client capabilities sent to provider in ReadDataSource: \n%s", diff) + } + if key := req.Config.GetAttr("name"); key.IsKnown() && key.AsString() == "deferred_read" { return providers.ReadDataSourceResponse{ State: req.Config, @@ -4189,6 +4229,17 @@ func (provider *deferredActionsProvider) Provider() providers.Interface { } }, PlanResourceChangeFn: func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse { + // client capabilities should always be set + want := providers.ClientCapabilities{ + DeferralAllowed: provider.deferralAllowed, + WriteOnlyAttributesAllowed: true, + StorePlannedPrivate: true, + ComputedBlocksAllowed: true, + } + if diff := cmp.Diff(want, req.ClientCapabilities); diff != "" { + provider.t.Errorf("wrong client capabilities sent to provider in PlanResourceChange: \n%s", diff) + } + var deferred *providers.Deferred var requiresReplace []cty.Path if req.ProposedNewState.IsNull() { @@ -4248,6 +4299,17 @@ func (provider *deferredActionsProvider) Provider() providers.Interface { } }, ImportResourceStateFn: func(request providers.ImportResourceStateRequest) providers.ImportResourceStateResponse { + // client capabilities should always be set + want := providers.ClientCapabilities{ + DeferralAllowed: provider.deferralAllowed, + WriteOnlyAttributesAllowed: true, + StorePlannedPrivate: true, + ComputedBlocksAllowed: true, + } + if diff := cmp.Diff(want, request.ClientCapabilities); diff != "" { + provider.t.Errorf("wrong client capabilities sent to provider in ImportResourceState: \n%s", diff) + } + if request.ID == "deferred" { return providers.ImportResourceStateResponse{ ImportedResources: []providers.ImportedResource{}, @@ -4271,6 +4333,17 @@ func (provider *deferredActionsProvider) Provider() providers.Interface { } }, OpenEphemeralResourceFn: func(op providers.OpenEphemeralResourceRequest) providers.OpenEphemeralResourceResponse { + // client capabilities should always be set + want := providers.ClientCapabilities{ + DeferralAllowed: provider.deferralAllowed, + WriteOnlyAttributesAllowed: true, + StorePlannedPrivate: true, + ComputedBlocksAllowed: true, + } + if diff := cmp.Diff(want, op.ClientCapabilities); diff != "" { + provider.t.Errorf("wrong client capabilities sent to provider in OpenEphemeralResource: \n%s", diff) + } + name := op.Config.GetAttr("name").AsString() res := providers.OpenEphemeralResourceResponse{ diff --git a/internal/terraform/node_resource_ephemeral.go b/internal/terraform/node_resource_ephemeral.go index 177b26fa855d..4e9d429e1279 100644 --- a/internal/terraform/node_resource_ephemeral.go +++ b/internal/terraform/node_resource_ephemeral.go @@ -149,8 +149,9 @@ func ephemeralResourceOpen(ctx EvalContext, inp ephemeralResourceInput) (*provid return h.PreEphemeralOp(rId, plans.Open) }) resp := provider.OpenEphemeralResource(providers.OpenEphemeralResourceRequest{ - TypeName: inp.addr.ContainingResource().Resource.Type, - Config: unmarkedConfigVal, + TypeName: inp.addr.ContainingResource().Resource.Type, + Config: unmarkedConfigVal, + ClientCapabilities: ctx.ClientCapabilities(), }) ctx.Hook(func(h Hook) (HookAction, error) { return h.PostEphemeralOp(rId, plans.Open, resp.Diagnostics.Err()) diff --git a/internal/terraform/node_resource_plan_partialexp.go b/internal/terraform/node_resource_plan_partialexp.go index 6a8d3c0903db..a323af22d69d 100644 --- a/internal/terraform/node_resource_plan_partialexp.go +++ b/internal/terraform/node_resource_plan_partialexp.go @@ -232,14 +232,11 @@ func (n *nodePlannablePartialExpandedResource) managedResourceExecute(ctx EvalCo // learn a subset of the "computed" attribute values to save as part // of our placeholder value for downstream checks. resp := provider.PlanResourceChange(providers.PlanResourceChangeRequest{ - TypeName: n.addr.Resource().Type, - Config: unmarkedConfigVal, - PriorState: priorVal, - ProposedNewState: proposedNewVal, - // TODO: Should we send "ProviderMeta" here? We don't have the - // necessary data for that wired through here right now, but - // we might need to do that before stabilizing support for unknown - // resource instance expansion. + TypeName: n.addr.Resource().Type, + Config: unmarkedConfigVal, + PriorState: priorVal, + ProposedNewState: proposedNewVal, + ClientCapabilities: ctx.ClientCapabilities(), }) diags = diags.Append(resp.Diagnostics.InConfigBody(n.config.Config, n.addr.String())) if diags.HasErrors() { From 9ce8b3dc79977f264aeee889327e298383701303 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 18 Sep 2026 11:02:34 -0400 Subject: [PATCH 22/33] backport of commit a4932aae68ce607f5a9f5cc3ebd6ef6572e71d0d (#39250) Co-authored-by: Austin Valle --- go.mod | 55 ++++----- go.sum | 115 +++++++++--------- internal/backend/remote-state/azure/go.sum | 36 +++--- internal/backend/remote-state/consul/go.sum | 36 +++--- internal/backend/remote-state/cos/go.sum | 36 +++--- internal/backend/remote-state/gcs/go.mod | 16 +-- internal/backend/remote-state/gcs/go.sum | 44 +++---- .../backend/remote-state/kubernetes/go.mod | 2 +- .../backend/remote-state/kubernetes/go.sum | 36 +++--- internal/backend/remote-state/oci/go.sum | 36 +++--- internal/backend/remote-state/oss/go.sum | 36 +++--- internal/backend/remote-state/pg/go.sum | 36 +++--- internal/backend/remote-state/s3/go.mod | 8 +- internal/backend/remote-state/s3/go.sum | 36 +++--- 14 files changed, 264 insertions(+), 264 deletions(-) diff --git a/go.mod b/go.mod index 91a55446decf..640146198c07 100644 --- a/go.mod +++ b/go.mod @@ -68,9 +68,9 @@ require ( github.com/zclconf/go-cty-yaml v1.1.0 go.opentelemetry.io/contrib/exporters/autoexport v0.68.0 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 - go.opentelemetry.io/otel v1.44.0 - go.opentelemetry.io/otel/sdk v1.44.0 - go.opentelemetry.io/otel/trace v1.44.0 + go.opentelemetry.io/otel v1.45.0 + go.opentelemetry.io/otel/sdk v1.45.0 + go.opentelemetry.io/otel/trace v1.45.0 go.uber.org/mock v0.6.0 golang.org/x/crypto v0.56.0 golang.org/x/mod v0.40.0 @@ -163,7 +163,7 @@ require ( github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect github.com/go-jose/go-jose/v4 v4.1.4 // indirect - github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/logr v1.4.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect @@ -212,7 +212,7 @@ require ( github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect - github.com/klauspost/compress v1.18.7 // indirect + github.com/klauspost/compress v1.19.1 // indirect github.com/knadh/koanf/maps v0.1.2 // indirect github.com/knadh/koanf/parsers/dotenv v1.1.1 // indirect github.com/knadh/koanf/parsers/hcl v1.0.0 // indirect @@ -249,11 +249,11 @@ require ( github.com/oracle/oci-go-sdk/v65 v65.89.1 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect - github.com/prometheus/client_golang v1.23.2 // indirect + github.com/prometheus/client_golang v1.24.1 // indirect github.com/prometheus/client_model v0.6.2 // indirect - github.com/prometheus/common v0.67.5 // indirect + github.com/prometheus/common v0.70.1 // indirect github.com/prometheus/otlptranslator v1.0.0 // indirect - github.com/prometheus/procfs v0.20.1 // indirect + github.com/prometheus/procfs v0.21.1 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/samber/lo v1.53.0 // indirect github.com/shopspring/decimal v1.4.0 // indirect @@ -279,24 +279,23 @@ require ( go.opentelemetry.io/contrib/detectors/gcp v1.44.0 // indirect go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.67.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.44.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.44.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.44.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.44.0 // indirect - go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.44.0 // indirect - go.opentelemetry.io/otel/exporters/prometheus v0.65.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.19.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.44.0 // indirect - go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.44.0 // indirect - go.opentelemetry.io/otel/log v0.19.0 // indirect - go.opentelemetry.io/otel/metric v1.44.0 // indirect - go.opentelemetry.io/otel/sdk/log v0.19.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.44.0 // indirect - go.opentelemetry.io/proto/otlp v1.10.0 // indirect - go.yaml.in/yaml/v2 v2.4.4 // indirect - go.yaml.in/yaml/v3 v3.0.4 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.21.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.21.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.45.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.45.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.45.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.45.0 // indirect + go.opentelemetry.io/otel/exporters/prometheus v0.67.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.21.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.45.0 // indirect + go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.45.0 // indirect + go.opentelemetry.io/otel/log v0.21.0 // indirect + go.opentelemetry.io/otel/metric v1.45.0 // indirect + go.opentelemetry.io/otel/sdk/log v0.21.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.45.0 // indirect + go.opentelemetry.io/proto/otlp v1.11.0 // indirect + go.yaml.in/yaml/v3 v3.0.5 // indirect golang.org/x/exp v0.0.0-20250506013437-ce4c2cf36ca6 // indirect golang.org/x/exp/typeparams v0.0.0-20231108232855-2478ac86f678 // indirect golang.org/x/sync v0.22.0 // indirect @@ -306,8 +305,8 @@ require ( google.golang.org/api v0.271.0 // indirect google.golang.org/appengine v1.6.8 // indirect google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d // indirect gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.66.2 // indirect diff --git a/go.sum b/go.sum index ed5a67667c46..518abefe6f3d 100644 --- a/go.sum +++ b/go.sum @@ -240,8 +240,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= +github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= @@ -452,8 +452,8 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.18.7 h1:aUyZsS4kH3QTKurYhAOwAHxllVPnOthb3vPfnF1Ehjw= -github.com/klauspost/compress v1.18.7/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk= +github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/knadh/koanf/maps v0.1.2 h1:RBfmAW5CnZT+PJ1CVc1QSJKf4Xu9kxfQgYVQSu8hpbo= github.com/knadh/koanf/maps v0.1.2/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= github.com/knadh/koanf/parsers/dotenv v1.1.1 h1:vfiRFsxq0ouiVs4t+R/VVA3TMrX5+VH14iEX6J5B1s4= @@ -598,8 +598,8 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o= -github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg= +github.com/prometheus/client_golang v1.24.1 h1:JnJkREXzWxUdCuPFpIWZiPispT9xVV59uiuyR2bPlnU= +github.com/prometheus/client_golang v1.24.1/go.mod h1:F+oSRECHg4sse5ucfYpYDeIv/hu68Zo0uoHKetWnzcE= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -609,8 +609,8 @@ github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTUGI4= -github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= +github.com/prometheus/common v0.70.1 h1:1HvjP4D5oL3t8RsPlwxA9onvvStjtIHYE5XuuwOi/PY= +github.com/prometheus/common v0.70.1/go.mod h1:VdFUQDMZK3VLkurFUVhia6uys/0suUp86TJz5qbJRhc= github.com/prometheus/otlptranslator v1.0.0 h1:s0LJW/iN9dkIH+EnhiD3BlkkP5QVIUVEoIwkU+A6qos= github.com/prometheus/otlptranslator v1.0.0/go.mod h1:vRYWnXvI6aWGpsdY/mOT/cbeVRBlPWtBNDb7kGR3uKM= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= @@ -618,8 +618,8 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.20.1 h1:XwbrGOIplXW/AU3YhIhLODXMJYyC1isLFfYCsTEycfc= -github.com/prometheus/procfs v0.20.1/go.mod h1:o9EMBZGRyvDrSPH1RqdxhojkuXstoe4UlK79eF5TGGo= +github.com/prometheus/procfs v0.21.1 h1:GljZCt+zSTS+NZq88cyQ1LjZ+RCHp3uVuabBWA5+OJI= +github.com/prometheus/procfs v0.21.1/go.mod h1:aB55Cww9pdSJVHk0hUf0inxWyyjPogFIjmHKYgMKmtY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= @@ -722,56 +722,57 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.6 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= -go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= -go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0 h1:Dn8rkudDzY6KV9dr/D/bTUuWgqDf9xe0rr4G2elrn0Y= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.19.0/go.mod h1:gMk9F0xDgyN9M/3Ed5Y1wKcx/9mlU91NXY2SNq7RQuU= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0 h1:HIBTQ3VO5aupLKjC90JgMqpezVXwFuq6Ryjn0/izoag= -go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.19.0/go.mod h1:ji9vId85hMxqfvICA0Jt8JqEdrXaAkcpkI9HPXya0ro= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.44.0 h1:SUplec5dp06reu1zaXmOXdvqH398taqrDXqUl99jxSc= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.44.0/go.mod h1:ho2g4N+ane+swq5I/VBkKWnRDY4kUINH3FuqyZqX/Ug= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.44.0 h1:RuynHbfU8JUEw7DyONgkVYg2SVtsoF28y0LGIr69jgA= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.44.0/go.mod h1:qZF+/lBs71APw8mlnEZcqZHMzqrYrsFiJOv83lX1OGo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.44.0 h1:4YsVu3B8+3qtWYYrsUYgn0OG78pN0rnNPRGX4SbokQI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.44.0/go.mod h1:+wnlSn0mD1ADVMe3v9Z/WIaiz6q6gL2J/ejaAmdmv80= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.44.0 h1:qazEJlUOQzhCpzQpFETGby7EdqjI1wsd0W+6Gg1SCTU= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.44.0/go.mod h1:fOD2Yefuxixkx3ahVNf0O/PERb6r4OlbxfATVnYvzCo= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.44.0 h1:lgh3PiVrRUWMLOVSkQicxzZll5NjF1r+AtsX1XRIHw0= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.44.0/go.mod h1:5Cnhth3m/AgOeTgE3ex12pPmiu/gGtZit03kSzx9X7s= -go.opentelemetry.io/otel/exporters/prometheus v0.65.0 h1:jOveH/b4lU9HT7y+Gfamf18BqlOuz2PWEvs8yM7Q6XE= -go.opentelemetry.io/otel/exporters/prometheus v0.65.0/go.mod h1:i1P8pcumauPtUI4YNopea1dhzEMuEqWP1xoUZDylLHo= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.19.0 h1:GJkybS+crDMdExT/BUNCEgfrmfboztcS6PhvSo88HKM= -go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.19.0/go.mod h1:NuAyxRYIG2lKX3YQkB+83StTxM7s52PUUkRRiC0wnYI= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.44.0 h1:hqxVTu/GtBF+vJ8d1fzW7fRxZFvgoDjWcxwwCaFDYpU= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.44.0/go.mod h1:z5fVEF4X5v0ESvlJqBrrFlBVoj5EQuefZpzsu7R+x5Q= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.44.0 h1:bl2S7Ubua0Nms+D/gAmznQTd4dxxMA93aKbcpKqiTCs= -go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.44.0/go.mod h1:L0hRV50XdVIODHUfWEqGRCXQvj2rV82STVo12FMFBU0= -go.opentelemetry.io/otel/log v0.19.0 h1:KUZs/GOsw79TBBMfDWsXS+KZ4g2Ckzksd1ymzsIEbo4= -go.opentelemetry.io/otel/log v0.19.0/go.mod h1:5DQYeGmxVIr4n0/BcJvF4upsraHjg6vudJJpnkL6Ipk= -go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= -go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= -go.opentelemetry.io/otel/metric/x v0.66.0 h1:YkCrx1zLOChi9ZcZ6euupOcsgzbVlec7D/xoEU1+cTA= -go.opentelemetry.io/otel/metric/x v0.66.0/go.mod h1:d1+BDj9t96do0/1LoU1ayfCv79ZgNE41qbhBvnMOBZk= -go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= -go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= -go.opentelemetry.io/otel/sdk/log v0.19.0 h1:scYVLqT22D2gqXItnWiocLUKGH9yvkkeql5dBDiXyko= -go.opentelemetry.io/otel/sdk/log v0.19.0/go.mod h1:vFBowwXGLlW9AvpuF7bMgnNI95LiW10szrOdvzBHlAg= -go.opentelemetry.io/otel/sdk/log/logtest v0.19.0 h1:BEbF7ZBB6qQloV/Ub1+3NQoOUnVtcGkU3XX4Ws3GQfk= -go.opentelemetry.io/otel/sdk/log/logtest v0.19.0/go.mod h1:Lua81/3yM0wOmoHTokLj9y9ADeA02v1naRrVrkAZuKk= -go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= -go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= -go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= -go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= -go.opentelemetry.io/proto/otlp v1.10.0 h1:IQRWgT5srOCYfiWnpqUYz9CVmbO8bFmKcwYxpuCSL2g= -go.opentelemetry.io/proto/otlp v1.10.0/go.mod h1:/CV4QoCR/S9yaPj8utp3lvQPoqMtxXdzn7ozvvozVqk= +go.opentelemetry.io/otel v1.45.0 h1:pdrWmLHofpubmArBv1LgFSv1Z0Ie/ppdZzu+kUN5EeU= +go.opentelemetry.io/otel v1.45.0/go.mod h1:XZxIqPapzEYnhNSScF5DIqXhm/rYi0FzCe2XddAwZfQ= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.21.0 h1:WseeVYf5dJZTsyPiyW5L14k5qsSibqXAMTSiFEDiWr0= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc v0.21.0/go.mod h1:SiLZnQS6Qk2eCpvr2CH/XMAOa64TWGXxEZJZCpD2Lmc= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.21.0 h1:fvNHGyo3CdRv/DQveXqhqBxnKTDyRaC5sMSQxilX/A0= +go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp v0.21.0/go.mod h1:zyGrjRKL2B/6+Jc/m4/otPoZqV2MY9ZjC/aBraRO7zc= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.45.0 h1:klTViGcsvLCd1xN3rZzfZ12NslC/OimbmR+k+A006RI= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.45.0/go.mod h1:jRsK04CWmXuY8A0O+wMpSf+t90RHZ53o5Qmxn2PQPfk= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.45.0 h1:pnxy6c/kvNBWdNNFzqpjuJLm9Hjhgk/Q0nY221rwuk0= +go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.45.0/go.mod h1:qw6YsFapotRwoDhXRZvljzaOvCQB7UfnafEJagpN2TA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.45.0 h1:QRefszxJmfPdjXUUm3j6iDzY03mTPXMjqErFqQ67vUg= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.45.0/go.mod h1:Tiz03lTBVBrm7eWZBOidzEaYaJa8tjwGUGv6d8mlTyk= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0 h1:fG5MCxGz8+2VtrN/WgqSpJFctVz24gpxj8CxkKmc8Ww= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.45.0/go.mod h1:BmAYTn+3ysbRe+IU2msxmf5Rx3g6DHvex+tWI3LdhYI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.45.0 h1:QBajQ2SrwQijzHyZbQlPsuIzpl/ll8DY6wPWsajeGcI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.45.0/go.mod h1:08ZQLjrPLQ6R4kAXvuOvODEer5Yh4CoFvll5qB2BCI8= +go.opentelemetry.io/otel/exporters/prometheus v0.67.0 h1:7IefDa35e6V3NoiqIeLDMDxMFyZDk5qcoC0Ax4cC16E= +go.opentelemetry.io/otel/exporters/prometheus v0.67.0/go.mod h1:nsPI1awTg5Vmg1YrommL2mVarVGlqc4yXOoKAkPRD0c= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.21.0 h1:2lpf4hnrasYIsUyEXwnTZq5lsxrMm4T2Bwb06IctAZQ= +go.opentelemetry.io/otel/exporters/stdout/stdoutlog v0.21.0/go.mod h1:YWOW6h7jwApz9Pl76ie/izUsSPj0s2MdIlpqbPqaf3U= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.45.0 h1:dm9iyzn6tioYZtwqaiBSU0TSI8Yu/8dTIbfG0+B49DY= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.45.0/go.mod h1:xAvxYjYK28qvt+yu4BYZ/zMmAjwMXINXD6JiMyeB8iI= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.45.0 h1:lsA/S1bxgdbyFGkTj+3meEdJ6ADVU7QoFstV6MXgE68= +go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.45.0/go.mod h1:L7u+MirGoB1bjeLH66+xDykF4RC8C3RN7lIFpBiewUo= +go.opentelemetry.io/otel/log v0.21.0 h1:SLsVDGmtyBrdw8/a2Z0bOIxou/+bN4z56GebH7T0LvA= +go.opentelemetry.io/otel/log v0.21.0/go.mod h1:iReetQrZL9Wyg84cCkOoCmqDHS5RCFfyxC7J+r8fn8g= +go.opentelemetry.io/otel/metric v1.45.0 h1:7Eg1uH7CJ5cXv9is6tnBe1FI6rj1nwUdbFypRm3br/M= +go.opentelemetry.io/otel/metric v1.45.0/go.mod h1:HAPbm1nd3p1PmFH7v2dR+6BjXxw+Lq4a2+pndMAm08s= +go.opentelemetry.io/otel/metric/x v0.67.0 h1:PcicCNZFkZ4bXfSooXdo3WN7RBOVOtjVdo1wD358Uns= +go.opentelemetry.io/otel/metric/x v0.67.0/go.mod h1:FBjCWZe6wgcqxcMtjdGiClDKXb2YxxXii0CXftE4QtI= +go.opentelemetry.io/otel/sdk v1.45.0 h1:4VVSMgQ83dUgW2aoX5f6JgLvHwIvzcuLnF9lUdCSpCw= +go.opentelemetry.io/otel/sdk v1.45.0/go.mod h1:Sr40LgXV7DsKMMJMKOhUWOgMWTfAaqvm2kF0g7ilwuA= +go.opentelemetry.io/otel/sdk/log v0.21.0 h1:QsE7XSR0ktQdKmRKGnR+f1ObGF32WG+7MER/P9KgmYc= +go.opentelemetry.io/otel/sdk/log v0.21.0/go.mod h1:m9mApjCoD2/1QuKCAptjv+BrG9WKOvQLVdNx+iBldTo= +go.opentelemetry.io/otel/sdk/log/logtest v0.21.0 h1:X+JBBgKlswCGYsmgL0CnoUUtlE//VB345c84jYAYkdQ= +go.opentelemetry.io/otel/sdk/log/logtest v0.21.0/go.mod h1:HD1575K8e6sIFBBDd5tZB3t9DlMytWXq9FuR+Y4rfjE= +go.opentelemetry.io/otel/sdk/metric v1.45.0 h1:oVFszMfyj1Am6s24Vtc7wBb8BKLcwepJjNEYILuiE3o= +go.opentelemetry.io/otel/sdk/metric v1.45.0/go.mod h1:vUWUxDZvu1WVRj8JA8S0AdhsPrZoDpA2DdZauIh4mDA= +go.opentelemetry.io/otel/trace v1.45.0 h1:l/mP6Uv7oNO7/TblbhpbgMidxhq1uO/rPsikOyVhxag= +go.opentelemetry.io/otel/trace v1.45.0/go.mod h1:qoJJA2xNMnxRrdISU/kLtfUH2wNeQbiv+jhs/CxI8bc= +go.opentelemetry.io/proto/otlp v1.11.0 h1:5rrYs0Ykyj50sdU/JU0x8etU+LubXWb+gED6TbEdMIk= +go.opentelemetry.io/proto/otlp v1.11.0/go.mod h1:SmVizdCOAm3XBtG1g1NnOdhW6jtddT72hLMhv8VwA8E= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ= go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ= -go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw= +go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -910,10 +911,10 @@ google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAs google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d h1:IL4hdHzcUv2l/gcg98/Rj3FbtE6axwqslOW8SW0C+S0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU= google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A= diff --git a/internal/backend/remote-state/azure/go.sum b/internal/backend/remote-state/azure/go.sum index e52a078d14f0..3da44a6d9ed0 100644 --- a/internal/backend/remote-state/azure/go.sum +++ b/internal/backend/remote-state/azure/go.sum @@ -113,8 +113,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= +github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= @@ -185,8 +185,8 @@ github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8 github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= github.com/jackofallops/giovanni v0.28.0 h1:fxn55SnxL2Rj3hgkkgQS9UKlIRXkkTZ5WcnE04JCBRE= github.com/jackofallops/giovanni v0.28.0/go.mod h1:CyzRgZyts4YSI/1iZF8poqdn9I6J8xpmg1iMpvhthTs= -github.com/klauspost/compress v1.18.7 h1:aUyZsS4kH3QTKurYhAOwAHxllVPnOthb3vPfnF1Ehjw= -github.com/klauspost/compress v1.18.7/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk= +github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= @@ -257,16 +257,16 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.6 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= -go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= -go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= -go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= -go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= -go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= -go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= -go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= -go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= -go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= -go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= +go.opentelemetry.io/otel v1.45.0 h1:pdrWmLHofpubmArBv1LgFSv1Z0Ie/ppdZzu+kUN5EeU= +go.opentelemetry.io/otel v1.45.0/go.mod h1:XZxIqPapzEYnhNSScF5DIqXhm/rYi0FzCe2XddAwZfQ= +go.opentelemetry.io/otel/metric v1.45.0 h1:7Eg1uH7CJ5cXv9is6tnBe1FI6rj1nwUdbFypRm3br/M= +go.opentelemetry.io/otel/metric v1.45.0/go.mod h1:HAPbm1nd3p1PmFH7v2dR+6BjXxw+Lq4a2+pndMAm08s= +go.opentelemetry.io/otel/sdk v1.45.0 h1:4VVSMgQ83dUgW2aoX5f6JgLvHwIvzcuLnF9lUdCSpCw= +go.opentelemetry.io/otel/sdk v1.45.0/go.mod h1:Sr40LgXV7DsKMMJMKOhUWOgMWTfAaqvm2kF0g7ilwuA= +go.opentelemetry.io/otel/sdk/metric v1.45.0 h1:oVFszMfyj1Am6s24Vtc7wBb8BKLcwepJjNEYILuiE3o= +go.opentelemetry.io/otel/sdk/metric v1.45.0/go.mod h1:vUWUxDZvu1WVRj8JA8S0AdhsPrZoDpA2DdZauIh4mDA= +go.opentelemetry.io/otel/trace v1.45.0 h1:l/mP6Uv7oNO7/TblbhpbgMidxhq1uO/rPsikOyVhxag= +go.opentelemetry.io/otel/trace v1.45.0/go.mod h1:qoJJA2xNMnxRrdISU/kLtfUH2wNeQbiv+jhs/CxI8bc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= @@ -345,10 +345,10 @@ google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAs google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d h1:IL4hdHzcUv2l/gcg98/Rj3FbtE6axwqslOW8SW0C+S0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU= google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= diff --git a/internal/backend/remote-state/consul/go.sum b/internal/backend/remote-state/consul/go.sum index c21f48e9bb1d..97cc43b93ddb 100644 --- a/internal/backend/remote-state/consul/go.sum +++ b/internal/backend/remote-state/consul/go.sum @@ -114,8 +114,8 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= +github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -217,8 +217,8 @@ github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/ github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/klauspost/compress v1.18.7 h1:aUyZsS4kH3QTKurYhAOwAHxllVPnOthb3vPfnF1Ehjw= -github.com/klauspost/compress v1.18.7/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk= +github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= @@ -326,16 +326,16 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.6 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= -go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= -go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= -go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= -go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= -go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= -go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= -go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= -go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= -go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= -go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= +go.opentelemetry.io/otel v1.45.0 h1:pdrWmLHofpubmArBv1LgFSv1Z0Ie/ppdZzu+kUN5EeU= +go.opentelemetry.io/otel v1.45.0/go.mod h1:XZxIqPapzEYnhNSScF5DIqXhm/rYi0FzCe2XddAwZfQ= +go.opentelemetry.io/otel/metric v1.45.0 h1:7Eg1uH7CJ5cXv9is6tnBe1FI6rj1nwUdbFypRm3br/M= +go.opentelemetry.io/otel/metric v1.45.0/go.mod h1:HAPbm1nd3p1PmFH7v2dR+6BjXxw+Lq4a2+pndMAm08s= +go.opentelemetry.io/otel/sdk v1.45.0 h1:4VVSMgQ83dUgW2aoX5f6JgLvHwIvzcuLnF9lUdCSpCw= +go.opentelemetry.io/otel/sdk v1.45.0/go.mod h1:Sr40LgXV7DsKMMJMKOhUWOgMWTfAaqvm2kF0g7ilwuA= +go.opentelemetry.io/otel/sdk/metric v1.45.0 h1:oVFszMfyj1Am6s24Vtc7wBb8BKLcwepJjNEYILuiE3o= +go.opentelemetry.io/otel/sdk/metric v1.45.0/go.mod h1:vUWUxDZvu1WVRj8JA8S0AdhsPrZoDpA2DdZauIh4mDA= +go.opentelemetry.io/otel/trace v1.45.0 h1:l/mP6Uv7oNO7/TblbhpbgMidxhq1uO/rPsikOyVhxag= +go.opentelemetry.io/otel/trace v1.45.0/go.mod h1:qoJJA2xNMnxRrdISU/kLtfUH2wNeQbiv+jhs/CxI8bc= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -398,10 +398,10 @@ google.golang.org/api v0.271.0/go.mod h1:CGT29bhwkbF+i11qkRUJb2KMKqcJ1hdFceEIRd9 google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d h1:IL4hdHzcUv2l/gcg98/Rj3FbtE6axwqslOW8SW0C+S0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU= google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= diff --git a/internal/backend/remote-state/cos/go.sum b/internal/backend/remote-state/cos/go.sum index 4586775f0add..5392a569bc5f 100644 --- a/internal/backend/remote-state/cos/go.sum +++ b/internal/backend/remote-state/cos/go.sum @@ -96,8 +96,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= +github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= @@ -146,8 +146,8 @@ github.com/hashicorp/terraform-svchost v0.2.1 h1:ubvrTFw3Q7CsoEaX7V06PtCTKG3wu7G github.com/hashicorp/terraform-svchost v0.2.1/go.mod h1:zDMheBLvNzu7Q6o9TBvPqiZToJcSuCLXjAXxBslSky4= github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= -github.com/klauspost/compress v1.18.7 h1:aUyZsS4kH3QTKurYhAOwAHxllVPnOthb3vPfnF1Ehjw= -github.com/klauspost/compress v1.18.7/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk= +github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -217,16 +217,16 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.6 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= -go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= -go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= -go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= -go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= -go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= -go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= -go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= -go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= -go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= -go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= +go.opentelemetry.io/otel v1.45.0 h1:pdrWmLHofpubmArBv1LgFSv1Z0Ie/ppdZzu+kUN5EeU= +go.opentelemetry.io/otel v1.45.0/go.mod h1:XZxIqPapzEYnhNSScF5DIqXhm/rYi0FzCe2XddAwZfQ= +go.opentelemetry.io/otel/metric v1.45.0 h1:7Eg1uH7CJ5cXv9is6tnBe1FI6rj1nwUdbFypRm3br/M= +go.opentelemetry.io/otel/metric v1.45.0/go.mod h1:HAPbm1nd3p1PmFH7v2dR+6BjXxw+Lq4a2+pndMAm08s= +go.opentelemetry.io/otel/sdk v1.45.0 h1:4VVSMgQ83dUgW2aoX5f6JgLvHwIvzcuLnF9lUdCSpCw= +go.opentelemetry.io/otel/sdk v1.45.0/go.mod h1:Sr40LgXV7DsKMMJMKOhUWOgMWTfAaqvm2kF0g7ilwuA= +go.opentelemetry.io/otel/sdk/metric v1.45.0 h1:oVFszMfyj1Am6s24Vtc7wBb8BKLcwepJjNEYILuiE3o= +go.opentelemetry.io/otel/sdk/metric v1.45.0/go.mod h1:vUWUxDZvu1WVRj8JA8S0AdhsPrZoDpA2DdZauIh4mDA= +go.opentelemetry.io/otel/trace v1.45.0 h1:l/mP6Uv7oNO7/TblbhpbgMidxhq1uO/rPsikOyVhxag= +go.opentelemetry.io/otel/trace v1.45.0/go.mod h1:qoJJA2xNMnxRrdISU/kLtfUH2wNeQbiv+jhs/CxI8bc= golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y= golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I= golang.org/x/mod v0.40.0 h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs= @@ -256,10 +256,10 @@ google.golang.org/api v0.271.0 h1:cIPN4qcUc61jlh7oXu6pwOQqbJW2GqYh5PS6rB2C/JY= google.golang.org/api v0.271.0/go.mod h1:CGT29bhwkbF+i11qkRUJb2KMKqcJ1hdFceEIRd9u64Q= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d h1:IL4hdHzcUv2l/gcg98/Rj3FbtE6axwqslOW8SW0C+S0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU= google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= diff --git a/internal/backend/remote-state/gcs/go.mod b/internal/backend/remote-state/gcs/go.mod index 8dc0fdb372dc..20747e012a0c 100644 --- a/internal/backend/remote-state/gcs/go.mod +++ b/internal/backend/remote-state/gcs/go.mod @@ -40,7 +40,7 @@ require ( github.com/fatih/color v1.18.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/go-jose/go-jose/v4 v4.1.4 // indirect - github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/logr v1.4.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/google/go-cmp v0.7.0 // indirect github.com/google/s2a-go v0.1.9 // indirect @@ -67,11 +67,11 @@ require ( go.opentelemetry.io/contrib/detectors/gcp v1.44.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect - go.opentelemetry.io/otel v1.44.0 // indirect - go.opentelemetry.io/otel/metric v1.44.0 // indirect - go.opentelemetry.io/otel/sdk v1.44.0 // indirect - go.opentelemetry.io/otel/sdk/metric v1.44.0 // indirect - go.opentelemetry.io/otel/trace v1.44.0 // indirect + go.opentelemetry.io/otel v1.45.0 // indirect + go.opentelemetry.io/otel/metric v1.45.0 // indirect + go.opentelemetry.io/otel/sdk v1.45.0 // indirect + go.opentelemetry.io/otel/sdk/metric v1.45.0 // indirect + go.opentelemetry.io/otel/trace v1.45.0 // indirect golang.org/x/crypto v0.56.0 // indirect golang.org/x/mod v0.40.0 // indirect golang.org/x/net v0.58.0 // indirect @@ -80,8 +80,8 @@ require ( golang.org/x/text v0.41.0 // indirect golang.org/x/time v0.15.0 // indirect golang.org/x/tools v0.49.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d // indirect google.golang.org/grpc v1.83.2 // indirect google.golang.org/protobuf v1.36.11 // indirect ) diff --git a/internal/backend/remote-state/gcs/go.sum b/internal/backend/remote-state/gcs/go.sum index 1dbb1522c3c4..5150d76d1098 100644 --- a/internal/backend/remote-state/gcs/go.sum +++ b/internal/backend/remote-state/gcs/go.sum @@ -108,8 +108,8 @@ github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= +github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= @@ -155,8 +155,8 @@ github.com/hashicorp/terraform-svchost v0.2.1 h1:ubvrTFw3Q7CsoEaX7V06PtCTKG3wu7G github.com/hashicorp/terraform-svchost v0.2.1/go.mod h1:zDMheBLvNzu7Q6o9TBvPqiZToJcSuCLXjAXxBslSky4= github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= -github.com/klauspost/compress v1.18.7 h1:aUyZsS4kH3QTKurYhAOwAHxllVPnOthb3vPfnF1Ehjw= -github.com/klauspost/compress v1.18.7/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk= +github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -207,20 +207,20 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.6 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= -go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= -go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.44.0 h1:hqxVTu/GtBF+vJ8d1fzW7fRxZFvgoDjWcxwwCaFDYpU= -go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.44.0/go.mod h1:z5fVEF4X5v0ESvlJqBrrFlBVoj5EQuefZpzsu7R+x5Q= -go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= -go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= -go.opentelemetry.io/otel/metric/x v0.66.0 h1:YkCrx1zLOChi9ZcZ6euupOcsgzbVlec7D/xoEU1+cTA= -go.opentelemetry.io/otel/metric/x v0.66.0/go.mod h1:d1+BDj9t96do0/1LoU1ayfCv79ZgNE41qbhBvnMOBZk= -go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= -go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= -go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= -go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= -go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= -go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= +go.opentelemetry.io/otel v1.45.0 h1:pdrWmLHofpubmArBv1LgFSv1Z0Ie/ppdZzu+kUN5EeU= +go.opentelemetry.io/otel v1.45.0/go.mod h1:XZxIqPapzEYnhNSScF5DIqXhm/rYi0FzCe2XddAwZfQ= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.45.0 h1:dm9iyzn6tioYZtwqaiBSU0TSI8Yu/8dTIbfG0+B49DY= +go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.45.0/go.mod h1:xAvxYjYK28qvt+yu4BYZ/zMmAjwMXINXD6JiMyeB8iI= +go.opentelemetry.io/otel/metric v1.45.0 h1:7Eg1uH7CJ5cXv9is6tnBe1FI6rj1nwUdbFypRm3br/M= +go.opentelemetry.io/otel/metric v1.45.0/go.mod h1:HAPbm1nd3p1PmFH7v2dR+6BjXxw+Lq4a2+pndMAm08s= +go.opentelemetry.io/otel/metric/x v0.67.0 h1:PcicCNZFkZ4bXfSooXdo3WN7RBOVOtjVdo1wD358Uns= +go.opentelemetry.io/otel/metric/x v0.67.0/go.mod h1:FBjCWZe6wgcqxcMtjdGiClDKXb2YxxXii0CXftE4QtI= +go.opentelemetry.io/otel/sdk v1.45.0 h1:4VVSMgQ83dUgW2aoX5f6JgLvHwIvzcuLnF9lUdCSpCw= +go.opentelemetry.io/otel/sdk v1.45.0/go.mod h1:Sr40LgXV7DsKMMJMKOhUWOgMWTfAaqvm2kF0g7ilwuA= +go.opentelemetry.io/otel/sdk/metric v1.45.0 h1:oVFszMfyj1Am6s24Vtc7wBb8BKLcwepJjNEYILuiE3o= +go.opentelemetry.io/otel/sdk/metric v1.45.0/go.mod h1:vUWUxDZvu1WVRj8JA8S0AdhsPrZoDpA2DdZauIh4mDA= +go.opentelemetry.io/otel/trace v1.45.0 h1:l/mP6Uv7oNO7/TblbhpbgMidxhq1uO/rPsikOyVhxag= +go.opentelemetry.io/otel/trace v1.45.0/go.mod h1:qoJJA2xNMnxRrdISU/kLtfUH2wNeQbiv+jhs/CxI8bc= golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y= golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I= golang.org/x/mod v0.40.0 h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs= @@ -252,10 +252,10 @@ google.golang.org/api v0.271.0 h1:cIPN4qcUc61jlh7oXu6pwOQqbJW2GqYh5PS6rB2C/JY= google.golang.org/api v0.271.0/go.mod h1:CGT29bhwkbF+i11qkRUJb2KMKqcJ1hdFceEIRd9u64Q= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d h1:IL4hdHzcUv2l/gcg98/Rj3FbtE6axwqslOW8SW0C+S0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU= google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= diff --git a/internal/backend/remote-state/kubernetes/go.mod b/internal/backend/remote-state/kubernetes/go.mod index f3a082cbf421..9c373f1dbc1a 100644 --- a/internal/backend/remote-state/kubernetes/go.mod +++ b/internal/backend/remote-state/kubernetes/go.mod @@ -24,7 +24,7 @@ require ( github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/fatih/color v1.18.0 // indirect github.com/fxamacker/cbor/v2 v2.7.0 // indirect - github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/logr v1.4.4 // indirect github.com/go-openapi/jsonpointer v0.21.0 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect github.com/go-openapi/swag v0.23.0 // indirect diff --git a/internal/backend/remote-state/kubernetes/go.sum b/internal/backend/remote-state/kubernetes/go.sum index 0371ecaa090d..49133a1bcb6b 100644 --- a/internal/backend/remote-state/kubernetes/go.sum +++ b/internal/backend/remote-state/kubernetes/go.sum @@ -98,8 +98,8 @@ github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= +github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= @@ -167,8 +167,8 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/compress v1.18.7 h1:aUyZsS4kH3QTKurYhAOwAHxllVPnOthb3vPfnF1Ehjw= -github.com/klauspost/compress v1.18.7/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk= +github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -256,16 +256,16 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.6 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= -go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= -go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= -go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= -go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= -go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= -go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= -go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= -go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= -go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= -go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= +go.opentelemetry.io/otel v1.45.0 h1:pdrWmLHofpubmArBv1LgFSv1Z0Ie/ppdZzu+kUN5EeU= +go.opentelemetry.io/otel v1.45.0/go.mod h1:XZxIqPapzEYnhNSScF5DIqXhm/rYi0FzCe2XddAwZfQ= +go.opentelemetry.io/otel/metric v1.45.0 h1:7Eg1uH7CJ5cXv9is6tnBe1FI6rj1nwUdbFypRm3br/M= +go.opentelemetry.io/otel/metric v1.45.0/go.mod h1:HAPbm1nd3p1PmFH7v2dR+6BjXxw+Lq4a2+pndMAm08s= +go.opentelemetry.io/otel/sdk v1.45.0 h1:4VVSMgQ83dUgW2aoX5f6JgLvHwIvzcuLnF9lUdCSpCw= +go.opentelemetry.io/otel/sdk v1.45.0/go.mod h1:Sr40LgXV7DsKMMJMKOhUWOgMWTfAaqvm2kF0g7ilwuA= +go.opentelemetry.io/otel/sdk/metric v1.45.0 h1:oVFszMfyj1Am6s24Vtc7wBb8BKLcwepJjNEYILuiE3o= +go.opentelemetry.io/otel/sdk/metric v1.45.0/go.mod h1:vUWUxDZvu1WVRj8JA8S0AdhsPrZoDpA2DdZauIh4mDA= +go.opentelemetry.io/otel/trace v1.45.0 h1:l/mP6Uv7oNO7/TblbhpbgMidxhq1uO/rPsikOyVhxag= +go.opentelemetry.io/otel/trace v1.45.0/go.mod h1:qoJJA2xNMnxRrdISU/kLtfUH2wNeQbiv+jhs/CxI8bc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -320,10 +320,10 @@ google.golang.org/api v0.271.0 h1:cIPN4qcUc61jlh7oXu6pwOQqbJW2GqYh5PS6rB2C/JY= google.golang.org/api v0.271.0/go.mod h1:CGT29bhwkbF+i11qkRUJb2KMKqcJ1hdFceEIRd9u64Q= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d h1:IL4hdHzcUv2l/gcg98/Rj3FbtE6axwqslOW8SW0C+S0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU= google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= diff --git a/internal/backend/remote-state/oci/go.sum b/internal/backend/remote-state/oci/go.sum index 085713ebef78..1556c117a1b3 100644 --- a/internal/backend/remote-state/oci/go.sum +++ b/internal/backend/remote-state/oci/go.sum @@ -93,8 +93,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= +github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= @@ -141,8 +141,8 @@ github.com/hashicorp/terraform-svchost v0.2.1 h1:ubvrTFw3Q7CsoEaX7V06PtCTKG3wu7G github.com/hashicorp/terraform-svchost v0.2.1/go.mod h1:zDMheBLvNzu7Q6o9TBvPqiZToJcSuCLXjAXxBslSky4= github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= -github.com/klauspost/compress v1.18.7 h1:aUyZsS4kH3QTKurYhAOwAHxllVPnOthb3vPfnF1Ehjw= -github.com/klauspost/compress v1.18.7/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk= +github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -206,16 +206,16 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.6 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= -go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= -go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= -go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= -go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= -go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= -go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= -go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= -go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= -go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= -go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= +go.opentelemetry.io/otel v1.45.0 h1:pdrWmLHofpubmArBv1LgFSv1Z0Ie/ppdZzu+kUN5EeU= +go.opentelemetry.io/otel v1.45.0/go.mod h1:XZxIqPapzEYnhNSScF5DIqXhm/rYi0FzCe2XddAwZfQ= +go.opentelemetry.io/otel/metric v1.45.0 h1:7Eg1uH7CJ5cXv9is6tnBe1FI6rj1nwUdbFypRm3br/M= +go.opentelemetry.io/otel/metric v1.45.0/go.mod h1:HAPbm1nd3p1PmFH7v2dR+6BjXxw+Lq4a2+pndMAm08s= +go.opentelemetry.io/otel/sdk v1.45.0 h1:4VVSMgQ83dUgW2aoX5f6JgLvHwIvzcuLnF9lUdCSpCw= +go.opentelemetry.io/otel/sdk v1.45.0/go.mod h1:Sr40LgXV7DsKMMJMKOhUWOgMWTfAaqvm2kF0g7ilwuA= +go.opentelemetry.io/otel/sdk/metric v1.45.0 h1:oVFszMfyj1Am6s24Vtc7wBb8BKLcwepJjNEYILuiE3o= +go.opentelemetry.io/otel/sdk/metric v1.45.0/go.mod h1:vUWUxDZvu1WVRj8JA8S0AdhsPrZoDpA2DdZauIh4mDA= +go.opentelemetry.io/otel/trace v1.45.0 h1:l/mP6Uv7oNO7/TblbhpbgMidxhq1uO/rPsikOyVhxag= +go.opentelemetry.io/otel/trace v1.45.0/go.mod h1:qoJJA2xNMnxRrdISU/kLtfUH2wNeQbiv+jhs/CxI8bc= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= @@ -286,10 +286,10 @@ google.golang.org/api v0.271.0 h1:cIPN4qcUc61jlh7oXu6pwOQqbJW2GqYh5PS6rB2C/JY= google.golang.org/api v0.271.0/go.mod h1:CGT29bhwkbF+i11qkRUJb2KMKqcJ1hdFceEIRd9u64Q= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d h1:IL4hdHzcUv2l/gcg98/Rj3FbtE6axwqslOW8SW0C+S0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU= google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= diff --git a/internal/backend/remote-state/oss/go.sum b/internal/backend/remote-state/oss/go.sum index 80f40c5e28fb..bf207b10476a 100644 --- a/internal/backend/remote-state/oss/go.sum +++ b/internal/backend/remote-state/oss/go.sum @@ -100,8 +100,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= +github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= @@ -155,8 +155,8 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfC github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/klauspost/compress v1.18.7 h1:aUyZsS4kH3QTKurYhAOwAHxllVPnOthb3vPfnF1Ehjw= -github.com/klauspost/compress v1.18.7/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk= +github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -232,16 +232,16 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.6 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= -go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= -go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= -go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= -go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= -go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= -go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= -go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= -go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= -go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= -go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= +go.opentelemetry.io/otel v1.45.0 h1:pdrWmLHofpubmArBv1LgFSv1Z0Ie/ppdZzu+kUN5EeU= +go.opentelemetry.io/otel v1.45.0/go.mod h1:XZxIqPapzEYnhNSScF5DIqXhm/rYi0FzCe2XddAwZfQ= +go.opentelemetry.io/otel/metric v1.45.0 h1:7Eg1uH7CJ5cXv9is6tnBe1FI6rj1nwUdbFypRm3br/M= +go.opentelemetry.io/otel/metric v1.45.0/go.mod h1:HAPbm1nd3p1PmFH7v2dR+6BjXxw+Lq4a2+pndMAm08s= +go.opentelemetry.io/otel/sdk v1.45.0 h1:4VVSMgQ83dUgW2aoX5f6JgLvHwIvzcuLnF9lUdCSpCw= +go.opentelemetry.io/otel/sdk v1.45.0/go.mod h1:Sr40LgXV7DsKMMJMKOhUWOgMWTfAaqvm2kF0g7ilwuA= +go.opentelemetry.io/otel/sdk/metric v1.45.0 h1:oVFszMfyj1Am6s24Vtc7wBb8BKLcwepJjNEYILuiE3o= +go.opentelemetry.io/otel/sdk/metric v1.45.0/go.mod h1:vUWUxDZvu1WVRj8JA8S0AdhsPrZoDpA2DdZauIh4mDA= +go.opentelemetry.io/otel/trace v1.45.0 h1:l/mP6Uv7oNO7/TblbhpbgMidxhq1uO/rPsikOyVhxag= +go.opentelemetry.io/otel/trace v1.45.0/go.mod h1:qoJJA2xNMnxRrdISU/kLtfUH2wNeQbiv+jhs/CxI8bc= golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y= golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I= golang.org/x/mod v0.40.0 h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs= @@ -271,10 +271,10 @@ google.golang.org/api v0.271.0 h1:cIPN4qcUc61jlh7oXu6pwOQqbJW2GqYh5PS6rB2C/JY= google.golang.org/api v0.271.0/go.mod h1:CGT29bhwkbF+i11qkRUJb2KMKqcJ1hdFceEIRd9u64Q= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d h1:IL4hdHzcUv2l/gcg98/Rj3FbtE6axwqslOW8SW0C+S0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU= google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= diff --git a/internal/backend/remote-state/pg/go.sum b/internal/backend/remote-state/pg/go.sum index d60367c8eee7..62d6085c602c 100644 --- a/internal/backend/remote-state/pg/go.sum +++ b/internal/backend/remote-state/pg/go.sum @@ -93,8 +93,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= +github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= @@ -138,8 +138,8 @@ github.com/hashicorp/terraform-svchost v0.2.1 h1:ubvrTFw3Q7CsoEaX7V06PtCTKG3wu7G github.com/hashicorp/terraform-svchost v0.2.1/go.mod h1:zDMheBLvNzu7Q6o9TBvPqiZToJcSuCLXjAXxBslSky4= github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= -github.com/klauspost/compress v1.18.7 h1:aUyZsS4kH3QTKurYhAOwAHxllVPnOthb3vPfnF1Ehjw= -github.com/klauspost/compress v1.18.7/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk= +github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/lib/pq v1.10.3 h1:v9QZf2Sn6AmjXtQeFpdoq/eaNtYP6IN+7lcrygsIAtg= @@ -190,16 +190,16 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.6 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= -go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= -go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= -go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= -go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= -go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= -go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= -go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= -go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= -go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= -go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= +go.opentelemetry.io/otel v1.45.0 h1:pdrWmLHofpubmArBv1LgFSv1Z0Ie/ppdZzu+kUN5EeU= +go.opentelemetry.io/otel v1.45.0/go.mod h1:XZxIqPapzEYnhNSScF5DIqXhm/rYi0FzCe2XddAwZfQ= +go.opentelemetry.io/otel/metric v1.45.0 h1:7Eg1uH7CJ5cXv9is6tnBe1FI6rj1nwUdbFypRm3br/M= +go.opentelemetry.io/otel/metric v1.45.0/go.mod h1:HAPbm1nd3p1PmFH7v2dR+6BjXxw+Lq4a2+pndMAm08s= +go.opentelemetry.io/otel/sdk v1.45.0 h1:4VVSMgQ83dUgW2aoX5f6JgLvHwIvzcuLnF9lUdCSpCw= +go.opentelemetry.io/otel/sdk v1.45.0/go.mod h1:Sr40LgXV7DsKMMJMKOhUWOgMWTfAaqvm2kF0g7ilwuA= +go.opentelemetry.io/otel/sdk/metric v1.45.0 h1:oVFszMfyj1Am6s24Vtc7wBb8BKLcwepJjNEYILuiE3o= +go.opentelemetry.io/otel/sdk/metric v1.45.0/go.mod h1:vUWUxDZvu1WVRj8JA8S0AdhsPrZoDpA2DdZauIh4mDA= +go.opentelemetry.io/otel/trace v1.45.0 h1:l/mP6Uv7oNO7/TblbhpbgMidxhq1uO/rPsikOyVhxag= +go.opentelemetry.io/otel/trace v1.45.0/go.mod h1:qoJJA2xNMnxRrdISU/kLtfUH2wNeQbiv+jhs/CxI8bc= golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y= golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I= golang.org/x/mod v0.40.0 h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs= @@ -229,10 +229,10 @@ google.golang.org/api v0.271.0 h1:cIPN4qcUc61jlh7oXu6pwOQqbJW2GqYh5PS6rB2C/JY= google.golang.org/api v0.271.0/go.mod h1:CGT29bhwkbF+i11qkRUJb2KMKqcJ1hdFceEIRd9u64Q= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d h1:IL4hdHzcUv2l/gcg98/Rj3FbtE6axwqslOW8SW0C+S0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU= google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= diff --git a/internal/backend/remote-state/s3/go.mod b/internal/backend/remote-state/s3/go.mod index af1902246dd8..49a9acac4721 100644 --- a/internal/backend/remote-state/s3/go.mod +++ b/internal/backend/remote-state/s3/go.mod @@ -48,7 +48,7 @@ require ( github.com/cloudflare/circl v1.6.3 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/fatih/color v1.18.0 // indirect - github.com/go-logr/logr v1.4.3 // indirect + github.com/go-logr/logr v1.4.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/google/uuid v1.6.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect @@ -68,9 +68,9 @@ require ( github.com/zclconf/go-cty-yaml v1.1.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/instrumentation/github.com/aws/aws-sdk-go-v2/otelaws v0.67.0 // indirect - go.opentelemetry.io/otel v1.44.0 // indirect - go.opentelemetry.io/otel/metric v1.44.0 // indirect - go.opentelemetry.io/otel/trace v1.44.0 // indirect + go.opentelemetry.io/otel v1.45.0 // indirect + go.opentelemetry.io/otel/metric v1.45.0 // indirect + go.opentelemetry.io/otel/trace v1.45.0 // indirect golang.org/x/crypto v0.56.0 // indirect golang.org/x/mod v0.40.0 // indirect golang.org/x/net v0.58.0 // indirect diff --git a/internal/backend/remote-state/s3/go.sum b/internal/backend/remote-state/s3/go.sum index 823b2d8384c4..6cfa357fbfc3 100644 --- a/internal/backend/remote-state/s3/go.sum +++ b/internal/backend/remote-state/s3/go.sum @@ -108,8 +108,8 @@ github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw github.com/go-jose/go-jose/v4 v4.1.4 h1:moDMcTHmvE6Groj34emNPLs/qtYXRVcd6S7NHbHz3kA= github.com/go-jose/go-jose/v4 v4.1.4/go.mod h1:x4oUasVrzR7071A4TnHLGSPpNOm2a21K9Kf04k1rs08= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= -github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.4 h1:tG4xh9yMsRCAiodLVTxyrkzSZ9+o0L1Kg/+cPVcbP/8= +github.com/go-logr/logr v1.4.4/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= @@ -160,8 +160,8 @@ github.com/hashicorp/terraform-svchost v0.2.1 h1:ubvrTFw3Q7CsoEaX7V06PtCTKG3wu7G github.com/hashicorp/terraform-svchost v0.2.1/go.mod h1:zDMheBLvNzu7Q6o9TBvPqiZToJcSuCLXjAXxBslSky4= github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8= github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns= -github.com/klauspost/compress v1.18.7 h1:aUyZsS4kH3QTKurYhAOwAHxllVPnOthb3vPfnF1Ehjw= -github.com/klauspost/compress v1.18.7/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= +github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk= +github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= @@ -215,16 +215,16 @@ go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.6 go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.63.0/go.mod h1:fvPi2qXDqFs8M4B4fmJhE92TyQs9Ydjlg3RvfUp+NbQ= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q= -go.opentelemetry.io/otel v1.44.0 h1:JjwHmHpA4iZ3wBxluu2fbbE7j4kqlE8jXyAyPXH7HqU= -go.opentelemetry.io/otel v1.44.0/go.mod h1:BMgjTHL9WPRlRjL2oZCBTL4whCGtXch2H4BhOPIAyYc= -go.opentelemetry.io/otel/metric v1.44.0 h1:1w0gILTcHdr3YI+ixLyjemwrVnsMURbTZFrSYCdDdmc= -go.opentelemetry.io/otel/metric v1.44.0/go.mod h1:8O7hanEPBNgEMmybD3s2VBKcgWOCsA6tzHBPODAiquo= -go.opentelemetry.io/otel/sdk v1.44.0 h1:nHYwb9lK+fJPU/dnT6s7W7Z8itMWyqrnVfbheVYrZ58= -go.opentelemetry.io/otel/sdk v1.44.0/go.mod h1:Osuydd3Se74nqjAKxid74N5eC+jfEqfTegHRnq58oK0= -go.opentelemetry.io/otel/sdk/metric v1.44.0 h1:3LlKgI+VjbVsjNRFZJZAJ30WjXC5VkNRks6si09iEfI= -go.opentelemetry.io/otel/sdk/metric v1.44.0/go.mod h1:5B5pMARnXxKhltooO4xUuCBorl65a4EpnTalObqOigA= -go.opentelemetry.io/otel/trace v1.44.0 h1:jxF5CsGYCe74MCRx2X4g7WsY/VBKRqqpNvXlX/6gtIk= -go.opentelemetry.io/otel/trace v1.44.0/go.mod h1:oLl1jrMQAVo6v3GAggN+1VH9VIz9iUSvW53sW1Q8PIE= +go.opentelemetry.io/otel v1.45.0 h1:pdrWmLHofpubmArBv1LgFSv1Z0Ie/ppdZzu+kUN5EeU= +go.opentelemetry.io/otel v1.45.0/go.mod h1:XZxIqPapzEYnhNSScF5DIqXhm/rYi0FzCe2XddAwZfQ= +go.opentelemetry.io/otel/metric v1.45.0 h1:7Eg1uH7CJ5cXv9is6tnBe1FI6rj1nwUdbFypRm3br/M= +go.opentelemetry.io/otel/metric v1.45.0/go.mod h1:HAPbm1nd3p1PmFH7v2dR+6BjXxw+Lq4a2+pndMAm08s= +go.opentelemetry.io/otel/sdk v1.45.0 h1:4VVSMgQ83dUgW2aoX5f6JgLvHwIvzcuLnF9lUdCSpCw= +go.opentelemetry.io/otel/sdk v1.45.0/go.mod h1:Sr40LgXV7DsKMMJMKOhUWOgMWTfAaqvm2kF0g7ilwuA= +go.opentelemetry.io/otel/sdk/metric v1.45.0 h1:oVFszMfyj1Am6s24Vtc7wBb8BKLcwepJjNEYILuiE3o= +go.opentelemetry.io/otel/sdk/metric v1.45.0/go.mod h1:vUWUxDZvu1WVRj8JA8S0AdhsPrZoDpA2DdZauIh4mDA= +go.opentelemetry.io/otel/trace v1.45.0 h1:l/mP6Uv7oNO7/TblbhpbgMidxhq1uO/rPsikOyVhxag= +go.opentelemetry.io/otel/trace v1.45.0/go.mod h1:qoJJA2xNMnxRrdISU/kLtfUH2wNeQbiv+jhs/CxI8bc= golang.org/x/crypto v0.56.0 h1:GUh5Ii4J5jtcseSMiRqr1jXCNHoxjeV9Fmekc2oLy6Y= golang.org/x/crypto v0.56.0/go.mod h1:OMW5y6CY9l38uPLmxU6l6pwcXp1obtLo3e6gT7gQR2I= golang.org/x/mod v0.40.0 h1:hUv+3cXcdRHz08UmSiOob7sadHig73uo5bkXxQ/tvUs= @@ -254,10 +254,10 @@ google.golang.org/api v0.271.0 h1:cIPN4qcUc61jlh7oXu6pwOQqbJW2GqYh5PS6rB2C/JY= google.golang.org/api v0.271.0/go.mod h1:CGT29bhwkbF+i11qkRUJb2KMKqcJ1hdFceEIRd9u64Q= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409 h1:VQZ/yAbAtjkHgH80teYd2em3xtIkkHd7ZhqfH2N9CsM= google.golang.org/genproto v0.0.0-20260128011058-8636f8732409/go.mod h1:rxKD3IEILWEu3P44seeNOAwZN4SaoKaQ/2eTg4mM6EM= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:Kjn0N0tCrDgiAFW+lGO4JZ3ck44CehvJQMAwj9QF0G8= -google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk= -google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d h1:FarXi840EJWSHYTN3ERkADbPWjl307+FGrA22KAVjjc= +google.golang.org/genproto/googleapis/api v0.0.0-20260803160001-6ac0973c030d/go.mod h1:K/+WGbmBY7aNW1HDw1fJnKYo10i0DkAX6pows00dLig= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d h1:IL4hdHzcUv2l/gcg98/Rj3FbtE6axwqslOW8SW0C+S0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20260803160001-6ac0973c030d/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8= google.golang.org/grpc v1.83.2 h1:EManeRomTObA0BU7I8vXgg/78uE5MJ9M8B39EX2WscU= google.golang.org/grpc v1.83.2/go.mod h1:YPI1hK3kDked6iHvgX3tR0y+nX/qpMFKhPgFsokw1S8= google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= From 15e64218ec92dccc0830937d048f1551a7252d6c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 18 Sep 2026 14:44:37 -0400 Subject: [PATCH 23/33] Backport of Ensure policy paths point to a directory in a query. into v1.17 (#39251) * backport of commit ac4e6723d59331d195ff5a90a40921f0d9fb6329 * backport of commit b992d138e34423cc4a3eb2e578137b0f1b55b761 --------- Co-authored-by: Sebastian Rivera --- .changes/v1.17/BUG FIXES-20260917-091500.yaml | 5 + internal/command/policy.go | 59 ++++- internal/command/query.go | 5 +- internal/command/query_test.go | 221 +++++++++++++++++- 4 files changed, 287 insertions(+), 3 deletions(-) create mode 100644 .changes/v1.17/BUG FIXES-20260917-091500.yaml diff --git a/.changes/v1.17/BUG FIXES-20260917-091500.yaml b/.changes/v1.17/BUG FIXES-20260917-091500.yaml new file mode 100644 index 000000000000..343a0b7548d8 --- /dev/null +++ b/.changes/v1.17/BUG FIXES-20260917-091500.yaml @@ -0,0 +1,5 @@ +kind: BUG FIXES +body: 'query: `terraform query -policies` now rejects a path that is not a directory, instead of passing it on to the policy engine' +time: 2026-09-17T09:15:00.000000-04:00 +custom: + Issue: "39238" diff --git a/internal/command/policy.go b/internal/command/policy.go index 78eeb3f239a3..77bcec249d35 100644 --- a/internal/command/policy.go +++ b/internal/command/policy.go @@ -10,6 +10,10 @@ import ( "github.com/hashicorp/terraform/internal/tfdiags" ) +// validatePolicyPaths checks that each of the given policy paths refers to +// something that exists and is readable. Both files and directories are +// accepted here, which is the behavior expected by "terraform init", "plan", +// and "apply". func validatePolicyPaths(policyPaths []string) (diags tfdiags.Diagnostics) { for _, path := range policyPaths { if _, err := os.Stat(path); err != nil { @@ -22,12 +26,65 @@ func validatePolicyPaths(policyPaths []string) (diags tfdiags.Diagnostics) { continue } + diags = diags.Append(policyPathReadErrorDiagnostic(path, err)) + } + } + return diags +} + +// validatePolicySetDirs checks that each of the given policy paths refers to an +// existing directory. Commands whose -policies option is documented as taking a +// policy set directory use this instead of validatePolicyPaths, so that a path +// to a single file is rejected with an actionable diagnostic rather than being +// passed along to the policy engine. +// +// Symlinks are resolved before the check, so a symlink to a directory is +// accepted while a symlink to a file or a dangling symlink is not. +func validatePolicySetDirs(policyPaths []string) (diags tfdiags.Diagnostics) { + for _, path := range policyPaths { + // An empty value, such as from "-policies=", has no path to report + // back to the user, so it gets its own message. + if path == "" { + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Invalid policy path", + "The -policies option requires the path of a policy set directory, but was given an empty value.", + )) + continue + } + + info, err := os.Stat(path) + if err != nil { + if os.IsNotExist(err) { + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Invalid policy path", + fmt.Sprintf("Terraform cannot find the policy path at %s. The -policies option requires the path of an existing policy set directory.", path), + )) + continue + } + + diags = diags.Append(policyPathReadErrorDiagnostic(path, err)) + continue + } + + if !info.IsDir() { diags = diags.Append(tfdiags.Sourceless( tfdiags.Error, "Invalid policy path", - fmt.Sprintf("Terraform could not read the policy path at %s: %s.", path, err), + fmt.Sprintf("The policy path %s is not a directory. The -policies option requires the path of a policy set directory, not an individual policy file.", path), )) } } return diags } + +// policyPathReadErrorDiagnostic builds the diagnostic for a policy path that +// could not be inspected on disk for a reason other than it not existing. +func policyPathReadErrorDiagnostic(path string, err error) tfdiags.Diagnostic { + return tfdiags.Sourceless( + tfdiags.Error, + "Invalid policy path", + fmt.Sprintf("Terraform could not read the policy path at %s: %s.", path, err), + ) +} diff --git a/internal/command/query.go b/internal/command/query.go index dbef8ff6c42e..41214a538ca8 100644 --- a/internal/command/query.go +++ b/internal/command/query.go @@ -195,7 +195,10 @@ func (c *QueryCommand) configureQueryPolicyClient(be backendrun.OperationsBacken } func (c *QueryCommand) Validate(args *arguments.Query) (diags tfdiags.Diagnostics) { - return diags.Append(validatePolicyPaths(args.PolicyPaths)) + // The query command's -policies option takes policy set directories, so we + // reject anything that isn't a directory here rather than letting it reach + // the policy client. + return diags.Append(validatePolicySetDirs(args.PolicyPaths)) } func (c *QueryCommand) PrepareBackend(args *arguments.State, viewType arguments.ViewType) (backendrun.OperationsBackend, tfdiags.Diagnostics) { diff --git a/internal/command/query_test.go b/internal/command/query_test.go index 635c823524ae..4edf13b36bb7 100644 --- a/internal/command/query_test.go +++ b/internal/command/query_test.go @@ -312,11 +312,51 @@ func TestQueryCommand_Validate(t *testing.T) { t.Fatal(err) } + emptyDir := t.TempDir() + filePath := filepath.Join(td, "main.policy.hcl") missingPath := filepath.Join(t.TempDir(), "does-not-exist") + // Symlink support is not guaranteed on every platform we test on, so the + // symlink cases are only registered when we can actually create them. + linkRoot := t.TempDir() + dirLink := filepath.Join(linkRoot, "dir-link") + fileLink := filepath.Join(linkRoot, "file-link") + danglingLink := filepath.Join(linkRoot, "dangling-link") + symlinksSupported := true + for target, link := range map[string]string{ + td: dirLink, + filePath: fileLink, + missingPath: danglingLink, + } { + if err := os.Symlink(target, link); err != nil { + symlinksSupported = false + break + } + } + + notADirDiags := func(path string) tfdiags.Diagnostics { + return tfdiags.Diagnostics{ + tfdiags.Sourceless( + tfdiags.Error, + "Invalid policy path", + fmt.Sprintf("The policy path %s is not a directory. The -policies option requires the path of a policy set directory, not an individual policy file.", path), + ), + } + } + missingDiags := func(path string) tfdiags.Diagnostics { + return tfdiags.Diagnostics{ + tfdiags.Sourceless( + tfdiags.Error, + "Invalid policy path", + fmt.Sprintf("Terraform cannot find the policy path at %s. The -policies option requires the path of an existing policy set directory.", path), + ), + } + } + tests := []struct { name string policyPaths []string + symlinks bool wantDiags tfdiags.Diagnostics }{ { @@ -330,21 +370,69 @@ func TestQueryCommand_Validate(t *testing.T) { name: "multiple valid paths", policyPaths: []string{td, td2}, }, + { + // Whether a directory actually contains any policies is for the + // policy engine to decide, not for CLI path validation. + name: "empty directory", + policyPaths: []string{emptyDir}, + }, { name: "non-existent path", policyPaths: []string{missingPath}, + wantDiags: missingDiags(missingPath), + }, + { + name: "empty path", + policyPaths: []string{""}, wantDiags: tfdiags.Diagnostics{ tfdiags.Sourceless( tfdiags.Error, "Invalid policy path", - fmt.Sprintf("Terraform cannot find the policy path at %s. Please ensure the file or directory exists and the path is correct.", missingPath), + "The -policies option requires the path of a policy set directory, but was given an empty value.", ), }, }, + { + name: "regular file", + policyPaths: []string{filePath}, + wantDiags: notADirDiags(filePath), + }, + { + name: "valid directories mixed with a regular file", + policyPaths: []string{td, filePath, td2}, + wantDiags: notADirDiags(filePath), + }, + { + // Every supplied path is validated, so more than one of them can + // be reported at once. + name: "multiple invalid paths", + policyPaths: []string{td, filePath, missingPath}, + wantDiags: append(notADirDiags(filePath), missingDiags(missingPath)...), + }, + { + name: "symlink to a directory", + policyPaths: []string{dirLink}, + symlinks: true, + }, + { + name: "symlink to a file", + policyPaths: []string{fileLink}, + symlinks: true, + wantDiags: notADirDiags(fileLink), + }, + { + name: "dangling symlink", + policyPaths: []string{danglingLink}, + symlinks: true, + wantDiags: missingDiags(danglingLink), + }, } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { + if tc.symlinks && !symlinksSupported { + t.Skip("symlinks are not supported on this platform") + } cmd := &QueryCommand{} got := cmd.Validate(&arguments.Query{PolicyPaths: tc.policyPaths}) if tc.wantDiags == nil { @@ -354,6 +442,14 @@ func TestQueryCommand_Validate(t *testing.T) { tfdiags.AssertDiagnosticsMatch(t, got, tc.wantDiags) }) } + + // A relative path to an existing directory is valid too. + t.Run("relative directory path", func(t *testing.T) { + t.Chdir(filepath.Dir(td)) + cmd := &QueryCommand{} + got := cmd.Validate(&arguments.Query{PolicyPaths: []string{filepath.Base(td)}}) + tfdiags.AssertNoDiagnostics(t, got) + }) } type queryPolicyRemoteCommandBackend struct { @@ -837,6 +933,129 @@ func TestQueryPolicyStatusReporting_NoPoliciesArgument(t *testing.T) { } } +// TestQueryCommand_policyPathNotADirectory checks that pointing -policies at an +// existing regular file fails the command before it prepares a backend, starts +// a policy client, or runs the query, in both the human and JSON views. +func TestQueryCommand_policyPathNotADirectory(t *testing.T) { + for _, tc := range []struct { + name string + flag string + json bool + }{ + {name: "human, single dash", flag: "-policies"}, + {name: "json, double dash", flag: "--policies", json: true}, + } { + t.Run(tc.name, func(t *testing.T) { + td := t.TempDir() + testCopyDir(t, testFixturePath(path.Join("query", "basic")), td) + t.Chdir(td) + + policyFile := filepath.Join(td, "allow.tfpolicy.hcl") + if err := os.WriteFile(policyFile, []byte(""), 0644); err != nil { + t.Fatal(err) + } + + providerSource := newMockProviderSource(t, map[string][]string{ + "hashicorp/test": {"1.0.0"}, + }) + p := queryFixtureProvider() + + policyClient := policy.NewTestMockClient(t) + var policyClientUsed atomic.Bool + policyClient.EvaluateFn = func(context.Context, policy.EvaluationRequest[*proto.PolicyEvaluateResourceRequest_ResourceMetadata]) policy.EvaluationResponse { + policyClientUsed.Store(true) + return policy.EvaluationResponse{Overall: policy.AllowResult} + } + policyClient.StopFn = func() { + policyClientUsed.Store(true) + } + + overrides := metaOverridesForProvider(p) + overrides.PolicyClient = policyClient + view, done := testView(t) + meta := Meta{ + testingOverrides: overrides, + View: view, + ProviderSource: providerSource, + } + + init := &InitCommand{Meta: meta} + if code := init.Run(nil); code != 0 { + t.Fatalf("init failed with status %d:\n%s", code, done(t).All()) + } + + view, done = testView(t) + meta.View = view + command := &QueryCommand{Meta: meta} + + args := []string{"-no-color", tc.flag + "=" + policyFile} + if tc.json { + args = append(args, "-json") + } + code := command.Run(args) + output := done(t) + + if code != 1 { + t.Fatalf("query exited with status %d, want 1:\n%s", code, output.All()) + } + + wantDetail := fmt.Sprintf("The policy path %s is not a directory.", policyFile) + if tc.json { + var found bool + for _, line := range strings.Split(strings.TrimSpace(output.Stdout()), "\n") { + if line == "" { + continue + } + var record map[string]any + if err := json.Unmarshal([]byte(line), &record); err != nil { + t.Fatalf("failed to decode JSON line %q: %s", line, err) + } + if record["type"] == "list_resource_found" { + t.Fatalf("query produced results despite an invalid policy path:\n%s", output.Stdout()) + } + if record["type"] != "diagnostic" { + continue + } + diagnostic, ok := record["diagnostic"].(map[string]any) + if !ok { + t.Fatalf("diagnostic record has no diagnostic object: %s", line) + } + if diagnostic["severity"] != "error" || diagnostic["summary"] != "Invalid policy path" { + continue + } + detail, _ := diagnostic["detail"].(string) + if !strings.Contains(detail, wantDetail) { + t.Fatalf("diagnostic detail = %q, want it to contain %q", detail, wantDetail) + } + found = true + } + if !found { + t.Fatalf("no \"Invalid policy path\" diagnostic in JSON output:\n%s", output.All()) + } + } else { + // The human view wraps long lines, so we check the significant + // fragments rather than the whole sentence. + got := output.Stderr() + for _, want := range []string{"Invalid policy path", policyFile, "is not a directory"} { + if !strings.Contains(got, want) { + t.Fatalf("missing expected error message\nwant message containing %q\ngot:\n%s", want, got) + } + } + if got := output.Stdout(); strings.Contains(got, "list.test_instance") { + t.Fatalf("query produced results despite an invalid policy path:\n%s", got) + } + } + + if p.ListResourceCalled { + t.Fatal("query was executed despite an invalid policy path") + } + if policyClientUsed.Load() { + t.Fatal("policy client was started despite an invalid policy path") + } + }) + } +} + func TestQuery_JSON(t *testing.T) { tmp := t.TempDir() tests := []struct { From 1ce11b99fb3985fdd1a886397ad9d0cabb1ac2ad Mon Sep 17 00:00:00 2001 From: Daniel Banck Date: Mon, 21 Sep 2026 15:39:30 +0000 Subject: [PATCH 24/33] backport of commit 83a4fecc499485caad8c27533cbc154f761f10cb --- internal/configs/module.go | 36 ++-- internal/configs/module_merge_test.go | 198 ++++++++++++++++++ internal/configs/parser_config.go | 5 +- internal/configs/provider_requirements.go | 27 +-- .../configs/provider_requirements_test.go | 12 +- .../terraform/config_graph_module_test.go | 35 ++++ 6 files changed, 275 insertions(+), 38 deletions(-) diff --git a/internal/configs/module.go b/internal/configs/module.go index 330343c04930..d9d6f4f68ffd 100644 --- a/internal/configs/module.go +++ b/internal/configs/module.go @@ -88,13 +88,12 @@ type File struct { ActiveExperiments experiments.Set - Backends []*Backend - StateStores []*StateStore - CloudConfigs []*CloudConfig - ProviderConfigs []*Provider - ProviderMetas []*ProviderMeta - RequiredProviders []*RequiredProviders - RequiredProviderExprs []*ProviderRequirementExpr + Backends []*Backend + StateStores []*StateStore + CloudConfigs []*CloudConfig + ProviderConfigs []*Provider + ProviderMetas []*ProviderMeta + RequiredProviders []*RequiredProvidersBlock Variables []*Variable Locals []*Local @@ -163,10 +162,13 @@ func NewModule(primaryFiles, overrideFiles []*File) (*Module, hcl.Diagnostics) { }) continue } - mod.ProviderRequirements = r - } - for _, expr := range file.RequiredProviderExprs { - mod.ProviderRequirementExprs[expr.Name] = expr + mod.ProviderRequirements = &RequiredProviders{ + RequiredProviders: r.RequiredProviders, + DeclRange: r.DeclRange, + } + for name, expr := range r.RequiredProviderExprs { + mod.ProviderRequirementExprs[name] = expr + } } } @@ -179,18 +181,18 @@ func NewModule(primaryFiles, overrideFiles []*File) (*Module, hcl.Diagnostics) { } // Any required_providers blocks in override files replace the entire - // block for each provider. Process resolved and expression-based requirements - // in file order, removing superseded declarations from either representation. + // block for each provider. Process blocks in file and source order, removing + // superseded declarations from either representation before evaluation. for _, file := range overrideFiles { for _, override := range file.RequiredProviders { for name, rp := range override.RequiredProviders { delete(mod.ProviderRequirementExprs, name) mod.ProviderRequirements.RequiredProviders[name] = rp } - } - for _, expr := range file.RequiredProviderExprs { - delete(mod.ProviderRequirements.RequiredProviders, expr.Name) - mod.ProviderRequirementExprs[expr.Name] = expr + for name, expr := range override.RequiredProviderExprs { + delete(mod.ProviderRequirements.RequiredProviders, name) + mod.ProviderRequirementExprs[name] = expr + } } } diff --git a/internal/configs/module_merge_test.go b/internal/configs/module_merge_test.go index bee8557fb5ef..090110f5a0c8 100644 --- a/internal/configs/module_merge_test.go +++ b/internal/configs/module_merge_test.go @@ -5,6 +5,7 @@ package configs import ( "fmt" + "strings" "testing" "github.com/hashicorp/hcl/v2" @@ -161,6 +162,203 @@ terraform { } } +func TestModuleOverrideRequiredProvidersSameFile(t *testing.T) { + const ( + expression = `required_providers { random = { source = var.provider_source, version = var.provider_version, configuration_aliases = [random.old] } }` + laterExpression = `required_providers { random = { source = "other/random", version = "~> 4.0" } }` + legacy = `required_providers { random = "~> 2.0" }` + emptyObject = `required_providers { random = {} }` + aliasesOnly = `required_providers { random = { configuration_aliases = [random.next] } }` + emptyBlock = `required_providers {}` + ) + + tests := []struct { + name string + blocks []string + wantBlock int + }{ + { + name: "expression-based to legacy", + blocks: []string{expression, legacy}, + wantBlock: 1, + }, + { + name: "expression-based to empty object", + blocks: []string{expression, emptyObject}, + wantBlock: 1, + }, + { + name: "expression-based to aliases-only", + blocks: []string{expression, aliasesOnly}, + wantBlock: 1, + }, + { + name: "legacy to expression-based", + blocks: []string{legacy, laterExpression}, + wantBlock: 1, + }, + { + name: "empty object to expression-based", + blocks: []string{emptyObject, laterExpression}, + wantBlock: 1, + }, + { + name: "aliases-only to expression-based clears aliases", + blocks: []string{aliasesOnly, laterExpression}, + wantBlock: 1, + }, + { + name: "alternating declarations ending resolved", + blocks: []string{`required_providers { random = "~> 3.0" }`, expression, legacy}, + wantBlock: 2, + }, + { + name: "alternating declarations ending expression-based", + blocks: []string{expression, legacy, laterExpression}, + wantBlock: 2, + }, + { + name: "aliases-only to legacy clears aliases", + blocks: []string{aliasesOnly, legacy}, + wantBlock: 1, + }, + { + name: "aliases-only to empty object clears aliases", + blocks: []string{aliasesOnly, emptyObject}, + wantBlock: 1, + }, + { + name: "empty block retains expression-based requirement", + blocks: []string{expression, emptyBlock}, + wantBlock: 0, + }, + { + name: "empty block retains resolved requirement", + blocks: []string{legacy, emptyBlock}, + wantBlock: 0, + }, + { + name: "empty block between declarations", + blocks: []string{expression, emptyBlock, legacy}, + wantBlock: 2, + }, + } + + for layout, separator := range map[string]string{ + "one terraform block": "\n", + "separate terraform blocks": "\n}\nterraform {\n", + } { + t.Run(layout, func(t *testing.T) { + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + parser := testParser(map[string]string{ + "mod/override.tf": "terraform {\n" + strings.Join(tc.blocks, separator) + "\n}", + }) + override, diags := parser.LoadConfigFileOverride("mod/override.tf") + assertNoDiagnostics(t, diags) + + // The whole declaration must come from the winning block, + // including its aliases, expressions, and source ranges. + want := override.RequiredProviders[tc.wantBlock] + mod, diags := NewModule(nil, []*File{override}) + assertNoDiagnostics(t, diags) + + req, hasResolved := mod.ProviderRequirements.RequiredProviders["random"] + expr, hasExpr := mod.ProviderRequirementExprs["random"] + if hasResolved == hasExpr { + t.Fatalf("expected exactly one representation of the requirement: resolved=%t, expression-based=%t", hasResolved, hasExpr) + } + assertResultDeepEqual(t, req, want.RequiredProviders["random"]) + assertResultDeepEqual(t, expr, want.RequiredProviderExprs["random"]) + }) + } + }) + } +} + +func TestModuleOverrideRequiredProvidersSameFileRetainsUnrelated(t *testing.T) { + parser := testParser(map[string]string{ + "mod/main.tf": ` +terraform { + required_providers { + legacy = "~> 1.0" + expression = { source = "acme/expression" } + } +} +`, + "mod/override.tf": ` +terraform { + required_providers { + random = { source = "acme/random" } + retainedlegacy = "~> 1.0" + retainedexpression = { source = "acme/expression" } + } + required_providers { + random = "~> 2.0" + } +} +`, + }) + primary, diags := parser.LoadConfigFile("mod/main.tf") + assertNoDiagnostics(t, diags) + override, diags := parser.LoadConfigFileOverride("mod/override.tf") + assertNoDiagnostics(t, diags) + + wantResolved := map[string]*RequiredProvider{ + "legacy": primary.RequiredProviders[0].RequiredProviders["legacy"], + "retainedlegacy": override.RequiredProviders[0].RequiredProviders["retainedlegacy"], + "random": override.RequiredProviders[1].RequiredProviders["random"], + } + wantExprs := map[string]*ProviderRequirementExpr{ + "expression": primary.RequiredProviders[0].RequiredProviderExprs["expression"], + "retainedexpression": override.RequiredProviders[0].RequiredProviderExprs["retainedexpression"], + } + + mod, diags := NewModule([]*File{primary}, []*File{override}) + assertNoDiagnostics(t, diags) + assertResultDeepEqual(t, mod.ProviderRequirements.RequiredProviders, wantResolved) + assertResultDeepEqual(t, mod.ProviderRequirementExprs, wantExprs) +} + +func TestModuleRequiredProvidersDuplicateEmptyBlocks(t *testing.T) { + for name, tc := range map[string]struct { + first string + second string + }{ + "two empty blocks": {}, + "empty then legacy": { + second: ` random = "~> 2.0"`, + }, + "legacy then empty": { + first: ` random = "~> 2.0"`, + }, + "empty then expression-based": { + second: ` random = { source = "acme/random" }`, + }, + "expression-based then empty": { + first: ` random = { source = "acme/random" }`, + }, + } { + t.Run(name, func(t *testing.T) { + _, diags := testParser(map[string]string{ + "mod/main.tf": fmt.Sprintf(`terraform { + required_providers { +%s + } + required_providers { +%s + } +} +`, tc.first, tc.second), + }).LoadConfigDir("mod") + assertDiagnosticCount(t, diags, 1) + assertExactDiagnostics(t, diags, []string{ + "mod/main.tf:5,3-21: Duplicate required providers configuration; A module may have only one required providers configuration. The required providers were previously configured at mod/main.tf:2,3-21.", + }) + }) + } +} + func TestModuleOverrideModule(t *testing.T) { mod, diags := testModuleFromDir("testdata/valid-modules/override-module") assertNoDiagnostics(t, diags) diff --git a/internal/configs/parser_config.go b/internal/configs/parser_config.go index a1e30fdca8e4..fa69c7624cdd 100644 --- a/internal/configs/parser_config.go +++ b/internal/configs/parser_config.go @@ -156,14 +156,11 @@ func parseConfigFile(body hcl.Body, diags hcl.Diagnostics, override, allowExperi } case "required_providers": - reqs, reqExprs, reqsDiags := decodeRequiredProvidersBlock(innerBlock) + reqs, reqsDiags := decodeRequiredProvidersBlock(innerBlock) diags = append(diags, reqsDiags...) if reqs != nil { file.RequiredProviders = append(file.RequiredProviders, reqs) } - for _, expr := range reqExprs { - file.RequiredProviderExprs = append(file.RequiredProviderExprs, expr) - } case "provider_meta": providerCfg, cfgDiags := decodeProviderMetaBlock(innerBlock) diff --git a/internal/configs/provider_requirements.go b/internal/configs/provider_requirements.go index f35b5db71bfc..7fb3be9d84b4 100644 --- a/internal/configs/provider_requirements.go +++ b/internal/configs/provider_requirements.go @@ -29,21 +29,24 @@ type RequiredProviders struct { DeclRange hcl.Range } -func decodeRequiredProvidersBlock(block *hcl.Block) ( - *RequiredProviders, - map[string]*ProviderRequirementExpr, - hcl.Diagnostics, -) { +// RequiredProvidersBlock retains both resolved and deferred declarations from a +// single required_providers block so that overrides can be applied in block order. +type RequiredProvidersBlock struct { + RequiredProviders map[string]*RequiredProvider + RequiredProviderExprs map[string]*ProviderRequirementExpr + DeclRange hcl.Range +} + +func decodeRequiredProvidersBlock(block *hcl.Block) (*RequiredProvidersBlock, hcl.Diagnostics) { attrs, diags := block.Body.JustAttributes() if diags.HasErrors() { - return nil, nil, diags + return nil, diags } - ret := &RequiredProviders{ + ret := &RequiredProvidersBlock{ RequiredProviders: make(map[string]*RequiredProvider), DeclRange: block.DefRange, } - var deferredExprs map[string]*ProviderRequirementExpr for name, attr := range attrs { rp := &RequiredProvider{ @@ -196,10 +199,10 @@ func decodeRequiredProvidersBlock(block *hcl.Block) ( providerExpr.VersionExpr = versionExpr } - if deferredExprs == nil { - deferredExprs = map[string]*ProviderRequirementExpr{} + if ret.RequiredProviderExprs == nil { + ret.RequiredProviderExprs = map[string]*ProviderRequirementExpr{} } - deferredExprs[name] = providerExpr + ret.RequiredProviderExprs[name] = providerExpr // Skip adding it to required providers. continue @@ -224,5 +227,5 @@ func decodeRequiredProvidersBlock(block *hcl.Block) ( ret.RequiredProviders[rp.Name] = rp } - return ret, deferredExprs, diags + return ret, diags } diff --git a/internal/configs/provider_requirements_test.go b/internal/configs/provider_requirements_test.go index 6ca12a88b9bb..bcbffac848af 100644 --- a/internal/configs/provider_requirements_test.go +++ b/internal/configs/provider_requirements_test.go @@ -361,7 +361,7 @@ func TestDecodeRequiredProvidersBlock(t *testing.T) { for name, test := range tests { t.Run(name, func(t *testing.T) { - got, gotExprs, diags := decodeRequiredProvidersBlock(test.Block) + got, diags := decodeRequiredProvidersBlock(test.Block) if diags.HasErrors() { if test.Error == "" { t.Fatalf("unexpected error: %v", diags) @@ -373,11 +373,13 @@ func TestDecodeRequiredProvidersBlock(t *testing.T) { t.Fatalf("expected error") } - if !cmp.Equal(got, test.Want, ignoreUnexported, comparer) { - t.Fatalf("wrong result:\n %s", cmp.Diff(got, test.Want, ignoreUnexported, comparer)) + want := &RequiredProvidersBlock{ + RequiredProviders: test.Want.RequiredProviders, + RequiredProviderExprs: test.WantExprs, + DeclRange: test.Want.DeclRange, } - if !cmp.Equal(gotExprs, test.WantExprs, providerExprComparer) { - t.Fatalf("wrong expressions:\n %s", cmp.Diff(gotExprs, test.WantExprs, providerExprComparer)) + if diff := cmp.Diff(want, got, ignoreUnexported, comparer, providerExprComparer); diff != "" { + t.Fatalf("wrong result (-want +got):\n %s", diff) } }) } diff --git a/internal/terraform/config_graph_module_test.go b/internal/terraform/config_graph_module_test.go index bfa7107ce7f4..4a6a907ae7aa 100644 --- a/internal/terraform/config_graph_module_test.go +++ b/internal/terraform/config_graph_module_test.go @@ -478,6 +478,41 @@ func TestImpliedProviderForUnqualifiedType(t *testing.T) { } } +func TestModule_required_provider_override_discards_expression(t *testing.T) { + // These undeclared variables must not contribute graph dependencies or be + // evaluated, because the later declaration replaces the entire requirement. + cfg := testModuleInline(t, map[string]string{ + "main.tf": "", + "override.tf": ` +terraform { + required_providers { + test = { + source = var.undeclared_source + version = var.undeclared_version + } + } + required_providers { + test = "~> 2.0" + } +} +`, + }) + + req, exists := cfg.Module.ProviderRequirements.RequiredProviders["test"] + if !exists { + t.Fatal("no provider requirements found for \"test\"") + } + if req.Source != "" { + t.Errorf("wrong provider source: got %q, want no explicit source", req.Source) + } + if got := req.Requirement.Required.String(); got != "~> 2.0" { + t.Errorf("wrong provider version constraint: got %q, want %q", got, "~> 2.0") + } + if want := addrs.NewDefaultProvider("test"); !req.Type.Equals(want) { + t.Errorf("wrong provider addr: got %s, want %s", req.Type, want) + } +} + // testNestedModuleConfigFromDir reads configuration from the given directory path as // a module with (optional) submodules and returns its configuration. This is a // helper for use in unit tests. From f3543becd5d06a072409486d8d6bff2c88af3d63 Mon Sep 17 00:00:00 2001 From: Daniel Banck Date: Tue, 22 Sep 2026 16:13:19 +0000 Subject: [PATCH 25/33] backport of commit 00e6065945950a526bb50b58c3a6697e69a39c9a --- internal/configs/config_build.go | 1 + internal/configs/provider_meta.go | 39 +++++++++++++++- internal/terraform/config_graph_build.go | 1 + .../terraform/config_graph_module_test.go | 46 +++++++++++++++++++ 4 files changed, 86 insertions(+), 1 deletion(-) diff --git a/internal/configs/config_build.go b/internal/configs/config_build.go index ebd4ac421738..ba1a6cf74f5a 100644 --- a/internal/configs/config_build.go +++ b/internal/configs/config_build.go @@ -24,6 +24,7 @@ func FinalizeConfig(cfg *Config, loader MockDataLoader) hcl.Diagnostics { // the known types for validation. providers := cfg.ResolveProviderTypes() cfg.ResolveProviderTypesForTests(providers) + diags = append(diags, cfg.ValidateProviderMetas()...) if cfg.Module != nil && cfg.Module.StateStore != nil { stateProviderDiags := cfg.ResolveStateStoreProviderType() diff --git a/internal/configs/provider_meta.go b/internal/configs/provider_meta.go index 522c76ea7bde..4addacde1e66 100644 --- a/internal/configs/provider_meta.go +++ b/internal/configs/provider_meta.go @@ -3,7 +3,12 @@ package configs -import "github.com/hashicorp/hcl/v2" +import ( + "fmt" + + "github.com/hashicorp/hcl/v2" + "github.com/hashicorp/terraform/internal/addrs" +) // ProviderMeta represents a "provider_meta" block inside a "terraform" block // in a module or file. @@ -15,6 +20,38 @@ type ProviderMeta struct { DeclRange hcl.Range } +// ValidateProviderMetas checks for metadata declarations with distinct local +// names that resolve to the same provider, including in child and alternate test +// modules. Provider requirements must already have been evaluated. +func (c *Config) ValidateProviderMetas() hcl.Diagnostics { + var diags hcl.Diagnostics + c.DeepEach(func(cfg *Config) { + metas := make(map[addrs.Provider]*ProviderMeta) + for _, pm := range cfg.Module.ProviderMetaConfigs { + provider := cfg.Module.ProviderForLocalConfig(addrs.LocalProviderConfig{LocalName: pm.Provider}) + // Duplicate local names are already diagnosed during module construction. + if existing, exists := metas[provider]; exists && existing.Provider != pm.Provider { + diags = append(diags, &hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: "Duplicate provider_meta block", + Detail: fmt.Sprintf("A provider_meta block for provider %q was already declared at %s. Providers may only have one provider_meta block per module.", existing.Provider, existing.DeclRange), + Subject: &pm.DeclRange, + }) + } + metas[provider] = pm + } + + for _, file := range cfg.Module.Tests { + for _, run := range file.Runs { + if run.ConfigUnderTest != nil { + diags = append(diags, run.ConfigUnderTest.ValidateProviderMetas()...) + } + } + } + }) + return diags +} + func decodeProviderMetaBlock(block *hcl.Block) (*ProviderMeta, hcl.Diagnostics) { // provider_meta must be a static map. We can verify this by attempting to // evaluate the values. diff --git a/internal/terraform/config_graph_build.go b/internal/terraform/config_graph_build.go index 9050ad34c465..33897e2382ce 100644 --- a/internal/terraform/config_graph_build.go +++ b/internal/terraform/config_graph_build.go @@ -133,6 +133,7 @@ func BuildModuleWithGraph(mod *configs.Module, vars InputValues) (*configs.Modul providers := cfg.ResolveProviderTypes() cfg.ResolveProviderTypesForTests(providers) + diags = diags.Append(cfg.ValidateProviderMetas()) if cfg.Module != nil && cfg.Module.StateStore != nil { stateProviderDiags := cfg.ResolveStateStoreProviderType() diags = diags.Append(stateProviderDiags) diff --git a/internal/terraform/config_graph_module_test.go b/internal/terraform/config_graph_module_test.go index 4a6a907ae7aa..729d422ea4ca 100644 --- a/internal/terraform/config_graph_module_test.go +++ b/internal/terraform/config_graph_module_test.go @@ -229,6 +229,52 @@ func TestProviderForLocalConfig(t *testing.T) { } } +func TestModule_provider_meta_duplicate_provider(t *testing.T) { + for name, source := range map[string]string{ + "literal source": `"acme/test"`, + "const variable source": `var.provider_source`, + } { + t.Run(name, func(t *testing.T) { + _, diags := testModuleInlineWithVarsReturnDiags(t, map[string]string{ + "main.tf": fmt.Sprintf(` +variable "provider_source" { + type = string + const = true + default = "acme/test" +} + +terraform { + required_providers { + first = { + source = "acme/test" + } + second = { + source = %s + } + } + + provider_meta "first" { + value = "first" + } + provider_meta "second" { + value = "second" + } +} +`, source), + }, nil) + + // Different local names must not allow multiple metadata blocks for + // the same resolved provider. A duplicate-requirement warning is not enough. + for _, diag := range diags.ToHCL() { + if diag.Severity == hcl.DiagError && diag.Summary == "Duplicate provider_meta block" { + return + } + } + t.Fatalf("expected Duplicate provider_meta block error, got: %v", diags.Err()) + }) + } +} + // At most one required_providers block per module is permitted. func TestModule_required_providers_multiple(t *testing.T) { _, diags := testModuleFromDirWithInitGraph("testdata/config-graph/invalid-modules/multiple-required-providers") From 8997b8c7e9cd81aabef24ff5acd77e3837d3f386 Mon Sep 17 00:00:00 2001 From: hc-github-team-tf-core Date: Wed, 23 Sep 2026 14:51:45 +0000 Subject: [PATCH 26/33] Prepare before 1.17.0-beta2 release --- CHANGELOG.md | 17 ++++------------- version/VERSION | 2 +- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0d72ba56c09..977740d450b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.17.0 (Unreleased) +## 1.17.0-beta2 (September 23, 2026) NEW FEATURES: @@ -7,7 +7,7 @@ NEW FEATURES: * A new `-minimal-refresh` planning option has been added, which will only refresh resources that have proposed changes. ([#35290](https://github.com/hashicorp/terraform/issues/35290)) -* policy: Terraform Policy is now generally available. The `-policies` flag for `plan`, `apply`, and `init` no longer requires the `-allow-experimental-features` flag. See https://developer.hashicorp.com/terraform/policy for more information. ([#38970](https://github.com/hashicorp/terraform/issues/38970)) +* policy: Terraform Policy is now generally available. The `-policies` flag for `plan`, `apply`, and `query` no longer requires an experimental build or the `-allow-experimental-features` flag. Query policies evaluate resources discovered by list blocks and report human-readable or JSON results. See https://developer.hashicorp.com/terraform/policy for more information. ([#38970](https://github.com/hashicorp/terraform/issues/38970)) ENHANCEMENTS: @@ -29,23 +29,14 @@ BUG FIXES: * query: report Unknown and N/A results for policy evaluations of discovered resources ([#39058](https://github.com/hashicorp/terraform/issues/39058)) +* query: `terraform query -policies` now rejects a path that is not a directory, instead of passing it on to the policy engine ([#39238](https://github.com/hashicorp/terraform/issues/39238)) + NOTES: * version: JSON output now includes a new `format_version` field, which will enable safer future changes of the command's JSON output format. It is assumed existing tooling ignores unknown fields and therefore this change should not be breaking in itself but we advice consumers to pay attention to `format_version` in future releases and/or use latest version of hashicorp/terraform-json & hashicorp/terraform-exec which does. ([#38930](https://github.com/hashicorp/terraform/issues/38930)) -EXPERIMENTS: - -Experiments are only enabled in alpha releases of Terraform CLI. The following features are not yet available in stable releases. - -- The experimental "deferred actions" feature, enabled by passing the `-allow-deferral` option to `terraform plan`, permits `count` and `for_each` arguments in `module`, `resource`, and `data` blocks to have unknown values and allows providers to react more flexibly to unknown values. -- `terraform test cleanup`: The experimental `test cleanup` command. In experimental builds of Terraform, a manifest file and state files for each failed cleanup operation during test operations are saved within the `.terraform` local directory. The `test cleanup` command will attempt to clean up the local state files left behind automatically, without requiring manual intervention. -- `terraform test`: `backend` blocks and `skip_cleanup` attributes: - - Test authors can now specify `backend` blocks within `run` blocks in Terraform Test files. Run blocks with `backend` blocks will load state from the specified backend instead of starting from empty state on every execution. This allows test authors to keep long-running test infrastructure alive between test operations, saving time during regular test operations. - - Test authors can now specify `skip_cleanup` attributes within test files and within run blocks. The `skip_cleanup` attribute tells `terraform test` not to clean up state files produced by run blocks with this attribute set to true. The state files for affected run blocks will be written to disk within the `.terraform` directory, where they can then be cleaned up manually using the also experimental `terraform test cleanup` command. -- `terraform query`: The experimental `-policies` flag permits specifying one or more policy set directory paths to evaluate policies against resources discovered by list blocks during a query operation. - ## Previous Releases For information on prior major and minor releases, refer to their changelogs: diff --git a/version/VERSION b/version/VERSION index ee8855caa4a7..d12e82c01550 100644 --- a/version/VERSION +++ b/version/VERSION @@ -1 +1 @@ -1.17.0-dev +1.17.0-beta2 From 4e328403e5f5c3553ad5e8661547b21252a3a49a Mon Sep 17 00:00:00 2001 From: hc-github-team-tf-core Date: Wed, 23 Sep 2026 16:00:49 +0000 Subject: [PATCH 27/33] Cleanup after 1.17.0-beta2 release --- CHANGELOG.md | 12 +++++++++++- version/VERSION | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 977740d450b2..59144acc1fb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.17.0-beta2 (September 23, 2026) +## 1.17.0 (Unreleased) NEW FEATURES: @@ -37,6 +37,16 @@ NOTES: * version: JSON output now includes a new `format_version` field, which will enable safer future changes of the command's JSON output format. It is assumed existing tooling ignores unknown fields and therefore this change should not be breaking in itself but we advice consumers to pay attention to `format_version` in future releases and/or use latest version of hashicorp/terraform-json & hashicorp/terraform-exec which does. ([#38930](https://github.com/hashicorp/terraform/issues/38930)) +EXPERIMENTS: + +Experiments are only enabled in alpha releases of Terraform CLI. The following features are not yet available in stable releases. + +- The experimental "deferred actions" feature, enabled by passing the `-allow-deferral` option to `terraform plan`, permits `count` and `for_each` arguments in `module`, `resource`, and `data` blocks to have unknown values and allows providers to react more flexibly to unknown values. +- `terraform test cleanup`: The experimental `test cleanup` command. In experimental builds of Terraform, a manifest file and state files for each failed cleanup operation during test operations are saved within the `.terraform` local directory. The `test cleanup` command will attempt to clean up the local state files left behind automatically, without requiring manual intervention. +- `terraform test`: `backend` blocks and `skip_cleanup` attributes: + - Test authors can now specify `backend` blocks within `run` blocks in Terraform Test files. Run blocks with `backend` blocks will load state from the specified backend instead of starting from empty state on every execution. This allows test authors to keep long-running test infrastructure alive between test operations, saving time during regular test operations. + - Test authors can now specify `skip_cleanup` attributes within test files and within run blocks. The `skip_cleanup` attribute tells `terraform test` not to clean up state files produced by run blocks with this attribute set to true. The state files for affected run blocks will be written to disk within the `.terraform` directory, where they can then be cleaned up manually using the also experimental `terraform test cleanup` command. + ## Previous Releases For information on prior major and minor releases, refer to their changelogs: diff --git a/version/VERSION b/version/VERSION index d12e82c01550..ee8855caa4a7 100644 --- a/version/VERSION +++ b/version/VERSION @@ -1 +1 @@ -1.17.0-beta2 +1.17.0-dev From dc6b9bbc3000361cffda558289f5a74225323a0c Mon Sep 17 00:00:00 2001 From: James Bardin Date: Thu, 24 Sep 2026 20:08:38 +0000 Subject: [PATCH 28/33] backport of commit b70fabb11d7f5087b7614a5d197413a0ec47d73f --- internal/terraform/context_apply2_test.go | 147 ++++++++++++++++++ .../node_resource_abstract_instance.go | 36 ++--- .../terraform/node_resource_apply_instance.go | 18 ++- 3 files changed, 175 insertions(+), 26 deletions(-) diff --git a/internal/terraform/context_apply2_test.go b/internal/terraform/context_apply2_test.go index 5925f3793aec..5f17d7c7e512 100644 --- a/internal/terraform/context_apply2_test.go +++ b/internal/terraform/context_apply2_test.go @@ -30,7 +30,9 @@ import ( "github.com/hashicorp/terraform/internal/plans" "github.com/hashicorp/terraform/internal/providers" testing_provider "github.com/hashicorp/terraform/internal/providers/testing" + "github.com/hashicorp/terraform/internal/provisioners" "github.com/hashicorp/terraform/internal/states" + "github.com/hashicorp/terraform/internal/states/statefile" "github.com/hashicorp/terraform/internal/tfdiags" ) @@ -5666,3 +5668,148 @@ resource "test_object" "forget" { t.Fatal("should be no deposed instances") } } + +// A create that fails with a partial state must never be visible in the +// working state with an invalid status, because concurrent nodes may be +// persisting state snapshots at any time. +func TestContext2Apply_failedCreateStatusVisibleToConcurrentStateUpdate(t *testing.T) { + m := testModuleInline(t, map[string]string{ + "main.tf": ` +resource "test_object" "a" { + test_string = "a" + provisioner "shell" {} +} + +resource "test_object" "b" { + test_string = "b" +} +`, + }) + + // b is held until a is either provisioning or complete + releaseB := make(chan struct{}) + var releaseOnce sync.Once + release := func() { releaseOnce.Do(func() { close(releaseB) }) } + bPersisted := make(chan struct{}) + + p := simpleMockProvider() + p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) (resp providers.ApplyResourceChangeResponse) { + resp.NewState = req.PlannedState + if req.PlannedState.GetAttr("test_string").AsString() == "a" { + resp.Diagnostics = resp.Diagnostics.Append(errors.New("create failed")) + } + return resp + } + + pr := testProvisioner() + pr.ProvisionResourceFn = func(req provisioners.ProvisionResourceRequest) (resp provisioners.ProvisionResourceResponse) { + release() + select { + case <-bPersisted: + case <-time.After(5 * time.Second): + panic("timeout") + } + return resp + } + + hook := &stateSerializingTestHook{ + onPreApply: func(addr addrs.AbsResourceInstance) { + if addr.Equal(mustResourceInstanceAddr("test_object.b")) { + select { + case <-releaseB: + case <-time.After(5 * time.Second): + panic("timeout") + } + } + }, + onPostApply: func(addr addrs.AbsResourceInstance) { + if addr.Equal(mustResourceInstanceAddr("test_object.a")) { + release() + } + }, + onUpdate: func(s *states.State) { + if s.ResourceInstance(mustResourceInstanceAddr("test_object.b")) != nil { + select { + case <-bPersisted: + default: + close(bPersisted) + } + } + }, + } + + ctx := testContext2(t, &ContextOpts{ + Hooks: []Hook{hook}, + Providers: map[addrs.Provider]providers.Factory{ + addrs.NewDefaultProvider("test"): testProviderFuncFixed(p), + }, + Provisioners: map[string]provisioners.Factory{ + "shell": testProvisionerFuncFixed(pr), + }, + }) + + plan, diags := ctx.Plan(m, states.NewState(), DefaultPlanOpts) + tfdiags.AssertNoErrors(t, diags) + + state, diags := ctx.Apply(plan, m, nil) + if !diags.HasErrors() { + t.Fatal("expected apply error") + } + + for _, err := range hook.errs() { + t.Errorf("state snapshot could not be serialized: %s", err) + } + + if pr.ProvisionResourceCalled { + t.Error("provisioner should not run for a failed create") + } + + a := state.ResourceInstance(mustResourceInstanceAddr("test_object.a")) + if a == nil || a.Current == nil || a.Current.Status != states.ObjectTainted { + t.Fatalf("expected test_object.a to be tainted, got %#v", a) + } +} + +// stateSerializingTestHook serializes every state snapshot, as the local backend's +// StateHook does via statemgr.Filesystem. +type stateSerializingTestHook struct { + NilHook + + mu sync.Mutex + serErrs []error + onPreApply func(addrs.AbsResourceInstance) + onPostApply func(addrs.AbsResourceInstance) + onUpdate func(*states.State) +} + +func (h *stateSerializingTestHook) PostApply(id HookResourceIdentity, dk addrs.DeposedKey, newState cty.Value, err error) (HookAction, error) { + if h.onPostApply != nil { + h.onPostApply(id.Addr) + } + return HookActionContinue, nil +} + +func (h *stateSerializingTestHook) PreApply(id HookResourceIdentity, dk addrs.DeposedKey, action plans.Action, priorState, plannedNewState cty.Value) (HookAction, error) { + if h.onPreApply != nil { + h.onPreApply(id.Addr) + } + return HookActionContinue, nil +} + +func (h *stateSerializingTestHook) PostStateUpdate(s *states.State) (HookAction, error) { + h.mu.Lock() + defer h.mu.Unlock() + if err := statefile.Write(&statefile.File{State: s}, &bytes.Buffer{}); err != nil { + h.serErrs = append(h.serErrs, err) + } + if h.onUpdate != nil { + h.onUpdate(s) + } + return HookActionContinue, nil +} + +func (h *stateSerializingTestHook) errs() []error { + h.mu.Lock() + defer h.mu.Unlock() + return h.serErrs +} diff --git a/internal/terraform/node_resource_abstract_instance.go b/internal/terraform/node_resource_abstract_instance.go index cc140a143874..78c60f0e9897 100644 --- a/internal/terraform/node_resource_abstract_instance.go +++ b/internal/terraform/node_resource_abstract_instance.go @@ -2603,15 +2603,15 @@ func (n *NodeAbstractResourceInstance) evalDestroyProvisionerConfig(ctx EvalCont // nil, since it is only used to evaluate the configuration. func (n *NodeAbstractResourceInstance) apply( ctx EvalContext, - state *states.ResourceInstanceObject, + priorState *states.ResourceInstanceObject, change *plans.ResourceInstanceChange, applyConfig *configs.Resource, keyData instances.RepetitionData, createBeforeDestroy bool) (*states.ResourceInstanceObject, tfdiags.Diagnostics) { var diags tfdiags.Diagnostics - if state == nil { - state = &states.ResourceInstanceObject{} + if priorState == nil { + priorState = &states.ResourceInstanceObject{} } if change.Action == plans.NoOp { @@ -2619,18 +2619,18 @@ func (n *NodeAbstractResourceInstance) apply( // anything, so we'll just echo back the state we were given and // let our internal checks and updates proceed. log.Printf("[TRACE] NodeAbstractResourceInstance.apply: skipping %s because it has no planned action", n.Addr) - return state, diags + return priorState, diags } provider, providerSchema, err := getProvider(ctx, n.ResolvedProvider) if err != nil { - return state, diags.Append(err) + return priorState, diags.Append(err) } schema := providerSchema.SchemaForResourceType(n.Addr.Resource.Resource.Mode, n.Addr.Resource.Resource.Type) if schema.Body == nil { // Should be caught during validation, so we don't bother with a pretty error here diags = diags.Append(fmt.Errorf("provider does not support resource type %q", n.Addr.Resource.Resource.Type)) - return state, diags + return priorState, diags } log.Printf("[INFO] Starting apply for %s", n.Addr) @@ -2641,7 +2641,7 @@ func (n *NodeAbstractResourceInstance) apply( configVal, _, configDiags = ctx.EvaluateBlock(applyConfig.Config, schema.Body, nil, keyData) diags = diags.Append(configDiags) if configDiags.HasErrors() { - return state, diags + return priorState, diags } } @@ -2666,13 +2666,13 @@ func (n *NodeAbstractResourceInstance) apply( strings.Join(unknownPaths, "\n"), ), )) - return state, diags + return priorState, diags } metaConfigVal, metaDiags := n.Provider().getProviderMeta(ctx, n.Addr.Resource, n.ProviderMetas) diags = diags.Append(metaDiags) if diags.HasErrors() { - return state, diags + return priorState, diags } log.Printf("[DEBUG] %s: applying the planned %s change", n.Addr, change.Action) @@ -2694,10 +2694,10 @@ func (n *NodeAbstractResourceInstance) apply( if change.Action == plans.Update && eq && !marks.MarksEqual(beforePaths, afterPaths) { // Copy the previous state, changing only the value newState := &states.ResourceInstanceObject{ - CreateBeforeDestroy: state.CreateBeforeDestroy, - Dependencies: state.Dependencies, - Private: state.Private, - Status: state.Status, + CreateBeforeDestroy: priorState.CreateBeforeDestroy, + Dependencies: priorState.Dependencies, + Private: priorState.Private, + Status: states.ObjectReady, Value: change.After, Identity: change.AfterIdentity, } @@ -2795,7 +2795,7 @@ func (n *NodeAbstractResourceInstance) apply( // Bail early in this particular case, because an object that doesn't // conform to the schema can't be saved in the state anyway -- the // serializer will reject it. - return state, diags + return priorState, diags } // Providers are supposed to return null values for all write-only attributes @@ -2813,7 +2813,7 @@ func (n *NodeAbstractResourceInstance) apply( diags = diags.Append(writeOnlyDiags) if writeOnlyDiags.HasErrors() { - return state, diags + return priorState, diags } // After this point we have a type-conforming result object and so we @@ -2948,12 +2948,12 @@ func (n *NodeAbstractResourceInstance) apply( // prior state as the new value, making this effectively a no-op. If // the item really _has_ been deleted then our next refresh will detect // that and fix it up. - return state.DeepCopy(), diags + return priorState.DeepCopy(), diags case diags.HasErrors() && !newVal.IsNull(): // if we have an error, make sure we restore the object status in the new state newState := &states.ResourceInstanceObject{ - Status: state.Status, + Status: priorState.Status, Value: newVal, Private: resp.Private, CreateBeforeDestroy: createBeforeDestroy, @@ -2963,7 +2963,7 @@ func (n *NodeAbstractResourceInstance) apply( // if the resource was being deleted, the dependencies are not going to // be recalculated and we need to restore those as well. if change.Action == plans.Delete { - newState.Dependencies = state.Dependencies + newState.Dependencies = priorState.Dependencies } return newState, diags diff --git a/internal/terraform/node_resource_apply_instance.go b/internal/terraform/node_resource_apply_instance.go index f5e2f4830142..ae8a1ef7f241 100644 --- a/internal/terraform/node_resource_apply_instance.go +++ b/internal/terraform/node_resource_apply_instance.go @@ -290,7 +290,7 @@ func (n *NodeApplyableResourceInstance) managedResourceExecute(ctx EvalContext) diags = diags.Append(applyDiags) if diags.HasErrors() { // apply errors might need to taint the state - if err := n.taintInstanceState(ctx, state, diffApply.Action); err != nil { + if state, err = n.taintInstanceState(ctx, state, diffApply.Action); err != nil { return diags.Append(err) } } else { @@ -323,7 +323,7 @@ func (n *NodeApplyableResourceInstance) managedResourceExecute(ctx EvalContext) diags = diags.Append(applyProvisionersDiags) // provisioners always tainted on error if diags.HasErrors() { - if err := n.taintInstanceState(ctx, state, diffApply.Action); err != nil { + if state, err = n.taintInstanceState(ctx, state, diffApply.Action); err != nil { // we always return immediately if we can't update state return diags.Append(err) } @@ -334,7 +334,7 @@ func (n *NodeApplyableResourceInstance) managedResourceExecute(ctx EvalContext) taintInstance, actionDiags := n.invokeActions(ctx, repData, configs.AfterEvents, state.Value) diags = diags.Append(actionDiags) if taintInstance { - if err := n.taintInstanceState(ctx, state, diffApply.Action); err != nil { + if state, err = n.taintInstanceState(ctx, state, diffApply.Action); err != nil { // we always return immediately if we can't update state return diags.Append(err) } @@ -469,18 +469,20 @@ func (n *NodeApplyableResourceInstance) checkPlannedChange(ctx EvalContext, plan // taintInstanceState takes the state object error from an apply operation and // writes the instance object to the global stated marked as tainted, but only -// if the instance was being created. +// if the instance was being created. The returned object is what was written, +// and must replace the caller's object so that later writes of it do not +// revert the tainted status. // // TODO: Tainted was invented for failed create events, and provisioners which // could only be associated with those create events. If actions ever need to be // rerun for other event types, something more specific than `Tainted` needs to // be added to the resource state. -func (n *NodeApplyableResourceInstance) taintInstanceState(ctx EvalContext, state *states.ResourceInstanceObject, action plans.Action) error { +func (n *NodeApplyableResourceInstance) taintInstanceState(ctx EvalContext, state *states.ResourceInstanceObject, action plans.Action) (*states.ResourceInstanceObject, error) { if action != plans.Create { - return nil + return state, nil } log.Printf("[TRACE] taintState: %s encountered an error during creation, so it is now marked as tainted", n.Addr) - return n.writeResourceInstanceState(ctx, state.AsTainted(), workingState) - + tainted := state.AsTainted() + return tainted, n.writeResourceInstanceState(ctx, tainted, workingState) } From 3755d8c208e5f50c7f11203bff4ce9dc40dc1379 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Fri, 25 Sep 2026 13:26:38 +0000 Subject: [PATCH 29/33] backport of commit d055cd793eacd810b37ca2932fcd68f7b981723f --- .changes/v1.16/BUG FIXES-20260925-091845.yaml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changes/v1.16/BUG FIXES-20260925-091845.yaml diff --git a/.changes/v1.16/BUG FIXES-20260925-091845.yaml b/.changes/v1.16/BUG FIXES-20260925-091845.yaml new file mode 100644 index 000000000000..99a25c3c7377 --- /dev/null +++ b/.changes/v1.16/BUG FIXES-20260925-091845.yaml @@ -0,0 +1,5 @@ +kind: BUG FIXES +body: FIx crash when tainted instance state is seen without a valid status +time: 2026-09-25T09:18:45.683653-04:00 +custom: + Issue: "39287" From b14608df94359e679e80ba8d2afbd3a4f7dc6d82 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 25 Sep 2026 13:38:27 -0400 Subject: [PATCH 30/33] backport of commit 58c471d9d4c4dadca893f14cbf8da589bf28880c (#39296) Co-authored-by: Kristin Laemmert --- .changes/v1.16/BUG FIXES-20260925-123349.yaml | 5 ++ .../terraform/context_apply_identity_test.go | 46 ++++++++++++++++--- .../node_resource_abstract_instance.go | 6 ++- 3 files changed, 49 insertions(+), 8 deletions(-) create mode 100644 .changes/v1.16/BUG FIXES-20260925-123349.yaml diff --git a/.changes/v1.16/BUG FIXES-20260925-123349.yaml b/.changes/v1.16/BUG FIXES-20260925-123349.yaml new file mode 100644 index 000000000000..1324eddb7c7e --- /dev/null +++ b/.changes/v1.16/BUG FIXES-20260925-123349.yaml @@ -0,0 +1,5 @@ +kind: BUG FIXES +body: 'resource-identity: fixed an issue where resource identity could be nil during delete' +time: 2026-09-25T12:33:49.337193-04:00 +custom: + Issue: "39285" diff --git a/internal/terraform/context_apply_identity_test.go b/internal/terraform/context_apply_identity_test.go index de59c478486b..2e8f4fa6c92a 100644 --- a/internal/terraform/context_apply_identity_test.go +++ b/internal/terraform/context_apply_identity_test.go @@ -24,8 +24,9 @@ func TestContext2Apply_identity(t *testing.T) { plannedIdentity cty.Value appliedIdentity cty.Value - expectedIdentity cty.Value - expectDiagnostics tfdiags.Diagnostics + expectedIdentity cty.Value + expectedDeleteIdentity cty.Value + expectDiagnostics tfdiags.Diagnostics }{ "create": { plannedIdentity: cty.ObjectVal(map[string]cty.Value{ @@ -94,7 +95,12 @@ func TestContext2Apply_identity(t *testing.T) { }, ) }), - plannedIdentity: cty.NilVal, + plannedIdentity: cty.ObjectVal(map[string]cty.Value{ + "id": cty.StringVal("planned-delete"), + }), + expectedDeleteIdentity: cty.ObjectVal(map[string]cty.Value{ + "id": cty.StringVal("planned-delete"), + }), expectedIdentity: cty.NullVal(cty.Object(map[string]cty.Type{ "id": cty.String, })), @@ -123,6 +129,9 @@ func TestContext2Apply_identity(t *testing.T) { plannedIdentity: cty.ObjectVal(map[string]cty.Value{ "id": cty.StringVal("bar"), }), + expectedDeleteIdentity: cty.ObjectVal(map[string]cty.Value{ + "id": cty.StringVal("foo"), + }), expectedIdentity: cty.ObjectVal(map[string]cty.Value{ "id": cty.StringVal("bar"), }), @@ -178,11 +187,17 @@ func TestContext2Apply_identity(t *testing.T) { } } - if !tc.appliedIdentity.IsNull() { + var applyRequests []providers.ApplyResourceChangeRequest + if tc.appliedIdentity != cty.NilVal || tc.expectedDeleteIdentity != cty.NilVal { p.ApplyResourceChangeFn = func(req providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse { - resp := providers.ApplyResourceChangeResponse{} - resp.NewState = req.PlannedState - resp.NewIdentity = tc.appliedIdentity + applyRequests = append(applyRequests, req) + resp := providers.ApplyResourceChangeResponse{ + NewState: req.PlannedState, + NewIdentity: req.PlannedIdentity, + } + if tc.appliedIdentity != cty.NilVal { + resp.NewIdentity = tc.appliedIdentity + } return resp } } @@ -197,6 +212,23 @@ func TestContext2Apply_identity(t *testing.T) { } tfdiags.AssertNoDiagnostics(t, diags) + if tc.expectedDeleteIdentity != cty.NilVal { + var deleteRequests []providers.ApplyResourceChangeRequest + for _, req := range applyRequests { + if req.PlannedState.IsNull() { + deleteRequests = append(deleteRequests, req) + } else if !req.PlannedIdentity.RawEquals(tc.plannedIdentity) { + t.Fatalf("wrong identity in apply request\nwant: %s\ngot: %s", tc.plannedIdentity.GoString(), req.PlannedIdentity.GoString()) + } + } + if len(deleteRequests) != 1 { + t.Fatalf("provider received %d delete requests; want 1", len(deleteRequests)) + } + if got := deleteRequests[0].PlannedIdentity; !got.RawEquals(tc.expectedDeleteIdentity) { + t.Fatalf("wrong identity in delete request\nwant: %s\ngot: %s", tc.expectedDeleteIdentity.GoString(), got.GoString()) + } + } + if !tc.expectedIdentity.IsNull() { schema := p.GetProviderSchemaResponse.ResourceTypes["test_resource"] diff --git a/internal/terraform/node_resource_abstract_instance.go b/internal/terraform/node_resource_abstract_instance.go index 78c60f0e9897..f2914b9a3e92 100644 --- a/internal/terraform/node_resource_abstract_instance.go +++ b/internal/terraform/node_resource_abstract_instance.go @@ -2725,6 +2725,10 @@ func (n *NodeAbstractResourceInstance) apply( } } } else { + plannedIdentity := change.AfterIdentity + if change.Action == plans.Delete && plannedIdentity.IsNull() { + plannedIdentity = change.BeforeIdentity + } resp = provider.ApplyResourceChange(providers.ApplyResourceChangeRequest{ TypeName: n.Addr.Resource.Resource.Type, PriorState: unmarkedBefore, @@ -2732,7 +2736,7 @@ func (n *NodeAbstractResourceInstance) apply( PlannedState: unmarkedAfter, PlannedPrivate: change.Private, ProviderMeta: metaConfigVal, - PlannedIdentity: change.AfterIdentity, + PlannedIdentity: plannedIdentity, }) if !resp.NewIdentity.IsNull() { From e432e7e2e88dd09d024fda91bc88181faf6270c5 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 2 Oct 2026 09:23:49 -0400 Subject: [PATCH 31/33] Backport of Cloud, backend/remote: forward `-minimal-refresh` to HCPT and TFE into v1.17 (#39321) * backport of commit 9739f0a4d4a07c50f6f0f0558967cd88d2dd2787 * backport of commit 6c2fa1aaf355005aa461abe5cbcef53f4aa06fe3 * backport of commit aca4e46487f1a0b9ba1b13d1877b04a0ef2d537f * backport of commit a9166494f7036545470fd66cb0993db4c2a22791 * backport of commit 26ba0a3244ed14e9d284c2c47d6ed57a3f97c48b * backport of commit 307cd7bd6ad1a6a54993a129e76bded5d4f18cdb * backport of commit 632479776863638a88c4eaa06e75943620a4ac30 * backport of commit fff2e50b0a08af015ca207cc09197a62e56e38b2 * backport of commit 4eae50a591ed2d1a9ef0ad53153f5671ae7dabc1 * backport of commit 4a5d9c5231b21fcc8f7bc6bb09fdcf655e31d594 --------- Co-authored-by: Shweta <35878561+shwetamurali@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 +- internal/backend/remote/backend_apply.go | 21 ++- .../remote/backend_minimal_refresh_test.go | 170 ++++++++++++++++++ internal/backend/remote/backend_plan.go | 27 ++- internal/cloud/backend_apply.go | 10 +- .../cloud/backend_minimal_refresh_test.go | 168 +++++++++++++++++ internal/cloud/backend_plan.go | 50 +++++- internal/cloud/tfe_client_mock.go | 4 + 9 files changed, 423 insertions(+), 33 deletions(-) create mode 100644 internal/backend/remote/backend_minimal_refresh_test.go create mode 100644 internal/cloud/backend_minimal_refresh_test.go diff --git a/go.mod b/go.mod index 640146198c07..2fb0487e8b5a 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/hashicorp/go-plugin v1.7.0 github.com/hashicorp/go-retryablehttp v0.7.8 github.com/hashicorp/go-slug v0.18.3 - github.com/hashicorp/go-tfe v1.110.0 + github.com/hashicorp/go-tfe v1.112.0 github.com/hashicorp/go-uuid v1.0.3 github.com/hashicorp/go-version v1.9.0 github.com/hashicorp/hcl v1.0.0 diff --git a/go.sum b/go.sum index 518abefe6f3d..be62f6851c75 100644 --- a/go.sum +++ b/go.sum @@ -378,8 +378,8 @@ github.com/hashicorp/go-slug v0.18.3 h1:xtF8Rz4WmaSQPMMLYptoyodSwgYfpCEnZCIdjckf github.com/hashicorp/go-slug v0.18.3/go.mod h1:///5rV+lBK0tFD6VwAFbKRx/NzQR6W56enWX4T0XLos= github.com/hashicorp/go-sockaddr v1.0.5 h1:dvk7TIXCZpmfOlM+9mlcrWmWjw/wlKT+VDq2wMvfPJU= github.com/hashicorp/go-sockaddr v1.0.5/go.mod h1:uoUUmtwU7n9Dv3O4SNLeFvg0SxQ3lyjsj6+CCykpaxI= -github.com/hashicorp/go-tfe v1.110.0 h1:R61zw8hgXH+A06rb77GhZXkexjiTls/sPM+lL3G4VsE= -github.com/hashicorp/go-tfe v1.110.0/go.mod h1:VH4URSfSw6421VEBdfjub/oTINTvT5Mhp4Gd9IA3Ifw= +github.com/hashicorp/go-tfe v1.112.0 h1:Mu/IjtFMedVyBsGfcOYU5nCcPODK+DuV7I42jnGgPIg= +github.com/hashicorp/go-tfe v1.112.0/go.mod h1:d8js2OmMnCq58gEh26mCS81nD8Aj7HmG6IO1b80gM78= github.com/hashicorp/go-tfe/v2 v2.6.0 h1:1CItfvWIAE09qLr644qDkzl0KZBv08O9Gu7je8CLSK4= github.com/hashicorp/go-tfe/v2 v2.6.0/go.mod h1:gosuJ9PH3NLxkCoCW3EIeHHli+5QqLUkboBiUZ1ljCM= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= diff --git a/internal/backend/remote/backend_apply.go b/internal/backend/remote/backend_apply.go index e9197abc9bf5..8c7990c312f0 100644 --- a/internal/backend/remote/backend_apply.go +++ b/internal/backend/remote/backend_apply.go @@ -14,6 +14,7 @@ import ( version "github.com/hashicorp/go-version" "github.com/hashicorp/terraform/internal/backend/backendrun" + "github.com/hashicorp/terraform/internal/cloud" "github.com/hashicorp/terraform/internal/plans" "github.com/hashicorp/terraform/internal/terraform" "github.com/hashicorp/terraform/internal/tfdiags" @@ -161,12 +162,20 @@ func (b *Remote) opApply(stopCtx, cancelCtx context.Context, op *backendrun.Oper } if op.PlanMinimalRefresh { - diags = diags.Append(tfdiags.Sourceless( - tfdiags.Error, - "Minimal refresh planning option is currently not supported", - `The "remote" backend does not support the -minimal-refresh option for `+ - `remote plans at this time.`, - )) + desiredAPIVersion, _ := version.NewVersion(cloud.MinimalRefreshMinAPIVersion) + + if parseErr != nil || currentAPIVersion.LessThan(desiredAPIVersion) { + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Minimal refresh is not supported", + fmt.Sprintf( + `The host %s does not support the -minimal-refresh option. `+ + `If you use Terraform Enterprise, upgrade to a version that `+ + `supports minimal refresh. Otherwise, run without -minimal-refresh.`, + b.hostname, + ), + )) + } } // Return if there are any errors. diff --git a/internal/backend/remote/backend_minimal_refresh_test.go b/internal/backend/remote/backend_minimal_refresh_test.go new file mode 100644 index 000000000000..a1bc6becdf6e --- /dev/null +++ b/internal/backend/remote/backend_minimal_refresh_test.go @@ -0,0 +1,170 @@ +// Copyright IBM Corp. 2014, 2026 +// SPDX-License-Identifier: BUSL-1.1 + +package remote + +import ( + "context" + "fmt" + "strings" + "testing" + + "github.com/hashicorp/cli" + + "github.com/hashicorp/terraform/internal/backend" + "github.com/hashicorp/terraform/internal/backend/backendrun" + "github.com/hashicorp/terraform/internal/cloud" + "github.com/hashicorp/terraform/internal/terminal" +) + +// TestRemote_minimalRefresh verifies that the -minimal-refresh planning option +// is forwarded to HCP Terraform / TFE as the minimal-refresh run attribute, +// and that it is not set for ordinary runs. +func TestRemote_minimalRefresh(t *testing.T) { + cases := map[string]struct { + apply bool + minimalRefresh bool + }{ + "plan": {}, + "plan minimal refresh": {minimalRefresh: true}, + "apply": {apply: true}, + "apply minimal refresh": {apply: true, minimalRefresh: true}, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + b, bCleanup := testBackendDefault(t) + defer bCleanup() + b.client.SetFakeRemoteAPIVersion(cloud.MinimalRefreshMinAPIVersion) + + var op *backendrun.Operation + var configCleanup func() + if tc.apply { + o, cc, done := testOperationApply(t, "./testdata/apply") + defer done(t) + op, configCleanup = o, cc + } else { + o, cc, done := testOperationPlan(t, "./testdata/plan") + defer done(t) + op, configCleanup = o, cc + } + defer configCleanup() + + op.Workspace = backend.DefaultStateName + op.PlanMinimalRefresh = tc.minimalRefresh + + run, err := b.Operation(context.Background(), op) + if err != nil { + t.Fatalf("error starting operation: %v", err) + } + <-run.Done() + + errOutput := b.CLI.(*cli.MockUi).ErrorWriter.String() + if run.Result != backendrun.OperationSuccess { + t.Fatalf("operation failed: %s", errOutput) + } + if strings.Contains(errOutput, "not supported") { + t.Fatalf("unexpected unsupported diagnostic: %s", errOutput) + } + + runsAPI := b.client.Runs.(*cloud.MockRuns) + if got := len(runsAPI.Runs); got != 1 { + t.Fatalf("wrong number of runs in the mock client %d; want 1", got) + } + for _, r := range runsAPI.Runs { + if got, want := r.MinimalRefresh, tc.minimalRefresh; got != want { + t.Errorf("wrong MinimalRefresh: got %v, want %v", got, want) + } + + // Minimal refresh must not be converted into -refresh=false or + // -refresh-only. + if !r.Refresh { + t.Error("expected Refresh to be true") + } + if r.RefreshOnly { + t.Error("expected RefreshOnly to be false") + } + + // A plan must remain speculative (the mock creates no apply for + // speculative configuration versions); an apply must be applicable. + if got, want := r.Apply != nil, tc.apply; got != want { + t.Errorf("wrong applicable run: got %v, want %v", got, want) + } + } + }) + } +} + +// TestRemote_minimalRefreshAPIVersion verifies that -minimal-refresh is rejected +// before any run is created when the server's API version is too old, and is +// forwarded when the server is at or above the minimum. +func TestRemote_minimalRefreshAPIVersion(t *testing.T) { + cases := map[string]struct { + apiVersion string + apply bool + wantErr bool + }{ + "plan below minimum": {apiVersion: "2.6", wantErr: true}, + "apply below minimum": {apiVersion: "2.6", apply: true, wantErr: true}, + "plan unparseable": {apiVersion: "", wantErr: true}, + "plan at minimum": {apiVersion: cloud.MinimalRefreshMinAPIVersion}, + "apply at minimum": {apiVersion: cloud.MinimalRefreshMinAPIVersion, apply: true}, + "plan above minimum": {apiVersion: "2.8"}, + "apply above minimum": {apiVersion: "2.8", apply: true}, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + b, bCleanup := testBackendDefault(t) + defer bCleanup() + b.client.SetFakeRemoteAPIVersion(tc.apiVersion) + + var op *backendrun.Operation + var configCleanup func() + var done func(*testing.T) *terminal.TestOutput + if tc.apply { + op, configCleanup, done = testOperationApply(t, "./testdata/apply") + } else { + op, configCleanup, done = testOperationPlan(t, "./testdata/plan") + } + defer configCleanup() + + op.Workspace = backend.DefaultStateName + op.PlanMinimalRefresh = true + + run, err := b.Operation(context.Background(), op) + if err != nil { + t.Fatalf("error starting operation: %v", err) + } + <-run.Done() + errOutput := strings.Join(strings.Fields(done(t).Stderr()), " ") + runsAPI := b.client.Runs.(*cloud.MockRuns) + + if tc.wantErr { + if run.Result == backendrun.OperationSuccess { + t.Fatal("expected operation to fail") + } + want := fmt.Sprintf("The host %s does not support the -minimal-refresh option", b.hostname) + if !strings.Contains(errOutput, want) { + t.Errorf("missing %q in error output:\n%s", want, errOutput) + } + if len(runsAPI.Runs) != 0 { + t.Errorf("expected no runs to be created, got %d", len(runsAPI.Runs)) + } + return + } + + if run.Result != backendrun.OperationSuccess { + t.Fatalf("operation failed: %s", errOutput) + } + if got := len(runsAPI.Runs); got != 1 { + t.Fatalf("expected 1 run, got %d", got) + } + for _, r := range runsAPI.Runs { + if !r.MinimalRefresh { + t.Error("expected MinimalRefresh to be forwarded") + } + } + }) + } +} diff --git a/internal/backend/remote/backend_plan.go b/internal/backend/remote/backend_plan.go index 8d7afbc5ac24..71756cbd7273 100644 --- a/internal/backend/remote/backend_plan.go +++ b/internal/backend/remote/backend_plan.go @@ -21,6 +21,7 @@ import ( version "github.com/hashicorp/go-version" "github.com/hashicorp/terraform/internal/backend/backendrun" + "github.com/hashicorp/terraform/internal/cloud" "github.com/hashicorp/terraform/internal/logging" "github.com/hashicorp/terraform/internal/plans" "github.com/hashicorp/terraform/internal/tfdiags" @@ -177,12 +178,20 @@ func (b *Remote) opPlan(stopCtx, cancelCtx context.Context, op *backendrun.Opera } if op.PlanMinimalRefresh { - diags = diags.Append(tfdiags.Sourceless( - tfdiags.Error, - "Minimal refresh planning option is currently not supported", - `The "remote" backend does not support the -minimal-refresh option for `+ - `remote plans at this time.`, - )) + desiredAPIVersion, _ := version.NewVersion(cloud.MinimalRefreshMinAPIVersion) + + if parseErr != nil || currentAPIVersion.LessThan(desiredAPIVersion) { + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Minimal refresh is not supported", + fmt.Sprintf( + `The host %s does not support the -minimal-refresh option. `+ + `If you use Terraform Enterprise, upgrade to a version that `+ + `supports minimal refresh. Otherwise, run without -minimal-refresh.`, + b.hostname, + ), + )) + } } // Return if there are any errors. @@ -308,6 +317,12 @@ in order to capture the filesystem context the remote workspace expects: Workspace: w, } + // Only send the minimal-refresh attribute when requested, so that it is + // never included for ordinary runs. + if op.PlanMinimalRefresh { + runOptions.MinimalRefresh = tfe.Bool(true) + } + switch op.PlanMode { case plans.NormalMode: // okay, but we don't need to do anything special for this diff --git a/internal/cloud/backend_apply.go b/internal/cloud/backend_apply.go index 0c6e99b8936c..e9c21d13d10a 100644 --- a/internal/cloud/backend_apply.go +++ b/internal/cloud/backend_apply.go @@ -76,15 +76,7 @@ func (b *Cloud) opApply(stopCtx, cancelCtx context.Context, op *backendrun.Opera )) } - // TODO:@austinvalle: This will eventually be added to HCPT / go-tfe and should be removed - if op.PlanMinimalRefresh { - diags = diags.Append(tfdiags.Sourceless( - tfdiags.Error, - "Minimal refresh planning option is currently not supported", - fmt.Sprintf("%s does not support the -minimal-refresh option for ", b.appName)+ - "plans at this time.", - )) - } + diags = diags.Append(b.checkMinimalRefreshAPIVersion(op)) // Return if there are any errors. if diags.HasErrors() { diff --git a/internal/cloud/backend_minimal_refresh_test.go b/internal/cloud/backend_minimal_refresh_test.go new file mode 100644 index 000000000000..67b1a64c3dac --- /dev/null +++ b/internal/cloud/backend_minimal_refresh_test.go @@ -0,0 +1,168 @@ +// Copyright IBM Corp. 2014, 2026 +// SPDX-License-Identifier: BUSL-1.1 + +package cloud + +import ( + "context" + "fmt" + "strings" + "testing" + + "github.com/hashicorp/cli" + + "github.com/hashicorp/terraform/internal/backend/backendrun" + "github.com/hashicorp/terraform/internal/terminal" +) + +// TestCloud_minimalRefresh verifies that the -minimal-refresh planning option +// is forwarded to HCP Terraform / TFE as the minimal-refresh run attribute, +// and that it is not set for ordinary runs. +func TestCloud_minimalRefresh(t *testing.T) { + cases := map[string]struct { + apply bool + minimalRefresh bool + }{ + "plan": {}, + "plan minimal refresh": {minimalRefresh: true}, + "apply": {apply: true}, + "apply minimal refresh": {apply: true, minimalRefresh: true}, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + b, bCleanup := testBackendWithName(t) + defer bCleanup() + b.client.SetFakeRemoteAPIVersion(MinimalRefreshMinAPIVersion) + + var op *backendrun.Operation + var configCleanup func() + if tc.apply { + o, cc, done := testOperationApply(t, "./testdata/apply") + defer done(t) + op, configCleanup = o, cc + } else { + o, cc, done := testOperationPlan(t, "./testdata/plan") + defer done(t) + op, configCleanup = o, cc + } + defer configCleanup() + + op.Workspace = testBackendSingleWorkspaceName + op.PlanMinimalRefresh = tc.minimalRefresh + + run, err := b.Operation(context.Background(), op) + if err != nil { + t.Fatalf("error starting operation: %v", err) + } + <-run.Done() + + errOutput := b.CLI.(*cli.MockUi).ErrorWriter.String() + if run.Result != backendrun.OperationSuccess { + t.Fatalf("operation failed: %s", errOutput) + } + if strings.Contains(errOutput, "not supported") { + t.Fatalf("unexpected unsupported diagnostic: %s", errOutput) + } + + runsAPI := b.client.Runs.(*MockRuns) + if got := len(runsAPI.Runs); got != 1 { + t.Fatalf("wrong number of runs in the mock client %d; want 1", got) + } + for _, r := range runsAPI.Runs { + if got, want := r.MinimalRefresh, tc.minimalRefresh; got != want { + t.Errorf("wrong MinimalRefresh: got %v, want %v", got, want) + } + + // Minimal refresh must not be converted into -refresh=false or + // -refresh-only. + if !r.Refresh { + t.Error("expected Refresh to be true") + } + if r.RefreshOnly { + t.Error("expected RefreshOnly to be false") + } + + // A plan must remain speculative (the mock creates no apply for + // speculative configuration versions); an apply must be applicable. + if got, want := r.Apply != nil, tc.apply; got != want { + t.Errorf("wrong applicable run: got %v, want %v", got, want) + } + } + }) + } +} + +// TestCloud_minimalRefreshAPIVersion verifies that -minimal-refresh is rejected +// before any run is created when the server's API version is too old, and is +// forwarded when the server is at or above the minimum. +func TestCloud_minimalRefreshAPIVersion(t *testing.T) { + cases := map[string]struct { + apiVersion string + apply bool + wantErr bool + }{ + "plan below minimum": {apiVersion: "2.6", wantErr: true}, + "apply below minimum": {apiVersion: "2.6", apply: true, wantErr: true}, + "plan unparseable": {apiVersion: "", wantErr: true}, + "plan at minimum": {apiVersion: MinimalRefreshMinAPIVersion}, + "apply at minimum": {apiVersion: MinimalRefreshMinAPIVersion, apply: true}, + "plan above minimum": {apiVersion: "2.8"}, + "apply above minimum": {apiVersion: "2.8", apply: true}, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + b, bCleanup := testBackendWithName(t) + defer bCleanup() + b.client.SetFakeRemoteAPIVersion(tc.apiVersion) + + var op *backendrun.Operation + var configCleanup func() + var done func(*testing.T) *terminal.TestOutput + if tc.apply { + op, configCleanup, done = testOperationApply(t, "./testdata/apply") + } else { + op, configCleanup, done = testOperationPlan(t, "./testdata/plan") + } + defer configCleanup() + + op.Workspace = testBackendSingleWorkspaceName + op.PlanMinimalRefresh = true + + run, err := b.Operation(context.Background(), op) + if err != nil { + t.Fatalf("error starting operation: %v", err) + } + <-run.Done() + errOutput := strings.Join(strings.Fields(done(t).Stderr()), " ") + runsAPI := b.client.Runs.(*MockRuns) + + if tc.wantErr { + if run.Result == backendrun.OperationSuccess { + t.Fatal("expected operation to fail") + } + want := fmt.Sprintf("The host %s does not support the -minimal-refresh option", b.Hostname) + if !strings.Contains(errOutput, want) { + t.Errorf("missing %q in error output:\n%s", want, errOutput) + } + if len(runsAPI.Runs) != 0 { + t.Errorf("expected no runs to be created, got %d", len(runsAPI.Runs)) + } + return + } + + if run.Result != backendrun.OperationSuccess { + t.Fatalf("operation failed: %s", errOutput) + } + if got := len(runsAPI.Runs); got != 1 { + t.Fatalf("expected 1 run, got %d", got) + } + for _, r := range runsAPI.Runs { + if !r.MinimalRefresh { + t.Error("expected MinimalRefresh to be forwarded") + } + } + }) + } +} diff --git a/internal/cloud/backend_plan.go b/internal/cloud/backend_plan.go index 812d39098012..15d45e4a85f7 100644 --- a/internal/cloud/backend_plan.go +++ b/internal/cloud/backend_plan.go @@ -31,6 +31,11 @@ import ( var planConfigurationVersionsPollInterval = 500 * time.Millisecond +// MinimalRefreshMinAPIVersion is the minimum TFP-API-Version a server must +// report for Terraform to send the -minimal-refresh option. It is shared with +// the legacy "remote" backend. +const MinimalRefreshMinAPIVersion = "2.7" + func (b *Cloud) opPlan(stopCtx, cancelCtx context.Context, op *backendrun.Operation, w *tfe.Workspace) (OperationResult, error) { log.Printf("[INFO] cloud: starting Plan operation") @@ -86,15 +91,7 @@ func (b *Cloud) opPlan(stopCtx, cancelCtx context.Context, op *backendrun.Operat )) } - // TODO:@austinvalle: This will eventually be added to HCPT / go-tfe and should be removed - if op.PlanMinimalRefresh { - diags = diags.Append(tfdiags.Sourceless( - tfdiags.Error, - "Minimal refresh planning option is currently not supported", - fmt.Sprintf("%s does not support the -minimal-refresh option for ", b.appName)+ - "plans at this time.", - )) - } + diags = diags.Append(b.checkMinimalRefreshAPIVersion(op)) if len(op.GenerateConfigOut) > 0 { diags = diags.Append(genconfig.ValidateTargetFile(op.GenerateConfigOut)) @@ -158,6 +155,12 @@ func (b *Cloud) plan(stopCtx, cancelCtx context.Context, op *backendrun.Operatio SavePlan: tfe.Bool(op.PlanOutPath != ""), } + // Only send the minimal-refresh attribute when requested, so that it is + // never included for ordinary runs. + if op.PlanMinimalRefresh { + runOptions.MinimalRefresh = tfe.Bool(true) + } + switch op.PlanMode { case plans.NormalMode: // okay, but we don't need to do anything special for this @@ -593,3 +596,32 @@ const lockTimeoutErr = ` [reset][red]Lock timeout exceeded, sending interrupt to cancel the remote operation. [reset] ` + +// checkMinimalRefreshAPIVersion returns an error diagnostic if -minimal-refresh +// was requested but the server's API version is too old to support it. Older +// servers silently ignore unknown run attributes, so this must be checked +// before any run is created. +func (b *Cloud) checkMinimalRefreshAPIVersion(op *backendrun.Operation) tfdiags.Diagnostics { + var diags tfdiags.Diagnostics + if !op.PlanMinimalRefresh { + return diags + } + + // For API versions prior to 2.3, RemoteAPIVersion will return an empty + // string, so a parse error is treated as an unsupported version. + currentAPIVersion, parseErr := version.NewVersion(b.client.RemoteAPIVersion()) + desiredAPIVersion, _ := version.NewVersion(MinimalRefreshMinAPIVersion) + if parseErr != nil || currentAPIVersion.LessThan(desiredAPIVersion) { + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Minimal refresh is not supported", + fmt.Sprintf( + `The host %s does not support the -minimal-refresh option. `+ + `If you use Terraform Enterprise, upgrade to a version that `+ + `supports minimal refresh. Otherwise, run without -minimal-refresh.`, + b.Hostname, + ), + )) + } + return diags +} diff --git a/internal/cloud/tfe_client_mock.go b/internal/cloud/tfe_client_mock.go index 53e3734aeee0..700c65358417 100644 --- a/internal/cloud/tfe_client_mock.go +++ b/internal/cloud/tfe_client_mock.go @@ -1332,6 +1332,10 @@ func (m *MockRuns) Create(ctx context.Context, options tfe.RunCreateOptions) (*t r.RefreshOnly = *options.RefreshOnly } + if options.MinimalRefresh != nil { + r.MinimalRefresh = *options.MinimalRefresh + } + if options.AllowConfigGeneration != nil && *options.AllowConfigGeneration { r.Plan.GeneratedConfiguration = true } From 690e019678890a1a2d3e99e7e3cd298e501334c5 Mon Sep 17 00:00:00 2001 From: hc-github-team-tf-core <82990137+hc-github-team-tf-core@users.noreply.github.com> Date: Wed, 7 Oct 2026 14:03:32 +0100 Subject: [PATCH 32/33] Prepare before 1.17.0-rc1 release (#39346) Co-authored-by: hc-github-team-tf-core --- CHANGELOG.md | 12 +----------- version/VERSION | 2 +- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59144acc1fb4..33342df0a5e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.17.0 (Unreleased) +## 1.17.0-rc1 (October 07, 2026) NEW FEATURES: @@ -37,16 +37,6 @@ NOTES: * version: JSON output now includes a new `format_version` field, which will enable safer future changes of the command's JSON output format. It is assumed existing tooling ignores unknown fields and therefore this change should not be breaking in itself but we advice consumers to pay attention to `format_version` in future releases and/or use latest version of hashicorp/terraform-json & hashicorp/terraform-exec which does. ([#38930](https://github.com/hashicorp/terraform/issues/38930)) -EXPERIMENTS: - -Experiments are only enabled in alpha releases of Terraform CLI. The following features are not yet available in stable releases. - -- The experimental "deferred actions" feature, enabled by passing the `-allow-deferral` option to `terraform plan`, permits `count` and `for_each` arguments in `module`, `resource`, and `data` blocks to have unknown values and allows providers to react more flexibly to unknown values. -- `terraform test cleanup`: The experimental `test cleanup` command. In experimental builds of Terraform, a manifest file and state files for each failed cleanup operation during test operations are saved within the `.terraform` local directory. The `test cleanup` command will attempt to clean up the local state files left behind automatically, without requiring manual intervention. -- `terraform test`: `backend` blocks and `skip_cleanup` attributes: - - Test authors can now specify `backend` blocks within `run` blocks in Terraform Test files. Run blocks with `backend` blocks will load state from the specified backend instead of starting from empty state on every execution. This allows test authors to keep long-running test infrastructure alive between test operations, saving time during regular test operations. - - Test authors can now specify `skip_cleanup` attributes within test files and within run blocks. The `skip_cleanup` attribute tells `terraform test` not to clean up state files produced by run blocks with this attribute set to true. The state files for affected run blocks will be written to disk within the `.terraform` directory, where they can then be cleaned up manually using the also experimental `terraform test cleanup` command. - ## Previous Releases For information on prior major and minor releases, refer to their changelogs: diff --git a/version/VERSION b/version/VERSION index ee8855caa4a7..f847033d17b0 100644 --- a/version/VERSION +++ b/version/VERSION @@ -1 +1 @@ -1.17.0-dev +1.17.0-rc1 From 6035c058aafb7dba128bab7999aee35508b3067d Mon Sep 17 00:00:00 2001 From: hc-github-team-tf-core Date: Wed, 7 Oct 2026 20:06:26 +0000 Subject: [PATCH 33/33] Cleanup after 1.17.0-rc1 release --- CHANGELOG.md | 12 +++++++++++- version/VERSION | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33342df0a5e6..59144acc1fb4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## 1.17.0-rc1 (October 07, 2026) +## 1.17.0 (Unreleased) NEW FEATURES: @@ -37,6 +37,16 @@ NOTES: * version: JSON output now includes a new `format_version` field, which will enable safer future changes of the command's JSON output format. It is assumed existing tooling ignores unknown fields and therefore this change should not be breaking in itself but we advice consumers to pay attention to `format_version` in future releases and/or use latest version of hashicorp/terraform-json & hashicorp/terraform-exec which does. ([#38930](https://github.com/hashicorp/terraform/issues/38930)) +EXPERIMENTS: + +Experiments are only enabled in alpha releases of Terraform CLI. The following features are not yet available in stable releases. + +- The experimental "deferred actions" feature, enabled by passing the `-allow-deferral` option to `terraform plan`, permits `count` and `for_each` arguments in `module`, `resource`, and `data` blocks to have unknown values and allows providers to react more flexibly to unknown values. +- `terraform test cleanup`: The experimental `test cleanup` command. In experimental builds of Terraform, a manifest file and state files for each failed cleanup operation during test operations are saved within the `.terraform` local directory. The `test cleanup` command will attempt to clean up the local state files left behind automatically, without requiring manual intervention. +- `terraform test`: `backend` blocks and `skip_cleanup` attributes: + - Test authors can now specify `backend` blocks within `run` blocks in Terraform Test files. Run blocks with `backend` blocks will load state from the specified backend instead of starting from empty state on every execution. This allows test authors to keep long-running test infrastructure alive between test operations, saving time during regular test operations. + - Test authors can now specify `skip_cleanup` attributes within test files and within run blocks. The `skip_cleanup` attribute tells `terraform test` not to clean up state files produced by run blocks with this attribute set to true. The state files for affected run blocks will be written to disk within the `.terraform` directory, where they can then be cleaned up manually using the also experimental `terraform test cleanup` command. + ## Previous Releases For information on prior major and minor releases, refer to their changelogs: diff --git a/version/VERSION b/version/VERSION index f847033d17b0..ee8855caa4a7 100644 --- a/version/VERSION +++ b/version/VERSION @@ -1 +1 @@ -1.17.0-rc1 +1.17.0-dev