5 // DeposedTransformer is a GraphTransformer that adds deposed resources
7 type DeposedTransformer struct {
8 // State is the global state. We'll automatically find the correct
9 // ModuleState based on the Graph.Path that is being transformed.
12 // View, if non-empty, is the ModuleState.View used around the state
13 // to find deposed resources.
17 func (t *DeposedTransformer) Transform(g *Graph) error {
18 state := t.State.ModuleByPath(g.Path)
20 // If there is no state for our module there can't be any deposed
21 // resources, since they live in the state.
25 // If we have a view, apply it now
27 state = state.View(t.View)
30 // Go through all the resources in our state to look for deposed resources
31 for k, rs := range state.Resources {
32 // If we have no deposed resources, then move on
33 if len(rs.Deposed) == 0 {
38 for i, _ := range deposed {
39 g.Add(&graphNodeDeposedResource{
42 ResourceType: rs.Type,
43 Provider: rs.Provider,
51 // graphNodeDeposedResource is the graph vertex representing a deposed resource.
52 type graphNodeDeposedResource struct {
59 func (n *graphNodeDeposedResource) Name() string {
60 return fmt.Sprintf("%s (deposed #%d)", n.ResourceName, n.Index)
63 func (n *graphNodeDeposedResource) ProvidedBy() []string {
64 return []string{resourceProvider(n.ResourceName, n.Provider)}
67 // GraphNodeEvalable impl.
68 func (n *graphNodeDeposedResource) EvalTree() EvalNode {
69 var provider ResourceProvider
70 var state *InstanceState
72 seq := &EvalSequence{Nodes: make([]EvalNode, 0, 5)}
74 // Build instance info
75 info := &InstanceInfo{Id: n.Name(), Type: n.ResourceType}
76 seq.Nodes = append(seq.Nodes, &EvalInstanceInfo{Info: info})
78 // Refresh the resource
79 seq.Nodes = append(seq.Nodes, &EvalOpFilter{
80 Ops: []walkOperation{walkRefresh},
84 Name: n.ProvidedBy()[0],
87 &EvalReadStateDeposed{
98 &EvalWriteStateDeposed{
100 ResourceType: n.ResourceType,
101 Provider: n.Provider,
110 var diff *InstanceDiff
112 seq.Nodes = append(seq.Nodes, &EvalOpFilter{
113 Ops: []walkOperation{walkApply, walkDestroy},
117 Name: n.ProvidedBy()[0],
120 &EvalReadStateDeposed{
121 Name: n.ResourceName,
130 // Call pre-apply hook
144 // Always write the resource back to the state deposed... if it
145 // was successfully destroyed it will be pruned. If it was not, it will
146 // be caught on the next run.
147 &EvalWriteStateDeposed{
148 Name: n.ResourceName,
149 ResourceType: n.ResourceType,
150 Provider: n.Provider,
162 &EvalUpdateStateHook{},