]>
Commit | Line | Data |
---|---|---|
bae9f6d2 JC |
1 | package terraform |
2 | ||
3 | import ( | |
4 | "errors" | |
5 | "fmt" | |
6 | "log" | |
7 | "sync" | |
8 | ||
9 | "github.com/hashicorp/terraform/config" | |
10 | "github.com/hashicorp/terraform/config/module" | |
11 | "github.com/hashicorp/terraform/dag" | |
12 | ) | |
13 | ||
14 | // ConfigTransformer is a GraphTransformer that adds all the resources | |
15 | // from the configuration to the graph. | |
16 | // | |
17 | // The module used to configure this transformer must be the root module. | |
18 | // | |
19 | // Only resources are added to the graph. Variables, outputs, and | |
20 | // providers must be added via other transforms. | |
21 | // | |
22 | // Unlike ConfigTransformerOld, this transformer creates a graph with | |
23 | // all resources including module resources, rather than creating module | |
24 | // nodes that are then "flattened". | |
25 | type ConfigTransformer struct { | |
26 | Concrete ConcreteResourceNodeFunc | |
27 | ||
28 | // Module is the module to add resources from. | |
29 | Module *module.Tree | |
30 | ||
31 | // Unique will only add resources that aren't already present in the graph. | |
32 | Unique bool | |
33 | ||
34 | // Mode will only add resources that match the given mode | |
35 | ModeFilter bool | |
36 | Mode config.ResourceMode | |
37 | ||
38 | l sync.Mutex | |
39 | uniqueMap map[string]struct{} | |
40 | } | |
41 | ||
42 | func (t *ConfigTransformer) Transform(g *Graph) error { | |
43 | // Lock since we use some internal state | |
44 | t.l.Lock() | |
45 | defer t.l.Unlock() | |
46 | ||
47 | // If no module is given, we don't do anything | |
48 | if t.Module == nil { | |
49 | return nil | |
50 | } | |
51 | ||
52 | // If the module isn't loaded, that is simply an error | |
53 | if !t.Module.Loaded() { | |
54 | return errors.New("module must be loaded for ConfigTransformer") | |
55 | } | |
56 | ||
57 | // Reset the uniqueness map. If we're tracking uniques, then populate | |
58 | // it with addresses. | |
59 | t.uniqueMap = make(map[string]struct{}) | |
60 | defer func() { t.uniqueMap = nil }() | |
61 | if t.Unique { | |
62 | for _, v := range g.Vertices() { | |
63 | if rn, ok := v.(GraphNodeResource); ok { | |
64 | t.uniqueMap[rn.ResourceAddr().String()] = struct{}{} | |
65 | } | |
66 | } | |
67 | } | |
68 | ||
69 | // Start the transformation process | |
70 | return t.transform(g, t.Module) | |
71 | } | |
72 | ||
73 | func (t *ConfigTransformer) transform(g *Graph, m *module.Tree) error { | |
74 | // If no config, do nothing | |
75 | if m == nil { | |
76 | return nil | |
77 | } | |
78 | ||
79 | // Add our resources | |
80 | if err := t.transformSingle(g, m); err != nil { | |
81 | return err | |
82 | } | |
83 | ||
84 | // Transform all the children. | |
85 | for _, c := range m.Children() { | |
86 | if err := t.transform(g, c); err != nil { | |
87 | return err | |
88 | } | |
89 | } | |
90 | ||
91 | return nil | |
92 | } | |
93 | ||
94 | func (t *ConfigTransformer) transformSingle(g *Graph, m *module.Tree) error { | |
95 | log.Printf("[TRACE] ConfigTransformer: Starting for path: %v", m.Path()) | |
96 | ||
97 | // Get the configuration for this module | |
98 | conf := m.Config() | |
99 | ||
100 | // Build the path we're at | |
101 | path := m.Path() | |
102 | ||
103 | // Write all the resources out | |
104 | for _, r := range conf.Resources { | |
105 | // Build the resource address | |
106 | addr, err := parseResourceAddressConfig(r) | |
107 | if err != nil { | |
108 | panic(fmt.Sprintf( | |
109 | "Error parsing config address, this is a bug: %#v", r)) | |
110 | } | |
111 | addr.Path = path | |
112 | ||
113 | // If this is already in our uniqueness map, don't add it again | |
114 | if _, ok := t.uniqueMap[addr.String()]; ok { | |
115 | continue | |
116 | } | |
117 | ||
118 | // Remove non-matching modes | |
119 | if t.ModeFilter && addr.Mode != t.Mode { | |
120 | continue | |
121 | } | |
122 | ||
123 | // Build the abstract node and the concrete one | |
124 | abstract := &NodeAbstractResource{Addr: addr} | |
125 | var node dag.Vertex = abstract | |
126 | if f := t.Concrete; f != nil { | |
127 | node = f(abstract) | |
128 | } | |
129 | ||
130 | // Add it to the graph | |
131 | g.Add(node) | |
132 | } | |
133 | ||
134 | return nil | |
135 | } |