]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - vendor/github.com/hashicorp/terraform/terraform/transform_config.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / terraform / transform_config.go
CommitLineData
bae9f6d2
JC
1package terraform
2
3import (
bae9f6d2
JC
4 "log"
5 "sync"
6
107c1cdb
ND
7 "github.com/hashicorp/terraform/addrs"
8 "github.com/hashicorp/terraform/configs"
bae9f6d2
JC
9 "github.com/hashicorp/terraform/dag"
10)
11
12// ConfigTransformer is a GraphTransformer that adds all the resources
13// from the configuration to the graph.
14//
15// The module used to configure this transformer must be the root module.
16//
17// Only resources are added to the graph. Variables, outputs, and
18// providers must be added via other transforms.
19//
20// Unlike ConfigTransformerOld, this transformer creates a graph with
21// all resources including module resources, rather than creating module
22// nodes that are then "flattened".
23type ConfigTransformer struct {
24 Concrete ConcreteResourceNodeFunc
25
26 // Module is the module to add resources from.
107c1cdb 27 Config *configs.Config
bae9f6d2
JC
28
29 // Unique will only add resources that aren't already present in the graph.
30 Unique bool
31
32 // Mode will only add resources that match the given mode
33 ModeFilter bool
107c1cdb 34 Mode addrs.ResourceMode
bae9f6d2
JC
35
36 l sync.Mutex
37 uniqueMap map[string]struct{}
38}
39
40func (t *ConfigTransformer) Transform(g *Graph) error {
41 // Lock since we use some internal state
42 t.l.Lock()
43 defer t.l.Unlock()
44
107c1cdb
ND
45 // If no configuration is available, we don't do anything
46 if t.Config == nil {
bae9f6d2
JC
47 return nil
48 }
49
bae9f6d2
JC
50 // Reset the uniqueness map. If we're tracking uniques, then populate
51 // it with addresses.
52 t.uniqueMap = make(map[string]struct{})
53 defer func() { t.uniqueMap = nil }()
54 if t.Unique {
55 for _, v := range g.Vertices() {
56 if rn, ok := v.(GraphNodeResource); ok {
57 t.uniqueMap[rn.ResourceAddr().String()] = struct{}{}
58 }
59 }
60 }
61
62 // Start the transformation process
107c1cdb 63 return t.transform(g, t.Config)
bae9f6d2
JC
64}
65
107c1cdb 66func (t *ConfigTransformer) transform(g *Graph, config *configs.Config) error {
bae9f6d2 67 // If no config, do nothing
107c1cdb 68 if config == nil {
bae9f6d2
JC
69 return nil
70 }
71
72 // Add our resources
107c1cdb 73 if err := t.transformSingle(g, config); err != nil {
bae9f6d2
JC
74 return err
75 }
76
77 // Transform all the children.
107c1cdb 78 for _, c := range config.Children {
bae9f6d2
JC
79 if err := t.transform(g, c); err != nil {
80 return err
81 }
82 }
83
84 return nil
85}
86
107c1cdb
ND
87func (t *ConfigTransformer) transformSingle(g *Graph, config *configs.Config) error {
88 path := config.Path
89 module := config.Module
90 log.Printf("[TRACE] ConfigTransformer: Starting for path: %v", path)
91
92 // For now we assume that each module call produces only one module
93 // instance with no key, since we don't yet support "count" and "for_each"
94 // on modules.
95 // FIXME: As part of supporting "count" and "for_each" on modules, rework
96 // this so that we'll "expand" the module call first and then create graph
97 // nodes for each module instance separately.
98 instPath := path.UnkeyedInstanceShim()
99
100 allResources := make([]*configs.Resource, 0, len(module.ManagedResources)+len(module.DataResources))
101 for _, r := range module.ManagedResources {
102 allResources = append(allResources, r)
103 }
104 for _, r := range module.DataResources {
105 allResources = append(allResources, r)
106 }
bae9f6d2 107
107c1cdb
ND
108 for _, r := range allResources {
109 relAddr := r.Addr()
bae9f6d2 110
107c1cdb
ND
111 if t.ModeFilter && relAddr.Mode != t.Mode {
112 // Skip non-matching modes
bae9f6d2
JC
113 continue
114 }
115
107c1cdb
ND
116 addr := relAddr.Absolute(instPath)
117 if _, ok := t.uniqueMap[addr.String()]; ok {
118 // We've already seen a resource with this address. This should
119 // never happen, because we enforce uniqueness in the config loader.
bae9f6d2
JC
120 continue
121 }
122
bae9f6d2
JC
123 abstract := &NodeAbstractResource{Addr: addr}
124 var node dag.Vertex = abstract
125 if f := t.Concrete; f != nil {
126 node = f(abstract)
127 }
128
bae9f6d2
JC
129 g.Add(node)
130 }
131
132 return nil
133}