github.com/ns1/terraform@v0.7.10-0.20161109153551-8949419bef40/terraform/transform_output_orphan.go (about) 1 package terraform 2 3 import ( 4 "fmt" 5 6 "github.com/hashicorp/terraform/dag" 7 ) 8 9 // GraphNodeOutput is an interface that nodes that are outputs must 10 // implement. The OutputName returned is the name of the output key 11 // that they manage. 12 type GraphNodeOutput interface { 13 OutputName() string 14 } 15 16 // AddOutputOrphanTransformer is a transformer that adds output orphans 17 // to the graph. Output orphans are outputs that are no longer in the 18 // configuration and therefore need to be removed from the state. 19 // 20 // NOTE: This is the _old_ way to add output orphans that is used with 21 // legacy graph builders. The new way is OrphanOutputTransformer. 22 type AddOutputOrphanTransformer struct { 23 State *State 24 } 25 26 func (t *AddOutputOrphanTransformer) Transform(g *Graph) error { 27 // Get the state for this module. If we have no state, we have no orphans 28 state := t.State.ModuleByPath(g.Path) 29 if state == nil { 30 return nil 31 } 32 33 // Create the set of outputs we do have in the graph 34 found := make(map[string]struct{}) 35 for _, v := range g.Vertices() { 36 on, ok := v.(GraphNodeOutput) 37 if !ok { 38 continue 39 } 40 41 found[on.OutputName()] = struct{}{} 42 } 43 44 // Go over all the outputs. If we don't have a graph node for it, 45 // create it. It doesn't need to depend on anything, since its just 46 // setting it empty. 47 for k, _ := range state.Outputs { 48 if _, ok := found[k]; ok { 49 continue 50 } 51 52 g.Add(&graphNodeOrphanOutput{OutputName: k}) 53 } 54 55 return nil 56 } 57 58 type graphNodeOrphanOutput struct { 59 OutputName string 60 } 61 62 func (n *graphNodeOrphanOutput) Name() string { 63 return fmt.Sprintf("output.%s (orphan)", n.OutputName) 64 } 65 66 func (n *graphNodeOrphanOutput) EvalTree() EvalNode { 67 return &EvalOpFilter{ 68 Ops: []walkOperation{walkApply, walkDestroy, walkRefresh}, 69 Node: &EvalDeleteOutput{ 70 Name: n.OutputName, 71 }, 72 } 73 } 74 75 // GraphNodeFlattenable impl. 76 func (n *graphNodeOrphanOutput) Flatten(p []string) (dag.Vertex, error) { 77 return &graphNodeOrphanOutputFlat{ 78 graphNodeOrphanOutput: n, 79 PathValue: p, 80 }, nil 81 } 82 83 type graphNodeOrphanOutputFlat struct { 84 *graphNodeOrphanOutput 85 86 PathValue []string 87 } 88 89 func (n *graphNodeOrphanOutputFlat) Name() string { 90 return fmt.Sprintf( 91 "%s.%s", modulePrefixStr(n.PathValue), n.graphNodeOrphanOutput.Name()) 92 } 93 94 func (n *graphNodeOrphanOutputFlat) EvalTree() EvalNode { 95 return &EvalOpFilter{ 96 Ops: []walkOperation{walkApply, walkDestroy, walkRefresh}, 97 Node: &EvalDeleteOutput{ 98 Name: n.OutputName, 99 }, 100 } 101 }