From 684ed7505d7aaa85d3eb4460d0ae7aec17b99aa8 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Mon, 10 Jan 2022 16:14:30 -0500 Subject: [PATCH] remove synthetic default expression for variables Now that variable evaluation checks for a nil expression the graph transformer does not need to generate a synthetic expression for variable defaults. This means that all default handling is now located in one place, and we are not surprised by a configuration expression showing up which doesn't actually exist in the configuration. Rename nodeModuleVariable.evalModuleCallArgument to evalModuleVariable. This method is no longer handling only the module call argument, it is also dealing with the variable declaration defaults and validation statements. Add an additional tests for validation with a non-nullable variable. --- internal/terraform/context_validate_test.go | 33 +++++++++++++++++++ internal/terraform/node_module_variable.go | 8 ++--- .../terraform/transform_module_variable.go | 8 ----- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/internal/terraform/context_validate_test.go b/internal/terraform/context_validate_test.go index a02d85cdd..1f0491f1a 100644 --- a/internal/terraform/context_validate_test.go +++ b/internal/terraform/context_validate_test.go @@ -2062,3 +2062,36 @@ output "out" { t.Fatal(diags.ErrWithWarnings()) } } + +func TestContext2Validate_nonNullableVariableDefaultValidation(t *testing.T) { + m := testModuleInline(t, map[string]string{ + "main.tf": ` + module "first" { + source = "./mod" + input = null + } + `, + + "mod/main.tf": ` + variable "input" { + type = string + default = "default" + nullable = false + + // Validation expressions should receive the default with nullable=false and + // a null input. + validation { + condition = var.input != null + error_message = "Input cannot be null!" + } + } + `, + }) + + ctx := testContext2(t, &ContextOpts{}) + + diags := ctx.Validate(m) + if diags.HasErrors() { + t.Fatal(diags.ErrWithWarnings()) + } +} diff --git a/internal/terraform/node_module_variable.go b/internal/terraform/node_module_variable.go index ae3450be5..c5e2294ea 100644 --- a/internal/terraform/node_module_variable.go +++ b/internal/terraform/node_module_variable.go @@ -149,10 +149,10 @@ func (n *nodeModuleVariable) Execute(ctx EvalContext, op walkOperation) (diags t switch op { case walkValidate: - val, err = n.evalModuleCallArgument(ctx, true) + val, err = n.evalModuleVariable(ctx, true) diags = diags.Append(err) default: - val, err = n.evalModuleCallArgument(ctx, false) + val, err = n.evalModuleVariable(ctx, false) diags = diags.Append(err) } if diags.HasErrors() { @@ -178,7 +178,7 @@ func (n *nodeModuleVariable) DotNode(name string, opts *dag.DotOpts) *dag.DotNod } } -// evalModuleCallArgument produces the value for a particular variable as will +// evalModuleVariable produces the value for a particular variable as will // be used by a child module instance. // // The result is written into a map, with its key set to the local name of the @@ -190,7 +190,7 @@ func (n *nodeModuleVariable) DotNode(name string, opts *dag.DotOpts) *dag.DotNod // validateOnly indicates that this evaluation is only for config // validation, and we will not have any expansion module instance // repetition data. -func (n *nodeModuleVariable) evalModuleCallArgument(ctx EvalContext, validateOnly bool) (cty.Value, error) { +func (n *nodeModuleVariable) evalModuleVariable(ctx EvalContext, validateOnly bool) (cty.Value, error) { var diags tfdiags.Diagnostics var givenVal cty.Value var errSourceRange tfdiags.SourceRange diff --git a/internal/terraform/transform_module_variable.go b/internal/terraform/transform_module_variable.go index b739bfd6e..a9fa02c4e 100644 --- a/internal/terraform/transform_module_variable.go +++ b/internal/terraform/transform_module_variable.go @@ -3,7 +3,6 @@ package terraform import ( "fmt" - "github.com/hashicorp/hcl/v2/hclsyntax" "github.com/hashicorp/terraform/internal/addrs" "github.com/hashicorp/terraform/internal/tfdiags" "github.com/zclconf/go-cty/cty" @@ -94,13 +93,6 @@ func (t *ModuleVariableTransformer) transformSingle(g *Graph, parent, c *configs var expr hcl.Expression if attr := content.Attributes[v.Name]; attr != nil { expr = attr.Expr - } else { - // No expression provided for this variable, so we'll make a - // synthetic one using the variable's default value. - expr = &hclsyntax.LiteralValueExpr{ - Val: v.Default, - SrcRange: v.DeclRange, // This is not exact, but close enough - } } // Add a plannable node, as the variable may expand