summaryrefslogtreecommitdiff
path: root/vendor/github.com/hashicorp/terraform/terraform/transform_orphan_count.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/terraform/transform_orphan_count.go')
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/transform_orphan_count.go110
1 files changed, 110 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/terraform/transform_orphan_count.go b/vendor/github.com/hashicorp/terraform/terraform/transform_orphan_count.go
new file mode 100644
index 00000000..b256a25b
--- /dev/null
+++ b/vendor/github.com/hashicorp/terraform/terraform/transform_orphan_count.go
@@ -0,0 +1,110 @@
+package terraform
+
+import (
+ "log"
+
+ "github.com/hashicorp/terraform/dag"
+)
+
+// OrphanResourceCountTransformer is a GraphTransformer that adds orphans
+// for an expanded count to the graph. The determination of this depends
+// on the count argument given.
+//
+// Orphans are found by comparing the count to what is found in the state.
+// This transform assumes that if an element in the state is within the count
+// bounds given, that it is not an orphan.
+type OrphanResourceCountTransformer struct {
+ Concrete ConcreteResourceNodeFunc
+
+ Count int // Actual count of the resource
+ Addr *ResourceAddress // Addr of the resource to look for orphans
+ State *State // Full global state
+}
+
+func (t *OrphanResourceCountTransformer) Transform(g *Graph) error {
+ log.Printf("[TRACE] OrphanResourceCount: Starting...")
+
+ // Grab the module in the state just for this resource address
+ ms := t.State.ModuleByPath(normalizeModulePath(t.Addr.Path))
+ if ms == nil {
+ // If no state, there can't be orphans
+ return nil
+ }
+
+ orphanIndex := -1
+ if t.Count == 1 {
+ orphanIndex = 0
+ }
+
+ // Go through the orphans and add them all to the state
+ for key, _ := range ms.Resources {
+ // Build the address
+ addr, err := parseResourceAddressInternal(key)
+ if err != nil {
+ return err
+ }
+ addr.Path = ms.Path[1:]
+
+ // Copy the address for comparison. If we aren't looking at
+ // the same resource, then just ignore it.
+ addrCopy := addr.Copy()
+ addrCopy.Index = -1
+ if !addrCopy.Equals(t.Addr) {
+ continue
+ }
+
+ log.Printf("[TRACE] OrphanResourceCount: Checking: %s", addr)
+
+ idx := addr.Index
+
+ // If we have zero and the index here is 0 or 1, then we
+ // change the index to a high number so that we treat it as
+ // an orphan.
+ if t.Count <= 0 && idx <= 0 {
+ idx = t.Count + 1
+ }
+
+ // If we have a count greater than 0 and we're at the zero index,
+ // we do a special case check to see if our state also has a
+ // -1 index value. If so, this is an orphan because our rules are
+ // that if both a -1 and 0 are in the state, the 0 is destroyed.
+ if t.Count > 0 && idx == orphanIndex {
+ // This is a piece of cleverness (beware), but its simple:
+ // if orphanIndex is 0, then check -1, else check 0.
+ checkIndex := (orphanIndex + 1) * -1
+
+ key := &ResourceStateKey{
+ Name: addr.Name,
+ Type: addr.Type,
+ Mode: addr.Mode,
+ Index: checkIndex,
+ }
+
+ if _, ok := ms.Resources[key.String()]; ok {
+ // We have a -1 index, too. Make an arbitrarily high
+ // index so that we always mark this as an orphan.
+ log.Printf(
+ "[WARN] OrphanResourceCount: %q both -1 and 0 index found, orphaning %d",
+ addr, orphanIndex)
+ idx = t.Count + 1
+ }
+ }
+
+ // If the index is within the count bounds, it is not an orphan
+ if idx < t.Count {
+ continue
+ }
+
+ // Build the abstract node and the concrete one
+ abstract := &NodeAbstractResource{Addr: addr}
+ var node dag.Vertex = abstract
+ if f := t.Concrete; f != nil {
+ node = f(abstract)
+ }
+
+ // Add it to the graph
+ g.Add(node)
+ }
+
+ return nil
+}