blob: 990cfa2b1a4604524494f92e03a40606550b246c [file] [log] [blame]
// Copyright (c) HashiCorp, Inc.
// 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()),
})
}