summaryrefslogtreecommitdiff
path: root/vendor/github.com/hashicorp/terraform/terraform/graph_builder.go
blob: 6374bb90450ab0529c678b74451030bf0c3b4d17 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package terraform

import (
	"fmt"
	"log"
	"strings"
)

// GraphBuilder is an interface that can be implemented and used with
// Terraform to build the graph that Terraform walks.
type GraphBuilder interface {
	// Build builds the graph for the given module path. It is up to
	// the interface implementation whether this build should expand
	// the graph or not.
	Build(path []string) (*Graph, error)
}

// BasicGraphBuilder is a GraphBuilder that builds a graph out of a
// series of transforms and (optionally) validates the graph is a valid
// structure.
type BasicGraphBuilder struct {
	Steps    []GraphTransformer
	Validate bool
	// Optional name to add to the graph debug log
	Name string
}

func (b *BasicGraphBuilder) Build(path []string) (*Graph, error) {
	g := &Graph{Path: path}

	debugName := "graph.json"
	if b.Name != "" {
		debugName = b.Name + "-" + debugName
	}
	debugBuf := dbug.NewFileWriter(debugName)
	g.SetDebugWriter(debugBuf)
	defer debugBuf.Close()

	for _, step := range b.Steps {
		if step == nil {
			continue
		}

		stepName := fmt.Sprintf("%T", step)
		dot := strings.LastIndex(stepName, ".")
		if dot >= 0 {
			stepName = stepName[dot+1:]
		}

		debugOp := g.DebugOperation(stepName, "")
		err := step.Transform(g)

		errMsg := ""
		if err != nil {
			errMsg = err.Error()
		}
		debugOp.End(errMsg)

		log.Printf(
			"[TRACE] Graph after step %T:\n\n%s",
			step, g.StringWithNodeTypes())

		if err != nil {
			return g, err
		}
	}

	// Validate the graph structure
	if b.Validate {
		if err := g.Validate(); err != nil {
			log.Printf("[ERROR] Graph validation failed. Graph:\n\n%s", g.String())
			return nil, err
		}
	}

	return g, nil
}