]>
Commit | Line | Data |
---|---|---|
bae9f6d2 JC |
1 | package terraform |
2 | ||
3 | import ( | |
4 | "fmt" | |
5 | "log" | |
6 | ||
7 | "github.com/hashicorp/terraform/config/module" | |
8 | "github.com/hashicorp/terraform/dag" | |
9 | ) | |
10 | ||
11 | // DiffTransformer is a GraphTransformer that adds the elements of | |
12 | // the diff to the graph. | |
13 | // | |
14 | // This transform is used for example by the ApplyGraphBuilder to ensure | |
15 | // that only resources that are being modified are represented in the graph. | |
16 | // | |
17 | // Module and State is still required for the DiffTransformer for annotations | |
18 | // since the Diff doesn't contain all the information required to build the | |
19 | // complete graph (such as create-before-destroy information). The graph | |
20 | // is built based on the diff first, though, ensuring that only resources | |
21 | // that are being modified are present in the graph. | |
22 | type DiffTransformer struct { | |
23 | Concrete ConcreteResourceNodeFunc | |
24 | ||
25 | Diff *Diff | |
26 | Module *module.Tree | |
27 | State *State | |
28 | } | |
29 | ||
30 | func (t *DiffTransformer) Transform(g *Graph) error { | |
31 | // If the diff is nil or empty (nil is empty) then do nothing | |
32 | if t.Diff.Empty() { | |
33 | return nil | |
34 | } | |
35 | ||
36 | // Go through all the modules in the diff. | |
37 | log.Printf("[TRACE] DiffTransformer: starting") | |
38 | var nodes []dag.Vertex | |
39 | for _, m := range t.Diff.Modules { | |
40 | log.Printf("[TRACE] DiffTransformer: Module: %s", m) | |
41 | // TODO: If this is a destroy diff then add a module destroy node | |
42 | ||
43 | // Go through all the resources in this module. | |
44 | for name, inst := range m.Resources { | |
45 | log.Printf("[TRACE] DiffTransformer: Resource %q: %#v", name, inst) | |
46 | ||
47 | // We have changes! This is a create or update operation. | |
48 | // First grab the address so we have a unique way to | |
49 | // reference this resource. | |
50 | addr, err := parseResourceAddressInternal(name) | |
51 | if err != nil { | |
52 | panic(fmt.Sprintf( | |
53 | "Error parsing internal name, this is a bug: %q", name)) | |
54 | } | |
55 | ||
56 | // Very important: add the module path for this resource to | |
57 | // the address. Remove "root" from it. | |
58 | addr.Path = m.Path[1:] | |
59 | ||
60 | // If we're destroying, add the destroy node | |
61 | if inst.Destroy || inst.GetDestroyDeposed() { | |
62 | abstract := &NodeAbstractResource{Addr: addr} | |
63 | g.Add(&NodeDestroyResource{NodeAbstractResource: abstract}) | |
64 | } | |
65 | ||
66 | // If we have changes, then add the applyable version | |
67 | if len(inst.Attributes) > 0 { | |
68 | // Add the resource to the graph | |
69 | abstract := &NodeAbstractResource{Addr: addr} | |
70 | var node dag.Vertex = abstract | |
71 | if f := t.Concrete; f != nil { | |
72 | node = f(abstract) | |
73 | } | |
74 | ||
75 | nodes = append(nodes, node) | |
76 | } | |
77 | } | |
78 | } | |
79 | ||
80 | // Add all the nodes to the graph | |
81 | for _, n := range nodes { | |
82 | g.Add(n) | |
83 | } | |
84 | ||
85 | return nil | |
86 | } |