github.com/r3labs/terraform@v0.8.4/terraform/node_resource_destroy.go (about) 1 package terraform 2 3 import ( 4 "fmt" 5 6 "github.com/hashicorp/terraform/config" 7 ) 8 9 // NodeDestroyResource represents a resource that is to be destroyed. 10 type NodeDestroyResource struct { 11 *NodeAbstractResource 12 } 13 14 func (n *NodeDestroyResource) Name() string { 15 return n.NodeAbstractResource.Name() + " (destroy)" 16 } 17 18 // GraphNodeDestroyer 19 func (n *NodeDestroyResource) DestroyAddr() *ResourceAddress { 20 return n.Addr 21 } 22 23 // GraphNodeDestroyerCBD 24 func (n *NodeDestroyResource) CreateBeforeDestroy() bool { 25 // If we have no config, we just assume no 26 if n.Config == nil { 27 return false 28 } 29 30 return n.Config.Lifecycle.CreateBeforeDestroy 31 } 32 33 // GraphNodeDestroyerCBD 34 func (n *NodeDestroyResource) ModifyCreateBeforeDestroy(v bool) error { 35 // If we have no config, do nothing since it won't affect the 36 // create step anyways. 37 if n.Config == nil { 38 return nil 39 } 40 41 // Set CBD to true 42 n.Config.Lifecycle.CreateBeforeDestroy = true 43 44 return nil 45 } 46 47 // GraphNodeReferenceable, overriding NodeAbstractResource 48 func (n *NodeDestroyResource) ReferenceableName() []string { 49 result := n.NodeAbstractResource.ReferenceableName() 50 for i, v := range result { 51 result[i] = v + ".destroy" 52 } 53 54 return result 55 } 56 57 // GraphNodeReferencer, overriding NodeAbstractResource 58 func (n *NodeDestroyResource) References() []string { 59 return nil 60 } 61 62 // GraphNodeDynamicExpandable 63 func (n *NodeDestroyResource) DynamicExpand(ctx EvalContext) (*Graph, error) { 64 // If we have no config we do nothing 65 if n.Addr == nil { 66 return nil, nil 67 } 68 69 state, lock := ctx.State() 70 lock.RLock() 71 defer lock.RUnlock() 72 73 // Start creating the steps 74 steps := make([]GraphTransformer, 0, 5) 75 76 // We want deposed resources in the state to be destroyed 77 steps = append(steps, &DeposedTransformer{ 78 State: state, 79 View: n.Addr.stateId(), 80 }) 81 82 // Target 83 steps = append(steps, &TargetsTransformer{ 84 ParsedTargets: n.Targets, 85 }) 86 87 // Always end with the root being added 88 steps = append(steps, &RootTransformer{}) 89 90 // Build the graph 91 b := &BasicGraphBuilder{ 92 Steps: steps, 93 Name: "NodeResourceDestroy", 94 } 95 return b.Build(ctx.Path()) 96 } 97 98 // GraphNodeEvalable 99 func (n *NodeDestroyResource) EvalTree() EvalNode { 100 // stateId is the ID to put into the state 101 stateId := n.Addr.stateId() 102 103 // Build the instance info. More of this will be populated during eval 104 info := &InstanceInfo{ 105 Id: stateId, 106 Type: n.Addr.Type, 107 uniqueExtra: "destroy", 108 } 109 110 // Get our state 111 rs := n.ResourceState 112 if rs == nil { 113 rs = &ResourceState{} 114 } 115 116 var diffApply *InstanceDiff 117 var provider ResourceProvider 118 var state *InstanceState 119 var err error 120 return &EvalOpFilter{ 121 Ops: []walkOperation{walkApply, walkDestroy}, 122 Node: &EvalSequence{ 123 Nodes: []EvalNode{ 124 // Get the saved diff for apply 125 &EvalReadDiff{ 126 Name: stateId, 127 Diff: &diffApply, 128 }, 129 130 // Filter the diff so we only get the destroy 131 &EvalFilterDiff{ 132 Diff: &diffApply, 133 Output: &diffApply, 134 Destroy: true, 135 }, 136 137 // If we're not destroying, then compare diffs 138 &EvalIf{ 139 If: func(ctx EvalContext) (bool, error) { 140 if diffApply != nil && diffApply.GetDestroy() { 141 return true, nil 142 } 143 144 return true, EvalEarlyExitError{} 145 }, 146 Then: EvalNoop{}, 147 }, 148 149 // Load the instance info so we have the module path set 150 &EvalInstanceInfo{Info: info}, 151 152 &EvalGetProvider{ 153 Name: n.ProvidedBy()[0], 154 Output: &provider, 155 }, 156 &EvalReadState{ 157 Name: stateId, 158 Output: &state, 159 }, 160 &EvalRequireState{ 161 State: &state, 162 }, 163 // Make sure we handle data sources properly. 164 &EvalIf{ 165 If: func(ctx EvalContext) (bool, error) { 166 if n.Addr == nil { 167 return false, fmt.Errorf("nil address") 168 } 169 170 if n.Addr.Mode == config.DataResourceMode { 171 return true, nil 172 } 173 174 return false, nil 175 }, 176 177 Then: &EvalReadDataApply{ 178 Info: info, 179 Diff: &diffApply, 180 Provider: &provider, 181 Output: &state, 182 }, 183 Else: &EvalApply{ 184 Info: info, 185 State: &state, 186 Diff: &diffApply, 187 Provider: &provider, 188 Output: &state, 189 Error: &err, 190 }, 191 }, 192 &EvalWriteState{ 193 Name: stateId, 194 ResourceType: n.Addr.Type, 195 Provider: rs.Provider, 196 Dependencies: rs.Dependencies, 197 State: &state, 198 }, 199 &EvalApplyPost{ 200 Info: info, 201 State: &state, 202 Error: &err, 203 }, 204 &EvalUpdateStateHook{}, 205 }, 206 }, 207 } 208 }