From 0ff1b77afa6807d94fd8001c8583d645c3181d16 Mon Sep 17 00:00:00 2001 From: Daniel Schmidt Date: Mon, 6 Jan 2025 16:10:14 +0100 Subject: [PATCH] standardize client capabilities --- internal/grpcwrap/provider.go | 1 + .../internal/stackeval/client_capabilities.go | 15 ++++ .../internal/stackeval/provider_instance.go | 9 +- .../stackeval/provider_instance_test.go | 10 +-- internal/terraform/eval_context.go | 4 + internal/terraform/eval_context_builtin.go | 7 ++ internal/terraform/eval_context_mock.go | 7 ++ .../node_resource_abstract_instance.go | 83 ++++++++----------- internal/terraform/node_resource_import.go | 9 +- .../terraform/node_resource_plan_instance.go | 9 +- internal/terraform/node_resource_validate.go | 8 +- 11 files changed, 81 insertions(+), 81 deletions(-) create mode 100644 internal/stacks/stackruntime/internal/stackeval/client_capabilities.go diff --git a/internal/grpcwrap/provider.go b/internal/grpcwrap/provider.go index 705e7b1ed1..f8644381ea 100644 --- a/internal/grpcwrap/provider.go +++ b/internal/grpcwrap/provider.go @@ -122,6 +122,7 @@ func (p *provider) ValidateResourceTypeConfig(_ context.Context, req *tfplugin5. TypeName: req.TypeName, Config: configVal, ClientCapabilities: providers.ClientCapabilities{ + DeferralAllowed: true, WriteOnlyAttributesAllowed: true, }, }) diff --git a/internal/stacks/stackruntime/internal/stackeval/client_capabilities.go b/internal/stacks/stackruntime/internal/stackeval/client_capabilities.go new file mode 100644 index 0000000000..15202fbb6a --- /dev/null +++ b/internal/stacks/stackruntime/internal/stackeval/client_capabilities.go @@ -0,0 +1,15 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package stackeval + +import "github.com/hashicorp/terraform/internal/providers" + +// ClientCapabilities returns the client capabilities sent to the providers +// for each request. They define what this terraform instance is capable of. +func ClientCapabilities() providers.ClientCapabilities { + return providers.ClientCapabilities{ + DeferralAllowed: true, + WriteOnlyAttributesAllowed: true, + } +} diff --git a/internal/stacks/stackruntime/internal/stackeval/provider_instance.go b/internal/stacks/stackruntime/internal/stackeval/provider_instance.go index 2ddc8e434f..7c8e0204f9 100644 --- a/internal/stacks/stackruntime/internal/stackeval/provider_instance.go +++ b/internal/stacks/stackruntime/internal/stackeval/provider_instance.go @@ -256,12 +256,9 @@ func (p *ProviderInstance) CheckClient(ctx context.Context, phase EvalPhase) (pr } resp := client.ConfigureProvider(providers.ConfigureProviderRequest{ - TerraformVersion: version.SemVer.String(), - Config: unmarkedArgs, - ClientCapabilities: providers.ClientCapabilities{ - DeferralAllowed: true, - WriteOnlyAttributesAllowed: true, - }, + TerraformVersion: version.SemVer.String(), + Config: unmarkedArgs, + ClientCapabilities: ClientCapabilities(), }) diags = diags.Append(resp.Diagnostics) if resp.Diagnostics.HasErrors() { diff --git a/internal/stacks/stackruntime/internal/stackeval/provider_instance_test.go b/internal/stacks/stackruntime/internal/stackeval/provider_instance_test.go index 1339b39916..6ca58c691d 100644 --- a/internal/stacks/stackruntime/internal/stackeval/provider_instance_test.go +++ b/internal/stacks/stackruntime/internal/stackeval/provider_instance_test.go @@ -383,10 +383,7 @@ func TestProviderInstanceCheckClient(t *testing.T) { Config: cty.ObjectVal(map[string]cty.Value{ "test": cty.StringVal("yep"), }), - ClientCapabilities: providers.ClientCapabilities{ - DeferralAllowed: true, - WriteOnlyAttributesAllowed: true, - }, + ClientCapabilities: ClientCapabilities(), } if diff := cmp.Diff(want, got, ctydebug.CmpOptions); diff != "" { t.Errorf("wrong request\n%s", diff) @@ -426,10 +423,7 @@ func TestProviderInstanceCheckClient(t *testing.T) { Config: cty.ObjectVal(map[string]cty.Value{ "test": cty.StringVal("yep"), }), - ClientCapabilities: providers.ClientCapabilities{ - DeferralAllowed: true, - WriteOnlyAttributesAllowed: true, - }, + ClientCapabilities: ClientCapabilities(), } if diff := cmp.Diff(want, got, ctydebug.CmpOptions); diff != "" { t.Errorf("wrong request\n%s", diff) diff --git a/internal/terraform/eval_context.go b/internal/terraform/eval_context.go index 30ed37e928..bde1626ca3 100644 --- a/internal/terraform/eval_context.go +++ b/internal/terraform/eval_context.go @@ -191,6 +191,10 @@ type EvalContext interface { // perform a planned action due to an upstream dependency being deferred. Deferrals() *deferring.Deferred + // ClientCapabilities returns the client capabilities sent to the providers + // for each request. They define what this terraform instance is capable of. + ClientCapabilities() providers.ClientCapabilities + // MoveResults returns a map describing the results of handling any // resource instance move statements prior to the graph walk, so that // the graph walk can then record that information appropriately in other diff --git a/internal/terraform/eval_context_builtin.go b/internal/terraform/eval_context_builtin.go index 0a7610a78f..c9950f608d 100644 --- a/internal/terraform/eval_context_builtin.go +++ b/internal/terraform/eval_context_builtin.go @@ -613,3 +613,10 @@ func (ctx *BuiltinEvalContext) Forget() bool { func (ctx *BuiltinEvalContext) EphemeralResources() *ephemeral.Resources { return ctx.EphemeralResourcesValue } + +func (ctx *BuiltinEvalContext) ClientCapabilities() providers.ClientCapabilities { + return providers.ClientCapabilities{ + DeferralAllowed: ctx.Deferrals().DeferralAllowed(), + WriteOnlyAttributesAllowed: true, + } +} diff --git a/internal/terraform/eval_context_mock.go b/internal/terraform/eval_context_mock.go index 47daaceadb..bd2edf2031 100644 --- a/internal/terraform/eval_context_mock.go +++ b/internal/terraform/eval_context_mock.go @@ -424,3 +424,10 @@ func (c *MockEvalContext) Forget() bool { c.ForgetCalled = true return c.ForgetValues } + +func (ctx *MockEvalContext) ClientCapabilities() providers.ClientCapabilities { + return providers.ClientCapabilities{ + DeferralAllowed: ctx.Deferrals().DeferralAllowed(), + WriteOnlyAttributesAllowed: true, + } +} diff --git a/internal/terraform/node_resource_abstract_instance.go b/internal/terraform/node_resource_abstract_instance.go index e7f223e8df..6d721cc853 100644 --- a/internal/terraform/node_resource_abstract_instance.go +++ b/internal/terraform/node_resource_abstract_instance.go @@ -432,16 +432,13 @@ func (n *NodeAbstractResourceInstance) planDestroy(ctx EvalContext, currentState // Allow the provider to check the destroy plan, and insert any // necessary private data. resp = provider.PlanResourceChange(providers.PlanResourceChangeRequest{ - TypeName: n.Addr.Resource.Resource.Type, - Config: nullVal, - PriorState: unmarkedPriorVal, - ProposedNewState: nullVal, - PriorPrivate: currentState.Private, - ProviderMeta: metaConfigVal, - ClientCapabilities: providers.ClientCapabilities{ - DeferralAllowed: deferralAllowed, - WriteOnlyAttributesAllowed: true, - }, + TypeName: n.Addr.Resource.Resource.Type, + Config: nullVal, + PriorState: unmarkedPriorVal, + ProposedNewState: nullVal, + PriorPrivate: currentState.Private, + ProviderMeta: metaConfigVal, + ClientCapabilities: ctx.ClientCapabilities(), }) deferred = resp.Deferred @@ -635,14 +632,11 @@ func (n *NodeAbstractResourceInstance) refresh(ctx EvalContext, deposedKey state } } else { resp = provider.ReadResource(providers.ReadResourceRequest{ - TypeName: n.Addr.Resource.Resource.Type, - PriorState: priorVal, - Private: state.Private, - ProviderMeta: metaConfigVal, - ClientCapabilities: providers.ClientCapabilities{ - DeferralAllowed: deferralAllowed, - WriteOnlyAttributesAllowed: true, - }, + TypeName: n.Addr.Resource.Resource.Type, + PriorState: priorVal, + Private: state.Private, + ProviderMeta: metaConfigVal, + ClientCapabilities: ctx.ClientCapabilities(), }) // If we don't support deferrals, but the provider reports a deferral and does not @@ -863,11 +857,9 @@ func (n *NodeAbstractResourceInstance) plan( unmarkedConfigVal, _ := origConfigVal.UnmarkDeep() validateResp := provider.ValidateResourceConfig( providers.ValidateResourceConfigRequest{ - TypeName: n.Addr.Resource.Resource.Type, - Config: unmarkedConfigVal, - ClientCapabilities: providers.ClientCapabilities{ - WriteOnlyAttributesAllowed: true, - }, + TypeName: n.Addr.Resource.Resource.Type, + Config: unmarkedConfigVal, + ClientCapabilities: ctx.ClientCapabilities(), }, ) diags = diags.Append(validateResp.Diagnostics.InConfigBody(config.Config, n.Addr.String())) @@ -926,16 +918,13 @@ func (n *NodeAbstractResourceInstance) plan( } } else { resp = provider.PlanResourceChange(providers.PlanResourceChangeRequest{ - TypeName: n.Addr.Resource.Resource.Type, - Config: unmarkedConfigVal, - PriorState: unmarkedPriorVal, - ProposedNewState: proposedNewVal, - PriorPrivate: priorPrivate, - ProviderMeta: metaConfigVal, - ClientCapabilities: providers.ClientCapabilities{ - DeferralAllowed: deferralAllowed, - WriteOnlyAttributesAllowed: true, - }, + TypeName: n.Addr.Resource.Resource.Type, + Config: unmarkedConfigVal, + PriorState: unmarkedPriorVal, + ProposedNewState: proposedNewVal, + PriorPrivate: priorPrivate, + ProviderMeta: metaConfigVal, + ClientCapabilities: ctx.ClientCapabilities(), }) // If we don't support deferrals, but the provider reports a deferral and does not // emit any error level diagnostics, we should emit an error. @@ -1100,16 +1089,13 @@ func (n *NodeAbstractResourceInstance) plan( } } else { resp = provider.PlanResourceChange(providers.PlanResourceChangeRequest{ - TypeName: n.Addr.Resource.Resource.Type, - Config: unmarkedConfigVal, - PriorState: nullPriorVal, - ProposedNewState: proposedNewVal, - PriorPrivate: plannedPrivate, - ProviderMeta: metaConfigVal, - ClientCapabilities: providers.ClientCapabilities{ - DeferralAllowed: deferralAllowed, - WriteOnlyAttributesAllowed: true, - }, + TypeName: n.Addr.Resource.Resource.Type, + Config: unmarkedConfigVal, + PriorState: nullPriorVal, + ProposedNewState: proposedNewVal, + PriorPrivate: plannedPrivate, + ProviderMeta: metaConfigVal, + ClientCapabilities: ctx.ClientCapabilities(), }) // If we don't support deferrals, but the provider reports a deferral and does not @@ -1567,13 +1553,10 @@ func (n *NodeAbstractResourceInstance) readDataSource(ctx EvalContext, configVal } } else { resp = provider.ReadDataSource(providers.ReadDataSourceRequest{ - TypeName: n.Addr.ContainingResource().Resource.Type, - Config: configVal, - ProviderMeta: metaConfigVal, - ClientCapabilities: providers.ClientCapabilities{ - DeferralAllowed: deferralAllowed, - WriteOnlyAttributesAllowed: true, - }, + TypeName: n.Addr.ContainingResource().Resource.Type, + Config: configVal, + ProviderMeta: metaConfigVal, + ClientCapabilities: ctx.ClientCapabilities(), }) // If we don't support deferrals, but the provider reports a deferral and does not diff --git a/internal/terraform/node_resource_import.go b/internal/terraform/node_resource_import.go index 5aefb9f289..fe4339cff7 100644 --- a/internal/terraform/node_resource_import.go +++ b/internal/terraform/node_resource_import.go @@ -103,12 +103,9 @@ func (n *graphNodeImportState) Execute(ctx EvalContext, op walkOperation) (diags } resp := provider.ImportResourceState(providers.ImportResourceStateRequest{ - TypeName: n.Addr.Resource.Resource.Type, - ID: n.ID, - ClientCapabilities: providers.ClientCapabilities{ - DeferralAllowed: false, - WriteOnlyAttributesAllowed: true, - }, + TypeName: n.Addr.Resource.Resource.Type, + ID: n.ID, + ClientCapabilities: ctx.ClientCapabilities(), }) diags = diags.Append(resp.Diagnostics) if diags.HasErrors() { diff --git a/internal/terraform/node_resource_plan_instance.go b/internal/terraform/node_resource_plan_instance.go index 0415b4694d..a7513cca64 100644 --- a/internal/terraform/node_resource_plan_instance.go +++ b/internal/terraform/node_resource_plan_instance.go @@ -649,12 +649,9 @@ func (n *NodePlannableResourceInstance) importState(ctx EvalContext, addr addrs. } } else { resp = provider.ImportResourceState(providers.ImportResourceStateRequest{ - TypeName: addr.Resource.Resource.Type, - ID: importId, - ClientCapabilities: providers.ClientCapabilities{ - DeferralAllowed: deferralAllowed, - WriteOnlyAttributesAllowed: true, - }, + TypeName: addr.Resource.Resource.Type, + ID: importId, + ClientCapabilities: ctx.ClientCapabilities(), }) } // If we don't support deferrals, but the provider reports a deferral and does not diff --git a/internal/terraform/node_resource_validate.go b/internal/terraform/node_resource_validate.go index 42d03a9fcf..b102d61d89 100644 --- a/internal/terraform/node_resource_validate.go +++ b/internal/terraform/node_resource_validate.go @@ -390,11 +390,9 @@ func (n *NodeValidatableResource) validateResource(ctx EvalContext) tfdiags.Diag // Use unmarked value for validate request unmarkedConfigVal, _ := configVal.UnmarkDeep() req := providers.ValidateResourceConfigRequest{ - TypeName: n.Config.Type, - Config: unmarkedConfigVal, - ClientCapabilities: providers.ClientCapabilities{ - WriteOnlyAttributesAllowed: true, - }, + TypeName: n.Config.Type, + Config: unmarkedConfigVal, + ClientCapabilities: ctx.ClientCapabilities(), } resp := provider.ValidateResourceConfig(req)