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 }