| // Copyright IBM Corp. 2014, 2026 | |
| // SPDX-License-Identifier: BUSL-1.1 | |
| package graph | |
| import ( | |
| "fmt" | |
| "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/lang/langrefs" | |
| "github.com/hashicorp/terraform/internal/moduletest" | |
| "github.com/hashicorp/terraform/internal/terraform" | |
| "github.com/hashicorp/terraform/internal/tfdiags" | |
| ) | |
| type TestInputValue struct { | |
| Value *terraform.InputValue | |
| } | |
| var ( | |
| _ GraphNodeExecutable = (*NodeVariableDefinition)(nil) | |
| _ GraphNodeReferenceable = (*NodeVariableDefinition)(nil) | |
| ) | |
| type NodeVariableDefinition struct { | |
| Address string | |
| Config *configs.Variable | |
| File *moduletest.File | |
| } | |
| func (n *NodeVariableDefinition) Name() string { | |
| return fmt.Sprintf("var.%s", n.Address) | |
| } | |
| func (n *NodeVariableDefinition) Referenceable() addrs.Referenceable { | |
| return &addrs.InputVariable{Name: n.Address} | |
| } | |
| func (n *NodeVariableDefinition) Execute(ctx *EvalContext) { | |
| if ctx.Stopped() || ctx.Cancelled() { | |
| return // don't evaluate anything when stopped or cancelled | |
| } | |
| input, diags := ctx.EvaluateUnparsedVariable(n.Address, n.Config) | |
| if input != nil { | |
| n.File.AppendDiagnostics(diags) | |
| if diags.HasErrors() { | |
| ctx.SetVariableStatus(n.Address, moduletest.Error) | |
| return | |
| } | |
| } else { | |
| input = &terraform.InputValue{ | |
| Value: cty.NilVal, | |
| } | |
| } | |
| value, diags := terraform.PrepareFinalInputVariableValue(addrs.AbsInputVariableInstance{ | |
| Module: addrs.RootModuleInstance, | |
| Variable: addrs.InputVariable{ | |
| Name: n.Address, | |
| }, | |
| }, input, n.Config) | |
| n.File.AppendDiagnostics(diags) | |
| if diags.HasErrors() { | |
| ctx.SetVariableStatus(n.Address, moduletest.Error) | |
| return | |
| } | |
| ctx.SetVariable(n.Address, &terraform.InputValue{ | |
| Value: value, | |
| SourceType: terraform.ValueFromConfig, | |
| SourceRange: tfdiags.SourceRangeFromHCL(n.Config.DeclRange), | |
| }) | |
| } | |
| var ( | |
| _ GraphNodeExecutable = (*NodeVariableExpression)(nil) | |
| _ GraphNodeReferencer = (*NodeVariableExpression)(nil) | |
| _ GraphNodeReferenceable = (*NodeVariableExpression)(nil) | |
| ) | |
| type NodeVariableExpression struct { | |
| Address string | |
| Expr hcl.Expression | |
| File *moduletest.File | |
| } | |
| func (n *NodeVariableExpression) Name() string { | |
| return fmt.Sprintf("var.%s", n.Address) | |
| } | |
| func (n *NodeVariableExpression) Referenceable() addrs.Referenceable { | |
| return &addrs.InputVariable{Name: n.Address} | |
| } | |
| func (n *NodeVariableExpression) References() []*addrs.Reference { | |
| refs, _ := langrefs.ReferencesInExpr(addrs.ParseRefFromTestingScope, n.Expr) | |
| return refs | |
| } | |
| func (n *NodeVariableExpression) Execute(ctx *EvalContext) { | |
| refs, refDiags := langrefs.ReferencesInExpr(addrs.ParseRefFromTestingScope, n.Expr) | |
| if !ctx.ReferencesCompleted(refs) { | |
| // before we do anything with the diags, we're going to check that all | |
| // of the references we know about were successfully parsed. If not, | |
| // then we'll skip actually assessing this node. | |
| ctx.SetVariableStatus(n.Address, moduletest.Skip) | |
| return | |
| } | |
| if ctx.Stopped() || ctx.Cancelled() { | |
| return // don't evaluate anything when stopped or cancelled | |
| } | |
| n.File.AppendDiagnostics(refDiags) | |
| if refDiags.HasErrors() { | |
| ctx.SetVariableStatus(n.Address, moduletest.Error) | |
| return | |
| } | |
| evalContext, moreDiags := ctx.HclContext(refs) | |
| n.File.AppendDiagnostics(moreDiags) | |
| if moreDiags.HasErrors() { | |
| ctx.SetVariableStatus(n.Address, moduletest.Error) | |
| return | |
| } | |
| var diags tfdiags.Diagnostics | |
| value, valueDiags := n.Expr.Value(evalContext) | |
| n.File.AppendDiagnostics(diags.Append(valueDiags)) | |
| if valueDiags.HasErrors() { | |
| ctx.SetVariableStatus(n.Address, moduletest.Error) | |
| return | |
| } | |
| ctx.SetVariable(n.Address, &terraform.InputValue{ | |
| Value: value, | |
| SourceType: terraform.ValueFromConfig, | |
| SourceRange: tfdiags.SourceRangeFromHCL(n.Expr.Range()), | |
| }) | |
| } |