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