]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blobdiff - vendor/github.com/hashicorp/terraform/terraform/transform_reference.go
deps: github.com/hashicorp/terraform@sdk-v0.11-with-go-modules
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / terraform / transform_reference.go
index c5452354d4b65917eef363aea0f67971b4d03b0e..be8c7f96c394e43468f84e9e6822871ed930c365 100644 (file)
@@ -76,6 +76,85 @@ func (t *ReferenceTransformer) Transform(g *Graph) error {
        return nil
 }
 
+// DestroyReferenceTransformer is a GraphTransformer that reverses the edges
+// for locals and outputs that depend on other nodes which will be
+// removed during destroy. If a destroy node is evaluated before the local or
+// output value, it will be removed from the state, and the later interpolation
+// will fail.
+type DestroyValueReferenceTransformer struct{}
+
+func (t *DestroyValueReferenceTransformer) Transform(g *Graph) error {
+       vs := g.Vertices()
+       for _, v := range vs {
+               switch v.(type) {
+               case *NodeApplyableOutput, *NodeLocal:
+                       // OK
+               default:
+                       continue
+               }
+
+               // reverse any outgoing edges so that the value is evaluated first.
+               for _, e := range g.EdgesFrom(v) {
+                       target := e.Target()
+
+                       // only destroy nodes will be evaluated in reverse
+                       if _, ok := target.(GraphNodeDestroyer); !ok {
+                               continue
+                       }
+
+                       log.Printf("[TRACE] output dep: %s", dag.VertexName(target))
+
+                       g.RemoveEdge(e)
+                       g.Connect(&DestroyEdge{S: target, T: v})
+               }
+       }
+
+       return nil
+}
+
+// PruneUnusedValuesTransformer is s GraphTransformer that removes local and
+// output values which are not referenced in the graph. Since outputs and
+// locals always need to be evaluated, if they reference a resource that is not
+// available in the state the interpolation could fail.
+type PruneUnusedValuesTransformer struct{}
+
+func (t *PruneUnusedValuesTransformer) Transform(g *Graph) error {
+       // this might need multiple runs in order to ensure that pruning a value
+       // doesn't effect a previously checked value.
+       for removed := 0; ; removed = 0 {
+               for _, v := range g.Vertices() {
+                       switch v.(type) {
+                       case *NodeApplyableOutput, *NodeLocal:
+                               // OK
+                       default:
+                               continue
+                       }
+
+                       dependants := g.UpEdges(v)
+
+                       switch dependants.Len() {
+                       case 0:
+                               // nothing at all depends on this
+                               g.Remove(v)
+                               removed++
+                       case 1:
+                               // because an output's destroy node always depends on the output,
+                               // we need to check for the case of a single destroy node.
+                               d := dependants.List()[0]
+                               if _, ok := d.(*NodeDestroyableOutput); ok {
+                                       g.Remove(v)
+                                       removed++
+                               }
+                       }
+               }
+               if removed == 0 {
+                       break
+               }
+       }
+
+       return nil
+}
+
 // ReferenceMap is a structure that can be used to efficiently check
 // for references on a graph.
 type ReferenceMap struct {
@@ -96,6 +175,7 @@ func (m *ReferenceMap) References(v dag.Vertex) ([]dag.Vertex, []string) {
        var matches []dag.Vertex
        var missing []string
        prefix := m.prefix(v)
+
        for _, ns := range rn.References() {
                found := false
                for _, n := range strings.Split(ns, "/") {
@@ -108,19 +188,14 @@ func (m *ReferenceMap) References(v dag.Vertex) ([]dag.Vertex, []string) {
                        // Mark that we found a match
                        found = true
 
-                       // Make sure this isn't a self reference, which isn't included
-                       selfRef := false
                        for _, p := range parents {
+                               // don't include self-references
                                if p == v {
-                                       selfRef = true
-                                       break
+                                       continue
                                }
-                       }
-                       if selfRef {
-                               continue
+                               matches = append(matches, p)
                        }
 
-                       matches = append(matches, parents...)
                        break
                }
 
@@ -296,14 +371,21 @@ func ReferenceFromInterpolatedVar(v config.InterpolatedVariable) []string {
                return []string{fmt.Sprintf("%s.%d/%s.N", id, idx, id)}
        case *config.UserVariable:
                return []string{fmt.Sprintf("var.%s", v.Name)}
+       case *config.LocalVariable:
+               return []string{fmt.Sprintf("local.%s", v.Name)}
        default:
                return nil
        }
 }
 
 func modulePrefixStr(p []string) string {
+       // strip "root"
+       if len(p) > 0 && p[0] == rootModulePath[0] {
+               p = p[1:]
+       }
+
        parts := make([]string, 0, len(p)*2)
-       for _, p := range p[1:] {
+       for _, p := range p {
                parts = append(parts, "module", p)
        }