github.com/pulumi/terraform@v1.4.0/pkg/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.Mode == o.Mode && r.Name == o.Name && r.Type == o.Type 33 } 34 35 func (r Resource) Less(o Resource) bool { 36 switch { 37 case r.Mode != o.Mode: 38 return r.Mode == DataResourceMode 39 40 case r.Type != o.Type: 41 return r.Type < o.Type 42 43 case r.Name != o.Name: 44 return r.Name < o.Name 45 46 default: 47 return false 48 } 49 } 50 51 func (r Resource) UniqueKey() UniqueKey { 52 return r // A Resource is its own UniqueKey 53 } 54 55 func (r Resource) uniqueKeySigil() {} 56 57 // Instance produces the address for a specific instance of the receiver 58 // that is idenfied by the given key. 59 func (r Resource) Instance(key InstanceKey) ResourceInstance { 60 return ResourceInstance{ 61 Resource: r, 62 Key: key, 63 } 64 } 65 66 // Absolute returns an AbsResource from the receiver and the given module 67 // instance address. 68 func (r Resource) Absolute(module ModuleInstance) AbsResource { 69 return AbsResource{ 70 Module: module, 71 Resource: r, 72 } 73 } 74 75 // InModule returns a ConfigResource from the receiver and the given module 76 // address. 77 func (r Resource) InModule(module Module) ConfigResource { 78 return ConfigResource{ 79 Module: module, 80 Resource: r, 81 } 82 } 83 84 // ImpliedProvider returns the implied provider type name, for e.g. the "aws" in 85 // "aws_instance" 86 func (r Resource) ImpliedProvider() string { 87 typeName := r.Type 88 if under := strings.Index(typeName, "_"); under != -1 { 89 typeName = typeName[:under] 90 } 91 92 return typeName 93 } 94 95 // ResourceInstance is an address for a specific instance of a resource. 96 // When a resource is defined in configuration with "count" or "for_each" it 97 // produces zero or more instances, which can be addressed using this type. 98 type ResourceInstance struct { 99 referenceable 100 Resource Resource 101 Key InstanceKey 102 } 103 104 func (r ResourceInstance) ContainingResource() Resource { 105 return r.Resource 106 } 107 108 func (r ResourceInstance) String() string { 109 if r.Key == NoKey { 110 return r.Resource.String() 111 } 112 return r.Resource.String() + r.Key.String() 113 } 114 115 func (r ResourceInstance) Equal(o ResourceInstance) bool { 116 return r.Key == o.Key && r.Resource.Equal(o.Resource) 117 } 118 119 func (r ResourceInstance) Less(o ResourceInstance) bool { 120 if !r.Resource.Equal(o.Resource) { 121 return r.Resource.Less(o.Resource) 122 } 123 124 if r.Key != o.Key { 125 return InstanceKeyLess(r.Key, o.Key) 126 } 127 128 return false 129 } 130 131 func (r ResourceInstance) UniqueKey() UniqueKey { 132 return r // A ResourceInstance is its own UniqueKey 133 } 134 135 func (r ResourceInstance) uniqueKeySigil() {} 136 137 // Absolute returns an AbsResourceInstance from the receiver and the given module 138 // instance address. 139 func (r ResourceInstance) Absolute(module ModuleInstance) AbsResourceInstance { 140 return AbsResourceInstance{ 141 Module: module, 142 Resource: r, 143 } 144 } 145 146 // AbsResource is an absolute address for a resource under a given module path. 147 type AbsResource struct { 148 targetable 149 Module ModuleInstance 150 Resource Resource 151 } 152 153 // Resource returns the address of a particular resource within the receiver. 154 func (m ModuleInstance) Resource(mode ResourceMode, typeName string, name string) AbsResource { 155 return AbsResource{ 156 Module: m, 157 Resource: Resource{ 158 Mode: mode, 159 Type: typeName, 160 Name: name, 161 }, 162 } 163 } 164 165 // Instance produces the address for a specific instance of the receiver 166 // that is idenfied by the given key. 167 func (r AbsResource) Instance(key InstanceKey) AbsResourceInstance { 168 return AbsResourceInstance{ 169 Module: r.Module, 170 Resource: r.Resource.Instance(key), 171 } 172 } 173 174 // Config returns the unexpanded ConfigResource for this AbsResource. 175 func (r AbsResource) Config() ConfigResource { 176 return ConfigResource{ 177 Module: r.Module.Module(), 178 Resource: r.Resource, 179 } 180 } 181 182 // TargetContains implements Targetable by returning true if the given other 183 // address is either equal to the receiver or is an instance of the 184 // receiver. 185 func (r AbsResource) TargetContains(other Targetable) bool { 186 switch to := other.(type) { 187 188 case AbsResource: 189 // We'll use our stringification as a cheat-ish way to test for equality. 190 return to.String() == r.String() 191 192 case ConfigResource: 193 // if an absolute resource from parsing a target address contains a 194 // ConfigResource, the string representation will match 195 return to.String() == r.String() 196 197 case AbsResourceInstance: 198 return r.TargetContains(to.ContainingResource()) 199 200 default: 201 return false 202 203 } 204 } 205 206 func (r AbsResource) AddrType() TargetableAddrType { 207 return AbsResourceAddrType 208 } 209 210 func (r AbsResource) String() string { 211 if len(r.Module) == 0 { 212 return r.Resource.String() 213 } 214 return fmt.Sprintf("%s.%s", r.Module.String(), r.Resource.String()) 215 } 216 217 // AffectedAbsResource returns the AbsResource. 218 func (r AbsResource) AffectedAbsResource() AbsResource { 219 return r 220 } 221 222 func (r AbsResource) Equal(o AbsResource) bool { 223 return r.Module.Equal(o.Module) && r.Resource.Equal(o.Resource) 224 } 225 226 func (r AbsResource) Less(o AbsResource) bool { 227 if !r.Module.Equal(o.Module) { 228 return r.Module.Less(o.Module) 229 } 230 231 if !r.Resource.Equal(o.Resource) { 232 return r.Resource.Less(o.Resource) 233 } 234 235 return false 236 } 237 238 func (r AbsResource) absMoveableSigil() { 239 // AbsResource is moveable 240 } 241 242 type absResourceKey string 243 244 func (r absResourceKey) uniqueKeySigil() {} 245 246 func (r AbsResource) UniqueKey() UniqueKey { 247 return absResourceKey(r.String()) 248 } 249 250 // AbsResourceInstance is an absolute address for a resource instance under a 251 // given module path. 252 type AbsResourceInstance struct { 253 targetable 254 Module ModuleInstance 255 Resource ResourceInstance 256 } 257 258 // ResourceInstance returns the address of a particular resource instance within the receiver. 259 func (m ModuleInstance) ResourceInstance(mode ResourceMode, typeName string, name string, key InstanceKey) AbsResourceInstance { 260 return AbsResourceInstance{ 261 Module: m, 262 Resource: ResourceInstance{ 263 Resource: Resource{ 264 Mode: mode, 265 Type: typeName, 266 Name: name, 267 }, 268 Key: key, 269 }, 270 } 271 } 272 273 // ContainingResource returns the address of the resource that contains the 274 // receving resource instance. In other words, it discards the key portion 275 // of the address to produce an AbsResource value. 276 func (r AbsResourceInstance) ContainingResource() AbsResource { 277 return AbsResource{ 278 Module: r.Module, 279 Resource: r.Resource.ContainingResource(), 280 } 281 } 282 283 // ConfigResource returns the address of the configuration block that declared 284 // this instance. 285 func (r AbsResourceInstance) ConfigResource() ConfigResource { 286 return ConfigResource{ 287 Module: r.Module.Module(), 288 Resource: r.Resource.Resource, 289 } 290 } 291 292 // TargetContains implements Targetable by returning true if the given other 293 // address is equal to the receiver. 294 func (r AbsResourceInstance) TargetContains(other Targetable) bool { 295 switch to := other.(type) { 296 297 // while we currently don't start with an AbsResourceInstance as a target 298 // address, check all resource types for consistency. 299 case AbsResourceInstance: 300 // We'll use our stringification as a cheat-ish way to test for equality. 301 return to.String() == r.String() 302 case ConfigResource: 303 return to.String() == r.String() 304 case AbsResource: 305 return to.String() == r.String() 306 307 default: 308 return false 309 310 } 311 } 312 313 func (r AbsResourceInstance) AddrType() TargetableAddrType { 314 return AbsResourceInstanceAddrType 315 } 316 317 func (r AbsResourceInstance) String() string { 318 if len(r.Module) == 0 { 319 return r.Resource.String() 320 } 321 return fmt.Sprintf("%s.%s", r.Module.String(), r.Resource.String()) 322 } 323 324 // AffectedAbsResource returns the AbsResource for the instance. 325 func (r AbsResourceInstance) AffectedAbsResource() AbsResource { 326 return AbsResource{ 327 Module: r.Module, 328 Resource: r.Resource.Resource, 329 } 330 } 331 332 func (r AbsResourceInstance) Check(t CheckType, i int) Check { 333 return Check{ 334 Container: r, 335 Type: t, 336 Index: i, 337 } 338 } 339 340 func (v AbsResourceInstance) CheckableKind() CheckableKind { 341 return CheckableResource 342 } 343 344 func (r AbsResourceInstance) Equal(o AbsResourceInstance) bool { 345 return r.Module.Equal(o.Module) && r.Resource.Equal(o.Resource) 346 } 347 348 // Less returns true if the receiver should sort before the given other value 349 // in a sorted list of addresses. 350 func (r AbsResourceInstance) Less(o AbsResourceInstance) bool { 351 if !r.Module.Equal(o.Module) { 352 return r.Module.Less(o.Module) 353 } 354 355 if !r.Resource.Equal(o.Resource) { 356 return r.Resource.Less(o.Resource) 357 } 358 359 return false 360 } 361 362 // AbsResourceInstance is a Checkable 363 func (r AbsResourceInstance) checkableSigil() {} 364 365 func (r AbsResourceInstance) ConfigCheckable() ConfigCheckable { 366 // The ConfigCheckable for an AbsResourceInstance is its ConfigResource. 367 return r.ConfigResource() 368 } 369 370 type absResourceInstanceKey string 371 372 func (r AbsResourceInstance) UniqueKey() UniqueKey { 373 return absResourceInstanceKey(r.String()) 374 } 375 376 func (r absResourceInstanceKey) uniqueKeySigil() {} 377 378 func (r AbsResourceInstance) absMoveableSigil() { 379 // AbsResourceInstance is moveable 380 } 381 382 // ConfigResource is an address for a resource within a configuration. 383 type ConfigResource struct { 384 targetable 385 Module Module 386 Resource Resource 387 } 388 389 // Resource returns the address of a particular resource within the module. 390 func (m Module) Resource(mode ResourceMode, typeName string, name string) ConfigResource { 391 return ConfigResource{ 392 Module: m, 393 Resource: Resource{ 394 Mode: mode, 395 Type: typeName, 396 Name: name, 397 }, 398 } 399 } 400 401 // Absolute produces the address for the receiver within a specific module instance. 402 func (r ConfigResource) Absolute(module ModuleInstance) AbsResource { 403 return AbsResource{ 404 Module: module, 405 Resource: r.Resource, 406 } 407 } 408 409 // TargetContains implements Targetable by returning true if the given other 410 // address is either equal to the receiver or is an instance of the 411 // receiver. 412 func (r ConfigResource) TargetContains(other Targetable) bool { 413 switch to := other.(type) { 414 case ConfigResource: 415 // We'll use our stringification as a cheat-ish way to test for equality. 416 return to.String() == r.String() 417 case AbsResource: 418 return r.TargetContains(to.Config()) 419 case AbsResourceInstance: 420 return r.TargetContains(to.ContainingResource()) 421 default: 422 return false 423 } 424 } 425 426 func (r ConfigResource) AddrType() TargetableAddrType { 427 return ConfigResourceAddrType 428 } 429 430 func (r ConfigResource) String() string { 431 if len(r.Module) == 0 { 432 return r.Resource.String() 433 } 434 return fmt.Sprintf("%s.%s", r.Module.String(), r.Resource.String()) 435 } 436 437 func (r ConfigResource) Equal(o ConfigResource) bool { 438 return r.Module.Equal(o.Module) && r.Resource.Equal(o.Resource) 439 } 440 441 func (r ConfigResource) UniqueKey() UniqueKey { 442 return configResourceKey(r.String()) 443 } 444 445 func (r ConfigResource) configMoveableSigil() { 446 // ConfigResource is moveable 447 } 448 449 func (r ConfigResource) configCheckableSigil() { 450 // ConfigResource represents a configuration object that declares checkable objects 451 } 452 453 func (v ConfigResource) CheckableKind() CheckableKind { 454 return CheckableResource 455 } 456 457 type configResourceKey string 458 459 func (k configResourceKey) uniqueKeySigil() {} 460 461 // ResourceMode defines which lifecycle applies to a given resource. Each 462 // resource lifecycle has a slightly different address format. 463 type ResourceMode rune 464 465 //go:generate go run golang.org/x/tools/cmd/stringer -type ResourceMode 466 467 const ( 468 // InvalidResourceMode is the zero value of ResourceMode and is not 469 // a valid resource mode. 470 InvalidResourceMode ResourceMode = 0 471 472 // ManagedResourceMode indicates a managed resource, as defined by 473 // "resource" blocks in configuration. 474 ManagedResourceMode ResourceMode = 'M' 475 476 // DataResourceMode indicates a data resource, as defined by 477 // "data" blocks in configuration. 478 DataResourceMode ResourceMode = 'D' 479 )