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  }