]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/hashicorp/terraform/terraform/transform_orphan_count.go
Initial transfer of provider code
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / terraform / transform_orphan_count.go
1 package terraform
2
3 import (
4 "log"
5
6 "github.com/hashicorp/terraform/dag"
7 )
8
9 // OrphanResourceCountTransformer is a GraphTransformer that adds orphans
10 // for an expanded count to the graph. The determination of this depends
11 // on the count argument given.
12 //
13 // Orphans are found by comparing the count to what is found in the state.
14 // This transform assumes that if an element in the state is within the count
15 // bounds given, that it is not an orphan.
16 type OrphanResourceCountTransformer struct {
17 Concrete ConcreteResourceNodeFunc
18
19 Count int // Actual count of the resource
20 Addr *ResourceAddress // Addr of the resource to look for orphans
21 State *State // Full global state
22 }
23
24 func (t *OrphanResourceCountTransformer) Transform(g *Graph) error {
25 log.Printf("[TRACE] OrphanResourceCount: Starting...")
26
27 // Grab the module in the state just for this resource address
28 ms := t.State.ModuleByPath(normalizeModulePath(t.Addr.Path))
29 if ms == nil {
30 // If no state, there can't be orphans
31 return nil
32 }
33
34 orphanIndex := -1
35 if t.Count == 1 {
36 orphanIndex = 0
37 }
38
39 // Go through the orphans and add them all to the state
40 for key, _ := range ms.Resources {
41 // Build the address
42 addr, err := parseResourceAddressInternal(key)
43 if err != nil {
44 return err
45 }
46 addr.Path = ms.Path[1:]
47
48 // Copy the address for comparison. If we aren't looking at
49 // the same resource, then just ignore it.
50 addrCopy := addr.Copy()
51 addrCopy.Index = -1
52 if !addrCopy.Equals(t.Addr) {
53 continue
54 }
55
56 log.Printf("[TRACE] OrphanResourceCount: Checking: %s", addr)
57
58 idx := addr.Index
59
60 // If we have zero and the index here is 0 or 1, then we
61 // change the index to a high number so that we treat it as
62 // an orphan.
63 if t.Count <= 0 && idx <= 0 {
64 idx = t.Count + 1
65 }
66
67 // If we have a count greater than 0 and we're at the zero index,
68 // we do a special case check to see if our state also has a
69 // -1 index value. If so, this is an orphan because our rules are
70 // that if both a -1 and 0 are in the state, the 0 is destroyed.
71 if t.Count > 0 && idx == orphanIndex {
72 // This is a piece of cleverness (beware), but its simple:
73 // if orphanIndex is 0, then check -1, else check 0.
74 checkIndex := (orphanIndex + 1) * -1
75
76 key := &ResourceStateKey{
77 Name: addr.Name,
78 Type: addr.Type,
79 Mode: addr.Mode,
80 Index: checkIndex,
81 }
82
83 if _, ok := ms.Resources[key.String()]; ok {
84 // We have a -1 index, too. Make an arbitrarily high
85 // index so that we always mark this as an orphan.
86 log.Printf(
87 "[WARN] OrphanResourceCount: %q both -1 and 0 index found, orphaning %d",
88 addr, orphanIndex)
89 idx = t.Count + 1
90 }
91 }
92
93 // If the index is within the count bounds, it is not an orphan
94 if idx < t.Count {
95 continue
96 }
97
98 // Build the abstract node and the concrete one
99 abstract := &NodeAbstractResource{Addr: addr}
100 var node dag.Vertex = abstract
101 if f := t.Concrete; f != nil {
102 node = f(abstract)
103 }
104
105 // Add it to the graph
106 g.Add(node)
107 }
108
109 return nil
110 }