blob: 1ee7a697a126bb77dee246c9ef9dac19ea0faa44 [file] [log] [blame] [edit]
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package graph
import (
"log"
"github.com/hashicorp/terraform/internal/addrs"
"github.com/hashicorp/terraform/internal/backend/backendrun"
"github.com/hashicorp/terraform/internal/moduletest"
"github.com/hashicorp/terraform/internal/terraform"
"github.com/hashicorp/terraform/internal/tfdiags"
)
// TestGraphBuilder is a GraphBuilder implementation that builds a graph for
// a terraform test file. The file may contain multiple runs, and each run may have
// dependencies on other runs.
type TestGraphBuilder struct {
File *moduletest.File
GlobalVars map[string]backendrun.UnparsedVariableValue
ContextOpts *terraform.ContextOpts
}
type graphOptions struct {
File *moduletest.File
GlobalVars map[string]backendrun.UnparsedVariableValue
ContextOpts *terraform.ContextOpts
}
// See GraphBuilder
func (b *TestGraphBuilder) Build() (*terraform.Graph, tfdiags.Diagnostics) {
log.Printf("[TRACE] building graph for terraform test")
return (&terraform.BasicGraphBuilder{
Steps: b.Steps(),
Name: "TestGraphBuilder",
}).Build(addrs.RootModuleInstance)
}
// See GraphBuilder
func (b *TestGraphBuilder) Steps() []terraform.GraphTransformer {
opts := &graphOptions{
File: b.File,
GlobalVars: b.GlobalVars,
ContextOpts: b.ContextOpts,
}
steps := []terraform.GraphTransformer{
&TestRunTransformer{opts},
&TestConfigTransformer{File: b.File},
&TestStateCleanupTransformer{opts},
terraform.DynamicTransformer(validateRunConfigs),
&TestProvidersTransformer{},
&CloseTestGraphTransformer{},
&terraform.TransitiveReductionTransformer{},
}
return steps
}
func validateRunConfigs(g *terraform.Graph) error {
for _, v := range g.Vertices() {
if node, ok := v.(*NodeTestRun); ok {
diags := node.run.Config.Validate(node.run.ModuleConfig)
node.run.Diagnostics = node.run.Diagnostics.Append(diags)
if diags.HasErrors() {
node.run.Status = moduletest.Error
}
}
}
return nil
}
// dynamicNode is a helper node which can be added to the graph to execute
// a dynamic function at some desired point in the graph.
type dynamicNode struct {
eval func(*EvalContext) tfdiags.Diagnostics
}
func (n *dynamicNode) Execute(evalCtx *EvalContext) tfdiags.Diagnostics {
return n.eval(evalCtx)
}