github.com/rstandt/terraform@v0.12.32-0.20230710220336-b1063613405c/addrs/resource.go (about) 1 package addrs 2 3 import ( 4 "fmt" 5 "strings" 6 ) 7 8 // Resource is an address for a resource block within configuration, which 9 // contains potentially-multiple resource instances if that configuration 10 // block uses "count" or "for_each". 11 type Resource struct { 12 referenceable 13 Mode ResourceMode 14 Type string 15 Name string 16 } 17 18 func (r Resource) String() string { 19 switch r.Mode { 20 case ManagedResourceMode: 21 return fmt.Sprintf("%s.%s", r.Type, r.Name) 22 case DataResourceMode: 23 return fmt.Sprintf("data.%s.%s", r.Type, r.Name) 24 default: 25 // Should never happen, but we'll return a string here rather than 26 // crashing just in case it does. 27 return fmt.Sprintf("<invalid>.%s.%s", r.Type, r.Name) 28 } 29 } 30 31 func (r Resource) Equal(o Resource) bool { 32 return r.String() == o.String() 33 } 34 35 // Instance produces the address for a specific instance of the receiver 36 // that is idenfied by the given key. 37 func (r Resource) Instance(key InstanceKey) ResourceInstance { 38 return ResourceInstance{ 39 Resource: r, 40 Key: key, 41 } 42 } 43 44 // Absolute returns an AbsResource from the receiver and the given module 45 // instance address. 46 func (r Resource) Absolute(module ModuleInstance) AbsResource { 47 return AbsResource{ 48 Module: module, 49 Resource: r, 50 } 51 } 52 53 // DefaultProviderConfig returns the address of the provider configuration 54 // that should be used for the resource identified by the reciever if it 55 // does not have a provider configuration address explicitly set in 56 // configuration. 57 // 58 // This method is not able to verify that such a configuration exists, nor 59 // represent the behavior of automatically inheriting certain provider 60 // configurations from parent modules. It just does a static analysis of the 61 // receiving address and returns an address to start from, relative to the 62 // same module that contains the resource. 63 func (r Resource) DefaultProviderConfig() ProviderConfig { 64 typeName := r.Type 65 if under := strings.Index(typeName, "_"); under != -1 { 66 typeName = typeName[:under] 67 } 68 69 return ProviderConfig{ 70 Type: NewLegacyProvider(typeName), 71 } 72 } 73 74 // ResourceInstance is an address for a specific instance of a resource. 75 // When a resource is defined in configuration with "count" or "for_each" it 76 // produces zero or more instances, which can be addressed using this type. 77 type ResourceInstance struct { 78 referenceable 79 Resource Resource 80 Key InstanceKey 81 } 82 83 func (r ResourceInstance) ContainingResource() Resource { 84 return r.Resource 85 } 86 87 func (r ResourceInstance) String() string { 88 if r.Key == NoKey { 89 return r.Resource.String() 90 } 91 return r.Resource.String() + r.Key.String() 92 } 93 94 func (r ResourceInstance) Equal(o ResourceInstance) bool { 95 return r.String() == o.String() 96 } 97 98 // Absolute returns an AbsResourceInstance from the receiver and the given module 99 // instance address. 100 func (r ResourceInstance) Absolute(module ModuleInstance) AbsResourceInstance { 101 return AbsResourceInstance{ 102 Module: module, 103 Resource: r, 104 } 105 } 106 107 // AbsResource is an absolute address for a resource under a given module path. 108 type AbsResource struct { 109 targetable 110 Module ModuleInstance 111 Resource Resource 112 } 113 114 // Resource returns the address of a particular resource within the receiver. 115 func (m ModuleInstance) Resource(mode ResourceMode, typeName string, name string) AbsResource { 116 return AbsResource{ 117 Module: m, 118 Resource: Resource{ 119 Mode: mode, 120 Type: typeName, 121 Name: name, 122 }, 123 } 124 } 125 126 // Instance produces the address for a specific instance of the receiver 127 // that is idenfied by the given key. 128 func (r AbsResource) Instance(key InstanceKey) AbsResourceInstance { 129 return AbsResourceInstance{ 130 Module: r.Module, 131 Resource: r.Resource.Instance(key), 132 } 133 } 134 135 // TargetContains implements Targetable by returning true if the given other 136 // address is either equal to the receiver or is an instance of the 137 // receiver. 138 func (r AbsResource) TargetContains(other Targetable) bool { 139 switch to := other.(type) { 140 141 case AbsResource: 142 // We'll use our stringification as a cheat-ish way to test for equality. 143 return to.String() == r.String() 144 145 case AbsResourceInstance: 146 return r.TargetContains(to.ContainingResource()) 147 148 default: 149 return false 150 151 } 152 } 153 154 func (r AbsResource) String() string { 155 if len(r.Module) == 0 { 156 return r.Resource.String() 157 } 158 return fmt.Sprintf("%s.%s", r.Module.String(), r.Resource.String()) 159 } 160 161 func (r AbsResource) Equal(o AbsResource) bool { 162 return r.String() == o.String() 163 } 164 165 // AbsResourceInstance is an absolute address for a resource instance under a 166 // given module path. 167 type AbsResourceInstance struct { 168 targetable 169 Module ModuleInstance 170 Resource ResourceInstance 171 } 172 173 // ResourceInstance returns the address of a particular resource instance within the receiver. 174 func (m ModuleInstance) ResourceInstance(mode ResourceMode, typeName string, name string, key InstanceKey) AbsResourceInstance { 175 return AbsResourceInstance{ 176 Module: m, 177 Resource: ResourceInstance{ 178 Resource: Resource{ 179 Mode: mode, 180 Type: typeName, 181 Name: name, 182 }, 183 Key: key, 184 }, 185 } 186 } 187 188 // ContainingResource returns the address of the resource that contains the 189 // receving resource instance. In other words, it discards the key portion 190 // of the address to produce an AbsResource value. 191 func (r AbsResourceInstance) ContainingResource() AbsResource { 192 return AbsResource{ 193 Module: r.Module, 194 Resource: r.Resource.ContainingResource(), 195 } 196 } 197 198 // TargetContains implements Targetable by returning true if the given other 199 // address is equal to the receiver. 200 func (r AbsResourceInstance) TargetContains(other Targetable) bool { 201 switch to := other.(type) { 202 203 case AbsResourceInstance: 204 // We'll use our stringification as a cheat-ish way to test for equality. 205 return to.String() == r.String() 206 207 default: 208 return false 209 210 } 211 } 212 213 func (r AbsResourceInstance) String() string { 214 if len(r.Module) == 0 { 215 return r.Resource.String() 216 } 217 return fmt.Sprintf("%s.%s", r.Module.String(), r.Resource.String()) 218 } 219 220 func (r AbsResourceInstance) Equal(o AbsResourceInstance) bool { 221 return r.String() == o.String() 222 } 223 224 // Less returns true if the receiver should sort before the given other value 225 // in a sorted list of addresses. 226 func (r AbsResourceInstance) Less(o AbsResourceInstance) bool { 227 switch { 228 229 case len(r.Module) != len(o.Module): 230 return len(r.Module) < len(o.Module) 231 232 case r.Module.String() != o.Module.String(): 233 return r.Module.Less(o.Module) 234 235 case r.Resource.Resource.Mode != o.Resource.Resource.Mode: 236 return r.Resource.Resource.Mode == DataResourceMode 237 238 case r.Resource.Resource.Type != o.Resource.Resource.Type: 239 return r.Resource.Resource.Type < o.Resource.Resource.Type 240 241 case r.Resource.Resource.Name != o.Resource.Resource.Name: 242 return r.Resource.Resource.Name < o.Resource.Resource.Name 243 244 case r.Resource.Key != o.Resource.Key: 245 return InstanceKeyLess(r.Resource.Key, o.Resource.Key) 246 247 default: 248 return false 249 250 } 251 } 252 253 // ResourceMode defines which lifecycle applies to a given resource. Each 254 // resource lifecycle has a slightly different address format. 255 type ResourceMode rune 256 257 //go:generate go run golang.org/x/tools/cmd/stringer -type ResourceMode 258 259 const ( 260 // InvalidResourceMode is the zero value of ResourceMode and is not 261 // a valid resource mode. 262 InvalidResourceMode ResourceMode = 0 263 264 // ManagedResourceMode indicates a managed resource, as defined by 265 // "resource" blocks in configuration. 266 ManagedResourceMode ResourceMode = 'M' 267 268 // DataResourceMode indicates a data resource, as defined by 269 // "data" blocks in configuration. 270 DataResourceMode ResourceMode = 'D' 271 )