github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/instances/expansion_mode.go (about)

     1  // Copyright (c) HashiCorp, Inc.
     2  // SPDX-License-Identifier: MPL-2.0
     3  
     4  package instances
     5  
     6  import (
     7  	"fmt"
     8  	"sort"
     9  
    10  	"github.com/zclconf/go-cty/cty"
    11  
    12  	"github.com/terramate-io/tf/addrs"
    13  )
    14  
    15  // expansion is an internal interface used to represent the different
    16  // ways expansion can operate depending on how repetition is configured for
    17  // an object.
    18  type expansion interface {
    19  	instanceKeys() []addrs.InstanceKey
    20  	repetitionData(addrs.InstanceKey) RepetitionData
    21  }
    22  
    23  // expansionSingle is the expansion corresponding to no repetition arguments
    24  // at all, producing a single object with no key.
    25  //
    26  // expansionSingleVal is the only valid value of this type.
    27  type expansionSingle uintptr
    28  
    29  var singleKeys = []addrs.InstanceKey{addrs.NoKey}
    30  var expansionSingleVal expansionSingle
    31  
    32  func (e expansionSingle) instanceKeys() []addrs.InstanceKey {
    33  	return singleKeys
    34  }
    35  
    36  func (e expansionSingle) repetitionData(key addrs.InstanceKey) RepetitionData {
    37  	if key != addrs.NoKey {
    38  		panic("cannot use instance key with non-repeating object")
    39  	}
    40  	return RepetitionData{}
    41  }
    42  
    43  // expansionCount is the expansion corresponding to the "count" argument.
    44  type expansionCount int
    45  
    46  func (e expansionCount) instanceKeys() []addrs.InstanceKey {
    47  	ret := make([]addrs.InstanceKey, int(e))
    48  	for i := range ret {
    49  		ret[i] = addrs.IntKey(i)
    50  	}
    51  	return ret
    52  }
    53  
    54  func (e expansionCount) repetitionData(key addrs.InstanceKey) RepetitionData {
    55  	i := int(key.(addrs.IntKey))
    56  	if i < 0 || i >= int(e) {
    57  		panic(fmt.Sprintf("instance key %d out of range for count %d", i, e))
    58  	}
    59  	return RepetitionData{
    60  		CountIndex: cty.NumberIntVal(int64(i)),
    61  	}
    62  }
    63  
    64  // expansionForEach is the expansion corresponding to the "for_each" argument.
    65  type expansionForEach map[string]cty.Value
    66  
    67  func (e expansionForEach) instanceKeys() []addrs.InstanceKey {
    68  	ret := make([]addrs.InstanceKey, 0, len(e))
    69  	for k := range e {
    70  		ret = append(ret, addrs.StringKey(k))
    71  	}
    72  	sort.Slice(ret, func(i, j int) bool {
    73  		return ret[i].(addrs.StringKey) < ret[j].(addrs.StringKey)
    74  	})
    75  	return ret
    76  }
    77  
    78  func (e expansionForEach) repetitionData(key addrs.InstanceKey) RepetitionData {
    79  	k := string(key.(addrs.StringKey))
    80  	v, ok := e[k]
    81  	if !ok {
    82  		panic(fmt.Sprintf("instance key %q does not match any instance", k))
    83  	}
    84  	return RepetitionData{
    85  		EachKey:   cty.StringVal(k),
    86  		EachValue: v,
    87  	}
    88  }