github.com/hashicorp/terraform-plugin-sdk@v1.17.2/terraform/graph_builder.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strings"
     7  
     8  	"github.com/hashicorp/terraform-plugin-sdk/internal/tfdiags"
     9  
    10  	"github.com/hashicorp/terraform-plugin-sdk/internal/addrs"
    11  )
    12  
    13  // GraphBuilder is an interface that can be implemented and used with
    14  // Terraform to build the graph that Terraform walks.
    15  type GraphBuilder interface {
    16  	// Build builds the graph for the given module path. It is up to
    17  	// the interface implementation whether this build should expand
    18  	// the graph or not.
    19  	Build(addrs.ModuleInstance) (*Graph, tfdiags.Diagnostics)
    20  }
    21  
    22  // BasicGraphBuilder is a GraphBuilder that builds a graph out of a
    23  // series of transforms and (optionally) validates the graph is a valid
    24  // structure.
    25  type BasicGraphBuilder struct {
    26  	Steps    []GraphTransformer
    27  	Validate bool
    28  	// Optional name to add to the graph debug log
    29  	Name string
    30  }
    31  
    32  func (b *BasicGraphBuilder) Build(path addrs.ModuleInstance) (*Graph, tfdiags.Diagnostics) {
    33  	var diags tfdiags.Diagnostics
    34  	g := &Graph{Path: path}
    35  
    36  	var lastStepStr string
    37  	for _, step := range b.Steps {
    38  		if step == nil {
    39  			continue
    40  		}
    41  		log.Printf("[TRACE] Executing graph transform %T", step)
    42  
    43  		stepName := fmt.Sprintf("%T", step)
    44  		dot := strings.LastIndex(stepName, ".")
    45  		if dot >= 0 {
    46  			stepName = stepName[dot+1:]
    47  		}
    48  
    49  		debugOp := g.DebugOperation(stepName, "")
    50  		err := step.Transform(g)
    51  
    52  		errMsg := ""
    53  		if err != nil {
    54  			errMsg = err.Error()
    55  		}
    56  		debugOp.End(errMsg)
    57  
    58  		if thisStepStr := g.StringWithNodeTypes(); thisStepStr != lastStepStr {
    59  			log.Printf("[TRACE] Completed graph transform %T with new graph:\n%s------", step, thisStepStr)
    60  			lastStepStr = thisStepStr
    61  		} else {
    62  			log.Printf("[TRACE] Completed graph transform %T (no changes)", step)
    63  		}
    64  
    65  		if err != nil {
    66  			if nf, isNF := err.(tfdiags.NonFatalError); isNF {
    67  				diags = diags.Append(nf.Diagnostics)
    68  			} else {
    69  				diags = diags.Append(err)
    70  				return g, diags
    71  			}
    72  		}
    73  	}
    74  
    75  	// Validate the graph structure
    76  	if b.Validate {
    77  		if err := g.Validate(); err != nil {
    78  			log.Printf("[ERROR] Graph validation failed. Graph:\n\n%s", g.String())
    79  			diags = diags.Append(err)
    80  			return nil, diags
    81  		}
    82  	}
    83  
    84  	return g, diags
    85  }