]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - 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
1 package terraform
2
3 import (
4 "log"
5 "sync"
6
7 "github.com/hashicorp/terraform/addrs"
8 "github.com/hashicorp/terraform/configs"
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".
23 type ConfigTransformer struct {
24 Concrete ConcreteResourceNodeFunc
25
26 // Module is the module to add resources from.
27 Config *configs.Config
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
34 Mode addrs.ResourceMode
35
36 l sync.Mutex
37 uniqueMap map[string]struct{}
38 }
39
40 func (t *ConfigTransformer) Transform(g *Graph) error {
41 // Lock since we use some internal state
42 t.l.Lock()
43 defer t.l.Unlock()
44
45 // If no configuration is available, we don't do anything
46 if t.Config == nil {
47 return nil
48 }
49
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
63 return t.transform(g, t.Config)
64 }
65
66 func (t *ConfigTransformer) transform(g *Graph, config *configs.Config) error {
67 // If no config, do nothing
68 if config == nil {
69 return nil
70 }
71
72 // Add our resources
73 if err := t.transformSingle(g, config); err != nil {
74 return err
75 }
76
77 // Transform all the children.
78 for _, c := range config.Children {
79 if err := t.transform(g, c); err != nil {
80 return err
81 }
82 }
83
84 return nil
85 }
86
87 func (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 }
107
108 for _, r := range allResources {
109 relAddr := r.Addr()
110
111 if t.ModeFilter && relAddr.Mode != t.Mode {
112 // Skip non-matching modes
113 continue
114 }
115
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.
120 continue
121 }
122
123 abstract := &NodeAbstractResource{Addr: addr}
124 var node dag.Vertex = abstract
125 if f := t.Concrete; f != nil {
126 node = f(abstract)
127 }
128
129 g.Add(node)
130 }
131
132 return nil
133 }