github.com/cycloidio/terraform@v1.1.10-0.20220513142504-76d5c768dc63/addrs/module.go (about) 1 package addrs 2 3 import ( 4 "strings" 5 ) 6 7 // Module is an address for a module call within configuration. This is 8 // the static counterpart of ModuleInstance, representing a traversal through 9 // the static module call tree in configuration and does not take into account 10 // the potentially-multiple instances of a module that might be created by 11 // "count" and "for_each" arguments within those calls. 12 // 13 // This type should be used only in very specialized cases when working with 14 // the static module call tree. Type ModuleInstance is appropriate in more cases. 15 // 16 // Although Module is a slice, it should be treated as immutable after creation. 17 type Module []string 18 19 // RootModule is the module address representing the root of the static module 20 // call tree, which is also the zero value of Module. 21 // 22 // Note that this is not the root of the dynamic module tree, which is instead 23 // represented by RootModuleInstance. 24 var RootModule Module 25 26 // IsRoot returns true if the receiver is the address of the root module, 27 // or false otherwise. 28 func (m Module) IsRoot() bool { 29 return len(m) == 0 30 } 31 32 func (m Module) String() string { 33 if len(m) == 0 { 34 return "" 35 } 36 var steps []string 37 for _, s := range m { 38 steps = append(steps, "module", s) 39 } 40 return strings.Join(steps, ".") 41 } 42 43 func (m Module) Equal(other Module) bool { 44 if len(m) != len(other) { 45 return false 46 } 47 for i := range m { 48 if m[i] != other[i] { 49 return false 50 } 51 } 52 return true 53 } 54 55 func (m Module) targetableSigil() { 56 // Module is targetable 57 } 58 59 // TargetContains implements Targetable for Module by returning true if the given other 60 // address either matches the receiver, is a sub-module-instance of the 61 // receiver, or is a targetable absolute address within a module that 62 // is contained within the receiver. 63 func (m Module) TargetContains(other Targetable) bool { 64 switch to := other.(type) { 65 66 case Module: 67 if len(to) < len(m) { 68 // Can't be contained if the path is shorter 69 return false 70 } 71 // Other is contained if its steps match for the length of our own path. 72 for i, ourStep := range m { 73 otherStep := to[i] 74 if ourStep != otherStep { 75 return false 76 } 77 } 78 // If we fall out here then the prefixed matched, so it's contained. 79 return true 80 81 case ModuleInstance: 82 return m.TargetContains(to.Module()) 83 84 case ConfigResource: 85 return m.TargetContains(to.Module) 86 87 case AbsResource: 88 return m.TargetContains(to.Module) 89 90 case AbsResourceInstance: 91 return m.TargetContains(to.Module) 92 93 default: 94 return false 95 } 96 } 97 98 func (m Module) AddrType() TargetableAddrType { 99 return ModuleAddrType 100 } 101 102 // Child returns the address of a child call in the receiver, identified by the 103 // given name. 104 func (m Module) Child(name string) Module { 105 ret := make(Module, 0, len(m)+1) 106 ret = append(ret, m...) 107 return append(ret, name) 108 } 109 110 // Parent returns the address of the parent module of the receiver, or the 111 // receiver itself if there is no parent (if it's the root module address). 112 func (m Module) Parent() Module { 113 if len(m) == 0 { 114 return m 115 } 116 return m[:len(m)-1] 117 } 118 119 // Call returns the module call address that corresponds to the given module 120 // instance, along with the address of the module that contains it. 121 // 122 // There is no call for the root module, so this method will panic if called 123 // on the root module address. 124 // 125 // In practice, this just turns the last element of the receiver into a 126 // ModuleCall and then returns a slice of the receiever that excludes that 127 // last part. This is just a convenience for situations where a call address 128 // is required, such as when dealing with *Reference and Referencable values. 129 func (m Module) Call() (Module, ModuleCall) { 130 if len(m) == 0 { 131 panic("cannot produce ModuleCall for root module") 132 } 133 134 caller, callName := m[:len(m)-1], m[len(m)-1] 135 return caller, ModuleCall{ 136 Name: callName, 137 } 138 } 139 140 // Ancestors returns a slice containing the receiver and all of its ancestor 141 // modules, all the way up to (and including) the root module. The result is 142 // ordered by depth, with the root module always first. 143 // 144 // Since the result always includes the root module, a caller may choose to 145 // ignore it by slicing the result with [1:]. 146 func (m Module) Ancestors() []Module { 147 ret := make([]Module, 0, len(m)+1) 148 for i := 0; i <= len(m); i++ { 149 ret = append(ret, m[:i]) 150 } 151 return ret 152 } 153 154 func (m Module) configMoveableSigil() { 155 // ModuleInstance is moveable 156 }