github.com/turtlemonvh/terraform@v0.6.9-0.20151204001754-8e40b6b855e8/terraform/transform_output.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  type AddOutputOrphanTransformer struct {
    20  	State *State
    21  }
    22  
    23  func (t *AddOutputOrphanTransformer) Transform(g *Graph) error {
    24  	// Get the state for this module. If we have no state, we have no orphans
    25  	state := t.State.ModuleByPath(g.Path)
    26  	if state == nil {
    27  		return nil
    28  	}
    29  
    30  	// Create the set of outputs we do have in the graph
    31  	found := make(map[string]struct{})
    32  	for _, v := range g.Vertices() {
    33  		on, ok := v.(GraphNodeOutput)
    34  		if !ok {
    35  			continue
    36  		}
    37  
    38  		found[on.OutputName()] = struct{}{}
    39  	}
    40  
    41  	// Go over all the outputs. If we don't have a graph node for it,
    42  	// create it. It doesn't need to depend on anything, since its just
    43  	// setting it empty.
    44  	for k, _ := range state.Outputs {
    45  		if _, ok := found[k]; ok {
    46  			continue
    47  		}
    48  
    49  		g.Add(&graphNodeOrphanOutput{OutputName: k})
    50  	}
    51  
    52  	return nil
    53  }
    54  
    55  type graphNodeOrphanOutput struct {
    56  	OutputName string
    57  }
    58  
    59  func (n *graphNodeOrphanOutput) Name() string {
    60  	return fmt.Sprintf("output.%s (orphan)", n.OutputName)
    61  }
    62  
    63  func (n *graphNodeOrphanOutput) EvalTree() EvalNode {
    64  	return &EvalOpFilter{
    65  		Ops: []walkOperation{walkApply, walkDestroy, walkRefresh},
    66  		Node: &EvalDeleteOutput{
    67  			Name: n.OutputName,
    68  		},
    69  	}
    70  }
    71  
    72  // GraphNodeFlattenable impl.
    73  func (n *graphNodeOrphanOutput) Flatten(p []string) (dag.Vertex, error) {
    74  	return &graphNodeOrphanOutputFlat{
    75  		graphNodeOrphanOutput: n,
    76  		PathValue:             p,
    77  	}, nil
    78  }
    79  
    80  type graphNodeOrphanOutputFlat struct {
    81  	*graphNodeOrphanOutput
    82  
    83  	PathValue []string
    84  }
    85  
    86  func (n *graphNodeOrphanOutputFlat) Name() string {
    87  	return fmt.Sprintf(
    88  		"%s.%s", modulePrefixStr(n.PathValue), n.graphNodeOrphanOutput.Name())
    89  }
    90  
    91  func (n *graphNodeOrphanOutputFlat) EvalTree() EvalNode {
    92  	return &EvalOpFilter{
    93  		Ops: []walkOperation{walkApply, walkDestroy, walkRefresh},
    94  		Node: &EvalDeleteOutput{
    95  			Name: n.OutputName,
    96  		},
    97  	}
    98  }