]>
Commit | Line | Data |
---|---|---|
bae9f6d2 JC |
1 | package terraform |
2 | ||
3 | import ( | |
15c0b25d AP |
4 | "log" |
5 | ||
107c1cdb | 6 | "github.com/hashicorp/terraform/configs" |
15c0b25d | 7 | "github.com/hashicorp/terraform/dag" |
bae9f6d2 JC |
8 | ) |
9 | ||
10 | // OutputTransformer is a GraphTransformer that adds all the outputs | |
11 | // in the configuration to the graph. | |
12 | // | |
13 | // This is done for the apply graph builder even if dependent nodes | |
14 | // aren't changing since there is no downside: the state will be available | |
15 | // even if the dependent items aren't changing. | |
16 | type OutputTransformer struct { | |
107c1cdb | 17 | Config *configs.Config |
bae9f6d2 JC |
18 | } |
19 | ||
20 | func (t *OutputTransformer) Transform(g *Graph) error { | |
107c1cdb | 21 | return t.transform(g, t.Config) |
bae9f6d2 JC |
22 | } |
23 | ||
107c1cdb ND |
24 | func (t *OutputTransformer) transform(g *Graph, c *configs.Config) error { |
25 | // If we have no config then there can be no outputs. | |
26 | if c == nil { | |
bae9f6d2 JC |
27 | return nil |
28 | } | |
29 | ||
30 | // Transform all the children. We must do this first because | |
31 | // we can reference module outputs and they must show up in the | |
32 | // reference map. | |
107c1cdb ND |
33 | for _, cc := range c.Children { |
34 | if err := t.transform(g, cc); err != nil { | |
bae9f6d2 JC |
35 | return err |
36 | } | |
37 | } | |
38 | ||
107c1cdb ND |
39 | // Our addressing system distinguishes between modules and module instances, |
40 | // but we're not yet ready to make that distinction here (since we don't | |
41 | // support "count"/"for_each" on modules) and so we just do a naive | |
42 | // transform of the module path into a module instance path, assuming that | |
43 | // no keys are in use. This should be removed when "count" and "for_each" | |
44 | // are implemented for modules. | |
45 | path := c.Path.UnkeyedInstanceShim() | |
bae9f6d2 | 46 | |
107c1cdb ND |
47 | for _, o := range c.Module.Outputs { |
48 | addr := path.OutputValue(o.Name) | |
bae9f6d2 | 49 | node := &NodeApplyableOutput{ |
107c1cdb ND |
50 | Addr: addr, |
51 | Config: o, | |
bae9f6d2 | 52 | } |
bae9f6d2 JC |
53 | g.Add(node) |
54 | } | |
55 | ||
56 | return nil | |
57 | } | |
15c0b25d AP |
58 | |
59 | // DestroyOutputTransformer is a GraphTransformer that adds nodes to delete | |
60 | // outputs during destroy. We need to do this to ensure that no stale outputs | |
61 | // are ever left in the state. | |
62 | type DestroyOutputTransformer struct { | |
63 | } | |
64 | ||
65 | func (t *DestroyOutputTransformer) Transform(g *Graph) error { | |
66 | for _, v := range g.Vertices() { | |
67 | output, ok := v.(*NodeApplyableOutput) | |
68 | if !ok { | |
69 | continue | |
70 | } | |
71 | ||
72 | // create the destroy node for this output | |
73 | node := &NodeDestroyableOutput{ | |
107c1cdb ND |
74 | Addr: output.Addr, |
75 | Config: output.Config, | |
15c0b25d AP |
76 | } |
77 | ||
78 | log.Printf("[TRACE] creating %s", node.Name()) | |
79 | g.Add(node) | |
80 | ||
81 | deps, err := g.Descendents(v) | |
82 | if err != nil { | |
83 | return err | |
84 | } | |
85 | ||
86 | // the destroy node must depend on the eval node | |
87 | deps.Add(v) | |
88 | ||
89 | for _, d := range deps.List() { | |
90 | log.Printf("[TRACE] %s depends on %s", node.Name(), dag.VertexName(d)) | |
91 | g.Connect(dag.BasicEdge(node, d)) | |
92 | } | |
93 | } | |
94 | return nil | |
95 | } |