github.com/terraform-linters/tflint-plugin-sdk@v0.22.0/terraform/addrs/instance_key.go (about)

     1  package addrs
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/zclconf/go-cty/cty"
     7  	"github.com/zclconf/go-cty/cty/gocty"
     8  )
     9  
    10  // InstanceKey represents the key of an instance within an object that
    11  // contains multiple instances due to using "count" or "for_each" arguments
    12  // in configuration.
    13  //
    14  // IntKey and StringKey are the two implementations of this type. No other
    15  // implementations are allowed. The single instance of an object that _isn't_
    16  // using "count" or "for_each" is represented by NoKey, which is a nil
    17  // InstanceKey.
    18  type InstanceKey interface {
    19  	instanceKeySigil()
    20  	String() string
    21  
    22  	// Value returns the cty.Value of the appropriate type for the InstanceKey
    23  	// value.
    24  	Value() cty.Value
    25  }
    26  
    27  // ParseInstanceKey returns the instance key corresponding to the given value,
    28  // which must be known and non-null.
    29  //
    30  // If an unknown or null value is provided then this function will panic. This
    31  // function is intended to deal with the values that would naturally be found
    32  // in a hcl.TraverseIndex, which (when parsed from source, at least) can never
    33  // contain unknown or null values.
    34  func ParseInstanceKey(key cty.Value) (InstanceKey, error) {
    35  	switch key.Type() {
    36  	case cty.String:
    37  		return StringKey(key.AsString()), nil
    38  	case cty.Number:
    39  		var idx int
    40  		err := gocty.FromCtyValue(key, &idx)
    41  		return IntKey(idx), err
    42  	default:
    43  		return NoKey, fmt.Errorf("either a string or an integer is required")
    44  	}
    45  }
    46  
    47  // NoKey represents the absense of an InstanceKey, for the single instance
    48  // of a configuration object that does not use "count" or "for_each" at all.
    49  var NoKey InstanceKey
    50  
    51  // IntKey is the InstanceKey representation representing integer indices, as
    52  // used when the "count" argument is specified or if for_each is used with
    53  // a sequence type.
    54  type IntKey int
    55  
    56  func (k IntKey) instanceKeySigil() {
    57  }
    58  
    59  func (k IntKey) String() string {
    60  	return fmt.Sprintf("[%d]", int(k))
    61  }
    62  
    63  // Value returns a cty.Value of type Number
    64  func (k IntKey) Value() cty.Value {
    65  	return cty.NumberIntVal(int64(k))
    66  }
    67  
    68  // StringKey is the InstanceKey representation representing string indices, as
    69  // used when the "for_each" argument is specified with a map or object type.
    70  type StringKey string
    71  
    72  func (k StringKey) instanceKeySigil() {
    73  }
    74  
    75  func (k StringKey) String() string {
    76  	// FIXME: This isn't _quite_ right because Go's quoted string syntax is
    77  	// slightly different than HCL's, but we'll accept it for now.
    78  	return fmt.Sprintf("[%q]", string(k))
    79  }
    80  
    81  // Value returns a cty.Value of type String
    82  func (k StringKey) Value() cty.Value {
    83  	return cty.StringVal(string(k))
    84  }
    85  
    86  // InstanceKeyType represents the different types of instance key that are
    87  // supported. Usually it is sufficient to simply type-assert an InstanceKey
    88  // value to either IntKey or StringKey, but this type and its values can be
    89  // used to represent the types themselves, rather than specific values
    90  // of those types.
    91  type InstanceKeyType rune
    92  
    93  const (
    94  	// NoKeyType is a type of NoKey instance key
    95  	NoKeyType InstanceKeyType = 0
    96  	// IntKeyType is a type of IntKey instance key
    97  	IntKeyType InstanceKeyType = 'I'
    98  	// StringKeyType is a type of StringKey instance key
    99  	StringKeyType InstanceKeyType = 'S'
   100  )