Skip to content

Commit

Permalink
terraform test: Fix crash when file level variables reference variabl…
Browse files Browse the repository at this point in the history
…es. (#34531)

* terraform test: Fix crash when referencing variables within the file level variable block

* also allow functions within variables blocks

* add tests
  • Loading branch information
liamcervante authored Jan 22, 2024
1 parent 0994e6f commit 430970c
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 6 deletions.
5 changes: 4 additions & 1 deletion internal/backend/local/backend_local.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/hashicorp/terraform/internal/backend"
"github.com/hashicorp/terraform/internal/configs"
"github.com/hashicorp/terraform/internal/configs/configload"
"github.com/hashicorp/terraform/internal/lang"
"github.com/hashicorp/terraform/internal/plans/planfile"
"github.com/hashicorp/terraform/internal/states/statemgr"
"github.com/hashicorp/terraform/internal/terraform"
Expand Down Expand Up @@ -516,7 +517,9 @@ var _ backend.UnparsedVariableValue = unparsedTestVariableValue{}
func (v unparsedTestVariableValue) ParseVariableValue(mode configs.VariableParsingMode) (*terraform.InputValue, tfdiags.Diagnostics) {
var diags tfdiags.Diagnostics

value, valueDiags := v.Expr.Value(nil)
value, valueDiags := v.Expr.Value(&hcl.EvalContext{
Functions: lang.TestingFunctions(),
})
diags = diags.Append(valueDiags)
if valueDiags.HasErrors() {
return nil, diags
Expand Down
19 changes: 16 additions & 3 deletions internal/backend/local/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1023,7 +1023,7 @@ func (runner *TestFileRunner) GetVariables(config *configs.Config, run *modulete
values := make(terraform.InputValues)

// First, let's look at the global variables.
for name, value := range runner.globalVariables {
for name, variable := range runner.globalVariables {
if !relevantVariables[name] {
// Then this run block doesn't need this value.
continue
Expand All @@ -1039,9 +1039,22 @@ func (runner *TestFileRunner) GetVariables(config *configs.Config, run *modulete
parsingMode = cfg.ParsingMode
}

var valueDiags tfdiags.Diagnostics
values[name], valueDiags = value.ParseVariableValue(parsingMode)
value, valueDiags := variable.ParseVariableValue(parsingMode)
diags = diags.Append(valueDiags)
if diags.HasErrors() {
// We still add a value for this variable even though we couldn't
// parse it as we don't want to compound errors later. For example,
// the system would report this variable didn't have a value which
// would confuse the user because it does have a value, it's just
// not a valid value. We have added the diagnostics so the user
// will be informed about the error, and the test won't run. We'll
// just report only the relevant errors.
values[name] = &terraform.InputValue{
Value: cty.NilVal,
}
continue
}
values[name] = value
}

// Second, we'll check the run level variables.
Expand Down
9 changes: 7 additions & 2 deletions internal/command/test_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ func TestTest_Runs(t *testing.T) {
code: 0,
},
"functions_available": {
expectedOut: "1 passed, 0 failed.",
expectedOut: "2 passed, 0 failed.",
code: 0,
},
"mocking": {
Expand All @@ -227,6 +227,11 @@ func TestTest_Runs(t *testing.T) {
expectedOut: "1 passed, 0 failed.",
code: 0,
},
"global_var_refs": {
expectedOut: "2 failed, 1 skipped.",
expectedErr: "Variables may not be used here.",
code: 1,
},
}
for name, tc := range tcs {
t.Run(name, func(t *testing.T) {
Expand Down Expand Up @@ -281,7 +286,7 @@ func TestTest_Runs(t *testing.T) {
}

if !strings.Contains(output.Stdout(), tc.expectedOut) {
t.Errorf("output didn't contain expected string:\n\n%s", output.All())
t.Errorf("output didn't contain expected string:\n\n%s", output.Stdout())
}

if !strings.Contains(output.Stderr(), tc.expectedErr) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
variables {
input = jsonencode({key:"value"})
}

run "test" {
assert {
condition = jsondecode(test_resource.resource.value).key == "value"
error_message = "wrong value"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

variables {
input = var.env_var_input
}

run "execute" {}
7 changes: 7 additions & 0 deletions internal/command/testdata/test/global_var_refs/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
variable "input" {
type = string
}

output "value" {
value = var.input
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

variables {
input = var.setup.value
}

run "setup" {
variables {
input = "hello"
}
}

run "execute" {
assert {
condition = output.value == "hello"
error_message = "bad output value"
}
}

0 comments on commit 430970c

Please sign in to comment.