@@ -26,21 +26,6 @@ func ParameterContextsEvalHook(input Input) func(ctx *tfcontext.Context, blocks
26
26
continue // Wow a value exists?!. This feels like a bug.
27
27
}
28
28
29
- countAttr , countExists := block .Attributes ()["count" ]
30
- if countExists {
31
- // Omit count = 0 values!
32
- countVal := countAttr .Value ()
33
- if ! countVal .Type ().Equals (cty .Number ) {
34
- continue // Probably unknown
35
- }
36
- v , _ := countVal .AsBigFloat ().Int64 ()
37
- if v < 1 {
38
- // Non-one counts are incorrect
39
- // Zero counts are ignored as the blocks are omitted
40
- continue
41
- }
42
- }
43
-
44
29
nameAttr := block .GetAttribute ("name" )
45
30
nameVal := nameAttr .Value ()
46
31
if ! nameVal .Type ().Equals (cty .String ) {
@@ -64,54 +49,181 @@ func ParameterContextsEvalHook(input Input) func(ctx *tfcontext.Context, blocks
64
49
}
65
50
}
66
51
67
- // Set the default value as the 'value' attribute
68
52
path := []string {
69
53
"data" ,
70
54
"coder_parameter" ,
71
55
block .Reference ().NameLabel (),
72
56
}
73
- if countExists {
74
- // Append to the existing tuple
75
- existing := ctx .Get (path ... )
76
- if existing .IsNull () {
77
- continue
78
- }
57
+ existing := ctx .Get (path ... )
58
+ obj , ok := mergeParamInstanceValues (block , existing , value )
59
+ if ! ok {
60
+ continue
61
+ }
62
+ ctx .Set (obj , path ... )
63
+ //
64
+ //ref := block.Reference()
65
+ //refKey := ref.RawKey()
66
+ //
67
+ //fmt.Println(refKey)
68
+ //
69
+ //countAttr, countExists := block.Attributes()["count"]
70
+ //if countExists {
71
+ // // Omit count = 0 values!
72
+ // countVal := countAttr.Value()
73
+ // if !countVal.Type().Equals(cty.Number) {
74
+ // continue // Probably unknown
75
+ // }
76
+ // v, _ := countVal.AsBigFloat().Int64()
77
+ // if v < 1 {
78
+ // // Non-one counts are incorrect
79
+ // // Zero counts are ignored as the blocks are omitted
80
+ // continue
81
+ // }
82
+ //}
83
+ //
84
+ //nameAttr := block.GetAttribute("name")
85
+ //nameVal := nameAttr.Value()
86
+ //if !nameVal.Type().Equals(cty.String) {
87
+ // continue // Ignore the errors at this point
88
+ //}
89
+ //
90
+ //// Set the default value as the 'value' attribute
91
+ //path := []string{
92
+ // "data",
93
+ // "coder_parameter",
94
+ // block.Reference().NameLabel(),
95
+ //}
96
+ //if countExists {
97
+ // // Append to the existing tuple
98
+ // existing := ctx.Get(path...)
99
+ // if existing.IsNull() {
100
+ // continue
101
+ // }
102
+ //
103
+ // if !existing.Type().IsTupleType() {
104
+ // continue
105
+ // }
106
+ //
107
+ // if existing.LengthInt() > 1 {
108
+ // // coder_parameters can only ever have a count of 0 or 1.
109
+ // // More than that is invalid. So ignore invalid blocks.
110
+ // continue
111
+ // }
112
+ //
113
+ // it := existing.ElementIterator()
114
+ // if !it.Next() {
115
+ // continue
116
+ // }
117
+ //
118
+ // _, v := it.Element()
119
+ // merged := hclext.MergeObjects(v, cty.ObjectVal(map[string]cty.Value{
120
+ // "value": value,
121
+ // }))
122
+ //
123
+ // // Since our count can only equal 1, we can safely set the
124
+ // // value to a tuple of length 1 in all cases.
125
+ // ctx.Set(cty.TupleVal([]cty.Value{merged}), path...)
126
+ // continue
127
+ //}
128
+ //
129
+ //path = append(path, "value")
130
+ //// The current context is in the `coder_parameter` block.
131
+ //// Use the parent context to "export" the value
132
+ //ctx.Set(value, path...)
133
+ //block.Context().Parent().Set(value, path...)
134
+ }
135
+ }
136
+ }
79
137
80
- if ! existing .Type ().IsTupleType () {
81
- continue
82
- }
138
+ func mergeParamInstanceValues (b * terraform.Block , existing cty.Value , value cty.Value ) (cty.Value , bool ) {
139
+ if existing .IsNull () {
140
+ return existing , false
141
+ }
83
142
84
- if existing .LengthInt () > 1 {
85
- // coder_parameters can only ever have a count of 0 or 1.
86
- // More than that is invalid. So ignore invalid blocks.
87
- continue
88
- }
143
+ ref := b .Reference ()
144
+ key := ref .RawKey ()
89
145
90
- it := existing .ElementIterator ()
91
- if ! it .Next () {
92
- continue
93
- }
146
+ switch {
147
+ case key .Type ().Equals (cty .Number ) && b .GetAttribute ("count" ) != nil :
148
+ if ! existing .Type ().IsTupleType () {
149
+ return existing , false
150
+ }
94
151
95
- _ , v := it .Element ()
96
- merged := hclext .MergeObjects (v , cty .ObjectVal (map [string ]cty.Value {
97
- "value" : value ,
98
- }))
152
+ idx , _ := key .AsBigFloat ().Int64 ()
153
+ elem := existing .Index (key )
154
+ if elem .IsNull () || ! elem .IsKnown () {
155
+ return existing , false
156
+ }
99
157
100
- // Since our count can only equal 1, we can safely set the
101
- // value to a tuple of length 1 in all cases.
102
- ctx .Set (cty .TupleVal ([]cty.Value {merged }), path ... )
103
- continue
104
- }
158
+ obj , ok := setObjectField (elem , "value" , value )
159
+ if ! ok {
160
+ return existing , false
161
+ }
105
162
106
- path = append (path , "value" )
107
- // The current context is in the `coder_parameter` block.
108
- // Use the parent context to "export" the value
109
- ctx .Set (value , path ... )
110
- //block.Context().Parent().Set(value, path...)
163
+ return hclext .InsertTupleElement (existing , int (idx ), obj ), true
164
+ case isForEachKey (key ) && b .GetAttribute ("for_each" ) != nil :
165
+ keyStr := ref .Key ()
166
+ if ! existing .Type ().IsObjectType () {
167
+ return existing , false
168
+ }
169
+
170
+ if ! existing .CanIterateElements () {
171
+ return existing , false
172
+ }
173
+
174
+ instances := existing .AsValueMap ()
175
+ if instances == nil {
176
+ return existing , false
177
+ }
178
+
179
+ instance , ok := instances [keyStr ]
180
+ if ! ok {
181
+ return existing , false
182
+ }
183
+
184
+ instance , ok = setObjectField (instance , "value" , value )
185
+ if ! ok {
186
+ return existing , false
187
+ }
188
+
189
+ instances [keyStr ] = instance
190
+ return cty .ObjectVal (instances ), true
191
+
192
+ default :
193
+ obj , ok := setObjectField (existing , "value" , value )
194
+ if ! ok {
195
+ return existing , false
111
196
}
197
+ return obj , true
112
198
}
113
199
}
114
200
201
+ func setObjectField (object cty.Value , field string , value cty.Value ) (cty.Value , bool ) {
202
+ if object .IsNull () {
203
+ return object , false
204
+ }
205
+
206
+ if ! object .Type ().IsObjectType () {
207
+ return object , false
208
+ }
209
+
210
+ if ! object .CanIterateElements () {
211
+ return object , false
212
+ }
213
+
214
+ instances := object .AsValueMap ()
215
+ if instances == nil {
216
+ return object , false
217
+ }
218
+
219
+ instances [field ] = value
220
+ return cty .ObjectVal (instances ), true
221
+ }
222
+
223
+ func isForEachKey (key cty.Value ) bool {
224
+ return key .Type ().Equals (cty .Number ) || key .Type ().Equals (cty .String )
225
+ }
226
+
115
227
func evaluateCoderParameterDefault (b * terraform.Block ) (cty.Value , bool ) {
116
228
attributes := b .Attributes ()
117
229
0 commit comments