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  )