github.com/opentofu/opentofu@v1.7.1/internal/tofu/graph_builder.go (about) 1 // Copyright (c) The OpenTofu Authors 2 // SPDX-License-Identifier: MPL-2.0 3 // Copyright (c) 2023 HashiCorp, Inc. 4 // SPDX-License-Identifier: MPL-2.0 5 6 package tofu 7 8 import ( 9 "log" 10 11 "github.com/opentofu/opentofu/internal/addrs" 12 "github.com/opentofu/opentofu/internal/logging" 13 "github.com/opentofu/opentofu/internal/tfdiags" 14 ) 15 16 // GraphBuilder is an interface that can be implemented and used with 17 // OpenTofu to build the graph that OpenTofu walks. 18 type GraphBuilder interface { 19 // Build builds the graph for the given module path. It is up to 20 // the interface implementation whether this build should expand 21 // the graph or not. 22 Build(addrs.ModuleInstance) (*Graph, tfdiags.Diagnostics) 23 } 24 25 // BasicGraphBuilder is a GraphBuilder that builds a graph out of a 26 // series of transforms and (optionally) validates the graph is a valid 27 // structure. 28 type BasicGraphBuilder struct { 29 Steps []GraphTransformer 30 // Optional name to add to the graph debug log 31 Name string 32 } 33 34 func (b *BasicGraphBuilder) Build(path addrs.ModuleInstance) (*Graph, tfdiags.Diagnostics) { 35 var diags tfdiags.Diagnostics 36 g := &Graph{Path: path} 37 38 var lastStepStr string 39 for _, step := range b.Steps { 40 if step == nil { 41 continue 42 } 43 log.Printf("[TRACE] Executing graph transform %T", step) 44 45 err := step.Transform(g) 46 if thisStepStr := g.StringWithNodeTypes(); thisStepStr != lastStepStr { 47 log.Printf("[TRACE] Completed graph transform %T with new graph:\n%s ------", step, logging.Indent(thisStepStr)) 48 lastStepStr = thisStepStr 49 } else { 50 log.Printf("[TRACE] Completed graph transform %T (no changes)", step) 51 } 52 53 if err != nil { 54 if nf, isNF := err.(tfdiags.NonFatalError); isNF { 55 diags = diags.Append(nf.Diagnostics) 56 } else { 57 diags = diags.Append(err) 58 return g, diags 59 } 60 } 61 } 62 63 if err := g.Validate(); err != nil { 64 log.Printf("[ERROR] Graph validation failed. Graph:\n\n%s", g.String()) 65 diags = diags.Append(err) 66 return nil, diags 67 } 68 69 return g, diags 70 }