From ab9a7f4d72e9f88436e4f00ae0a774c0c91d7bc6 Mon Sep 17 00:00:00 2001 From: Andrei Ciobanu Date: Wed, 29 Jan 2025 10:50:45 +0200 Subject: [PATCH] Fix error message when default value of variable is of wrong type (#2444) Signed-off-by: yottta --- internal/configs/named_values.go | 3 ++- internal/configs/parser_config_test.go | 19 ++++++++++++++++++- .../variable-complex-bad-default-inner-obj.tf | 15 +++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 internal/configs/testdata/invalid-files/variable-complex-bad-default-inner-obj.tf diff --git a/internal/configs/named_values.go b/internal/configs/named_values.go index 7a79a2c021..b27a25244f 100644 --- a/internal/configs/named_values.go +++ b/internal/configs/named_values.go @@ -12,6 +12,7 @@ import ( "github.com/hashicorp/hcl/v2/ext/typeexpr" "github.com/hashicorp/hcl/v2/gohcl" "github.com/hashicorp/hcl/v2/hclsyntax" + "github.com/opentofu/opentofu/internal/tfdiags" "github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty/convert" @@ -157,7 +158,7 @@ func decodeVariableBlock(block *hcl.Block, override bool) (*Variable, hcl.Diagno diags = append(diags, &hcl.Diagnostic{ Severity: hcl.DiagError, Summary: "Invalid default value for variable", - Detail: fmt.Sprintf("This default value is not compatible with the variable's type constraint: %s.", err), + Detail: fmt.Sprintf("This default value is not compatible with the variable's type constraint: %s.", tfdiags.FormatError(err)), Subject: attr.Expr.Range().Ptr(), }) val = cty.DynamicVal diff --git a/internal/configs/parser_config_test.go b/internal/configs/parser_config_test.go index 0abe072823..624c163913 100644 --- a/internal/configs/parser_config_test.go +++ b/internal/configs/parser_config_test.go @@ -92,47 +92,61 @@ func TestParserLoadConfigFileFailure(t *testing.T) { // This test uses a subset of the same fixture files as // TestParserLoadConfigFileFailure, but additionally verifies that each -// file produces the expected diagnostic summary. +// file produces the expected diagnostic summary and detail. func TestParserLoadConfigFileFailureMessages(t *testing.T) { tests := []struct { Filename string WantSeverity hcl.DiagnosticSeverity WantDiag string + WantDetail string }{ { "invalid-files/data-resource-lifecycle.tf", hcl.DiagError, "Invalid data resource lifecycle argument", + `The lifecycle argument "ignore_changes" is defined only for managed resources ("resource" blocks), and is not valid for data resources.`, }, { "invalid-files/variable-type-unknown.tf", hcl.DiagError, "Invalid type specification", + `The keyword "notatype" is not a valid type specification.`, }, { "invalid-files/unexpected-attr.tf", hcl.DiagError, "Unsupported argument", + `An argument named "foo" is not expected here.`, }, { "invalid-files/unexpected-block.tf", hcl.DiagError, "Unsupported block type", + `Blocks of type "varyable" are not expected here. Did you mean "variable"?`, }, { "invalid-files/resource-count-and-for_each.tf", hcl.DiagError, `Invalid combination of "count" and "for_each"`, + `The "count" and "for_each" meta-arguments are mutually-exclusive, only one should be used to be explicit about the number of resources to be created.`, }, { "invalid-files/data-count-and-for_each.tf", hcl.DiagError, `Invalid combination of "count" and "for_each"`, + `The "count" and "for_each" meta-arguments are mutually-exclusive, only one should be used to be explicit about the number of resources to be created.`, }, { "invalid-files/resource-lifecycle-badbool.tf", hcl.DiagError, "Unsuitable value type", + `Unsuitable value: a bool is required`, + }, + { + "invalid-files/variable-complex-bad-default-inner-obj.tf", + hcl.DiagError, + "Invalid default value for variable", + `This default value is not compatible with the variable's type constraint: ["mykey"].field: a bool is required.`, }, } @@ -161,6 +175,9 @@ func TestParserLoadConfigFileFailureMessages(t *testing.T) { if diags[0].Summary != test.WantDiag { t.Errorf("Wrong diagnostic summary\ngot: %s\nwant: %s", diags[0].Summary, test.WantDiag) } + if diags[0].Detail != test.WantDetail { + t.Errorf("Wrong diagnostic detail\ngot: %s\nwant: %s", diags[0].Detail, test.WantDetail) + } }) } } diff --git a/internal/configs/testdata/invalid-files/variable-complex-bad-default-inner-obj.tf b/internal/configs/testdata/invalid-files/variable-complex-bad-default-inner-obj.tf new file mode 100644 index 0000000000..053543f2cd --- /dev/null +++ b/internal/configs/testdata/invalid-files/variable-complex-bad-default-inner-obj.tf @@ -0,0 +1,15 @@ +// https://github.com/opentofu/opentofu/issues/2394 +// This validates the returned error message when the default value +// inner field type does not match the definition of the variable +variable "bad_type_for_inner_field" { + type = map(object({ + field = bool + })) + + default = { + "mykey" = { + field = "not a bool" + dont = "mind me" + } + } +} \ No newline at end of file