From 9c39e51466e5594002fb0366f686f17e0def56b3 Mon Sep 17 00:00:00 2001 From: Liam Cervante Date: Wed, 31 Jan 2024 14:54:59 +0100 Subject: [PATCH] Add 'explicit configuration required' message when provider schema validation fails (#34595) --- internal/terraform/node_provider.go | 10 +++++ internal/terraform/node_provider_test.go | 53 +++++++++++++++++++++++- 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/internal/terraform/node_provider.go b/internal/terraform/node_provider.go index 5470e92b669f..3e14637b7140 100644 --- a/internal/terraform/node_provider.go +++ b/internal/terraform/node_provider.go @@ -115,6 +115,16 @@ func (n *NodeApplyableProvider) ConfigureProvider(ctx EvalContext, provider prov configVal, configBody, evalDiags := ctx.EvaluateBlock(configBody, configSchema, nil, EvalDataForNoInstanceKey) diags = diags.Append(evalDiags) if evalDiags.HasErrors() { + if config == nil { + // The error messages from the above evaluation will be confusing + // if there isn't an explicit "provider" block in the configuration. + // Add some detail to the error message in this case. + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Invalid provider configuration", + fmt.Sprintf(providerConfigErr, n.Addr.Provider), + )) + } return diags } diff --git a/internal/terraform/node_provider_test.go b/internal/terraform/node_provider_test.go index fc07ae3f7ec4..9af24038345f 100644 --- a/internal/terraform/node_provider_test.go +++ b/internal/terraform/node_provider_test.go @@ -9,13 +9,14 @@ import ( "testing" "github.com/hashicorp/hcl/v2" + "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" "github.com/hashicorp/terraform/internal/lang/marks" "github.com/hashicorp/terraform/internal/providers" "github.com/hashicorp/terraform/internal/tfdiags" - "github.com/zclconf/go-cty/cty" ) func TestNodeApplyableProviderExecute(t *testing.T) { @@ -349,6 +350,19 @@ func TestNodeApplyableProvider_ConfigProvider(t *testing.T) { } return } + + // requiredProvider matches provider, but its attributes are required + // explicitly. This means we can simulate an earlier failure in the + // config validation. + requiredProvider := mockProviderWithConfigSchema(&configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "region": { + Type: cty.String, + Required: true, + }, + }, + }) + ctx := &MockEvalContext{ProviderProvider: provider} ctx.installSimpleEval() @@ -410,6 +424,43 @@ func TestNodeApplyableProvider_ConfigProvider(t *testing.T) { } }) + t.Run("missing schema-required config (no config at all)", func(t *testing.T) { + node := NodeApplyableProvider{ + NodeAbstractProvider: &NodeAbstractProvider{ + Addr: mustProviderConfig(`provider["registry.terraform.io/hashicorp/aws"]`), + }, + } + + diags := node.ConfigureProvider(ctx, requiredProvider, false) + if !diags.HasErrors() { + t.Fatal("missing expected error with nil config") + } + if !strings.Contains(diags.Err().Error(), "requires explicit configuration") { + t.Errorf("diagnostic is missing \"requires explicit configuration\" message: %s", diags.Err()) + } + }) + + t.Run("missing schema-required config", func(t *testing.T) { + config := &configs.Provider{ + Name: "test", + Config: hcl.EmptyBody(), + } + node := NodeApplyableProvider{ + NodeAbstractProvider: &NodeAbstractProvider{ + Addr: mustProviderConfig(`provider["registry.terraform.io/hashicorp/aws"]`), + Config: config, + }, + } + + diags := node.ConfigureProvider(ctx, requiredProvider, false) + if !diags.HasErrors() { + t.Fatal("missing expected error with invalid config") + } + if !strings.Contains(diags.Err().Error(), "The argument \"region\" is required, but was not set.") { + t.Errorf("wrong diagnostic: %s", diags.Err()) + } + }) + } // This test is similar to TestNodeApplyableProvider_ConfigProvider, but tests responses from the providers.ConfigureProviderRequest