github.com/hashicorp/terraform-plugin-sdk@v1.17.2/terraform/node_module_removed.go (about) 1 package terraform 2 3 import ( 4 "fmt" 5 6 "github.com/hashicorp/terraform-plugin-sdk/internal/addrs" 7 ) 8 9 // NodeModuleRemoved represents a module that is no longer in the 10 // config. 11 type NodeModuleRemoved struct { 12 Addr addrs.ModuleInstance 13 } 14 15 var ( 16 _ GraphNodeSubPath = (*NodeModuleRemoved)(nil) 17 _ RemovableIfNotTargeted = (*NodeModuleRemoved)(nil) 18 _ GraphNodeEvalable = (*NodeModuleRemoved)(nil) 19 _ GraphNodeReferencer = (*NodeModuleRemoved)(nil) 20 _ GraphNodeReferenceOutside = (*NodeModuleRemoved)(nil) 21 ) 22 23 func (n *NodeModuleRemoved) Name() string { 24 return fmt.Sprintf("%s (removed)", n.Addr.String()) 25 } 26 27 // GraphNodeSubPath 28 func (n *NodeModuleRemoved) Path() addrs.ModuleInstance { 29 return n.Addr 30 } 31 32 // GraphNodeEvalable 33 func (n *NodeModuleRemoved) EvalTree() EvalNode { 34 return &EvalOpFilter{ 35 Ops: []walkOperation{walkRefresh, walkApply, walkDestroy}, 36 Node: &EvalCheckModuleRemoved{ 37 Addr: n.Addr, 38 }, 39 } 40 } 41 42 func (n *NodeModuleRemoved) ReferenceOutside() (selfPath, referencePath addrs.ModuleInstance) { 43 // Our "References" implementation indicates that this node depends on 44 // the call to the module it represents, which implicitly depends on 45 // everything inside the module. That reference must therefore be 46 // interpreted in terms of our parent module. 47 return n.Addr, n.Addr.Parent() 48 } 49 50 func (n *NodeModuleRemoved) References() []*addrs.Reference { 51 // We depend on the call to the module we represent, because that 52 // implicitly then depends on everything inside that module. 53 // Our ReferenceOutside implementation causes this to be interpreted 54 // within the parent module. 55 56 _, call := n.Addr.CallInstance() 57 return []*addrs.Reference{ 58 { 59 Subject: call, 60 61 // No source range here, because there's nothing reasonable for 62 // us to return. 63 }, 64 } 65 } 66 67 // RemovableIfNotTargeted 68 func (n *NodeModuleRemoved) RemoveIfNotTargeted() bool { 69 // We need to add this so that this node will be removed if 70 // it isn't targeted or a dependency of a target. 71 return true 72 } 73 74 // EvalCheckModuleRemoved is an EvalNode implementation that verifies that 75 // a module has been removed from the state as expected. 76 type EvalCheckModuleRemoved struct { 77 Addr addrs.ModuleInstance 78 } 79 80 func (n *EvalCheckModuleRemoved) Eval(ctx EvalContext) (interface{}, error) { 81 mod := ctx.State().Module(n.Addr) 82 if mod != nil { 83 // If we get here then that indicates a bug either in the states 84 // module or in an earlier step of the graph walk, since we should've 85 // pruned out the module when the last resource was removed from it. 86 return nil, fmt.Errorf("leftover module %s in state that should have been removed; this is a bug in Terraform and should be reported", n.Addr) 87 } 88 return nil, nil 89 }