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