Skip to content

Commit 430970c

Browse files
author
Liam Cervante
authored
terraform test: Fix crash when file level variables reference variables. (#34531)
* terraform test: Fix crash when referencing variables within the file level variable block * also allow functions within variables blocks * add tests
1 parent 0994e6f commit 430970c

File tree

7 files changed

+67
-6
lines changed

7 files changed

+67
-6
lines changed

internal/backend/local/backend_local.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/hashicorp/terraform/internal/backend"
1717
"github.com/hashicorp/terraform/internal/configs"
1818
"github.com/hashicorp/terraform/internal/configs/configload"
19+
"github.com/hashicorp/terraform/internal/lang"
1920
"github.com/hashicorp/terraform/internal/plans/planfile"
2021
"github.com/hashicorp/terraform/internal/states/statemgr"
2122
"github.com/hashicorp/terraform/internal/terraform"
@@ -516,7 +517,9 @@ var _ backend.UnparsedVariableValue = unparsedTestVariableValue{}
516517
func (v unparsedTestVariableValue) ParseVariableValue(mode configs.VariableParsingMode) (*terraform.InputValue, tfdiags.Diagnostics) {
517518
var diags tfdiags.Diagnostics
518519

519-
value, valueDiags := v.Expr.Value(nil)
520+
value, valueDiags := v.Expr.Value(&hcl.EvalContext{
521+
Functions: lang.TestingFunctions(),
522+
})
520523
diags = diags.Append(valueDiags)
521524
if valueDiags.HasErrors() {
522525
return nil, diags

internal/backend/local/test.go

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,7 +1023,7 @@ func (runner *TestFileRunner) GetVariables(config *configs.Config, run *modulete
10231023
values := make(terraform.InputValues)
10241024

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

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

10471060
// Second, we'll check the run level variables.

internal/command/test_test.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ func TestTest_Runs(t *testing.T) {
208208
code: 0,
209209
},
210210
"functions_available": {
211-
expectedOut: "1 passed, 0 failed.",
211+
expectedOut: "2 passed, 0 failed.",
212212
code: 0,
213213
},
214214
"mocking": {
@@ -227,6 +227,11 @@ func TestTest_Runs(t *testing.T) {
227227
expectedOut: "1 passed, 0 failed.",
228228
code: 0,
229229
},
230+
"global_var_refs": {
231+
expectedOut: "2 failed, 1 skipped.",
232+
expectedErr: "Variables may not be used here.",
233+
code: 1,
234+
},
230235
}
231236
for name, tc := range tcs {
232237
t.Run(name, func(t *testing.T) {
@@ -281,7 +286,7 @@ func TestTest_Runs(t *testing.T) {
281286
}
282287

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

287292
if !strings.Contains(output.Stderr(), tc.expectedErr) {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
variables {
2+
input = jsonencode({key:"value"})
3+
}
4+
5+
run "test" {
6+
assert {
7+
condition = jsondecode(test_resource.resource.value).key == "value"
8+
error_message = "wrong value"
9+
}
10+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
variables {
3+
input = var.env_var_input
4+
}
5+
6+
run "execute" {}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
variable "input" {
2+
type = string
3+
}
4+
5+
output "value" {
6+
value = var.input
7+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
2+
variables {
3+
input = var.setup.value
4+
}
5+
6+
run "setup" {
7+
variables {
8+
input = "hello"
9+
}
10+
}
11+
12+
run "execute" {
13+
assert {
14+
condition = output.value == "hello"
15+
error_message = "bad output value"
16+
}
17+
}

0 commit comments

Comments
 (0)