@@ -171,8 +171,9 @@ func convertDynamicRepSpecs(resourceb *hclwrite.Body, dSpec dynamicBlock, diskSi
171
171
}
172
172
173
173
// Create the for expression for the flattened replication_specs
174
- forExpr := fmt .Sprintf ("for %s in %s : [\n for i in range(%s) : " ,
175
- nSpec , hcl .GetAttrExpr (dSpec .forEach ), numShardsExpr )
174
+ outerFor := buildForExpression (nSpec , hcl .GetAttrExpr (dSpec .forEach ))
175
+ innerFor := buildForExpressionWithIndex ("i" , fmt .Sprintf ("range(%s)" , numShardsExpr ))
176
+ forExpr := fmt .Sprintf ("%s [\n %s" , outerFor , innerFor )
176
177
tokens := hcl .TokensFromExpr (forExpr )
177
178
tokens = append (tokens , hcl .TokensObject (dSpec .content .Body ())... )
178
179
tokens = append (tokens , hcl .TokensFromExpr ("\n ]\n ]" )... )
@@ -190,7 +191,7 @@ func convertDynamicRepSpecs(resourceb *hclwrite.Body, dSpec dynamicBlock, diskSi
190
191
}
191
192
192
193
// Create the for expression without num_shards
193
- forExpr := fmt . Sprintf ( "for %s in %s :" , nSpec , hcl .GetAttrExpr (dSpec .forEach ))
194
+ forExpr := buildForExpression ( nSpec , hcl .GetAttrExpr (dSpec .forEach ))
194
195
tokens := hcl .TokensFromExpr (forExpr )
195
196
tokens = append (tokens , hcl .TokensObject (dSpec .content .Body ())... )
196
197
tokens = hcl .EncloseBracketsNewLines (tokens )
@@ -208,16 +209,7 @@ func processRegionConfigBlocks(targetBody *hclwrite.Body, blocks []*hclwrite.Blo
208
209
blockBody := blockFile .Body ()
209
210
210
211
// Copy all attributes in deterministic order
211
- attrs := block .Body ().Attributes ()
212
- var names []string
213
- for name := range attrs {
214
- names = append (names , name )
215
- }
216
- slices .Sort (names )
217
- for _ , name := range names {
218
- attr := attrs [name ]
219
- blockBody .SetAttributeRaw (name , hcl .TokensFromExpr (hcl .GetAttrExpr (attr )))
220
- }
212
+ copyAttributesSorted (blockBody , block .Body ().Attributes ())
221
213
222
214
// Add disk_size_gb to specs blocks if needed
223
215
if diskSizeGB != nil && (blockType == nElectableSpecs ||
@@ -242,31 +234,12 @@ func convertDynamicRepSpecsWithDynamicConfig(resourceb *hclwrite.Body, dSpec, dC
242
234
// Transform references in place for the dynamic config content
243
235
transformDynamicBlockReferencesRecursive (dConfig .content .Body (), configBlockName , nRegion )
244
236
// Also transform outer references (with deterministic ordering)
245
- attrs := dConfig .content .Body ().Attributes ()
246
- var attrNames []string
247
- for name := range attrs {
248
- attrNames = append (attrNames , name )
249
- }
250
- slices .Sort (attrNames )
251
- for _ , name := range attrNames {
252
- attr := attrs [name ]
253
- expr := hcl .GetAttrExpr (attr )
254
- expr = replaceDynamicBlockReferences (expr , nRepSpecs , nSpec )
255
- dConfig .content .Body ().SetAttributeRaw (name , hcl .TokensFromExpr (expr ))
237
+ transform := func (expr string ) string {
238
+ return replaceDynamicBlockReferences (expr , nRepSpecs , nSpec )
256
239
}
240
+ transformAttributesSorted (dConfig .content .Body (), dConfig .content .Body ().Attributes (), transform )
257
241
for _ , block := range dConfig .content .Body ().Blocks () {
258
- blockAttrs := block .Body ().Attributes ()
259
- var blockAttrNames []string
260
- for name := range blockAttrs {
261
- blockAttrNames = append (blockAttrNames , name )
262
- }
263
- slices .Sort (blockAttrNames )
264
- for _ , name := range blockAttrNames {
265
- attr := blockAttrs [name ]
266
- expr := hcl .GetAttrExpr (attr )
267
- expr = replaceDynamicBlockReferences (expr , nRepSpecs , nSpec )
268
- block .Body ().SetAttributeRaw (name , hcl .TokensFromExpr (expr ))
269
- }
242
+ transformAttributesSorted (block .Body (), block .Body ().Attributes (), transform )
270
243
}
271
244
272
245
// Build the expression using HCL functions
@@ -278,22 +251,13 @@ func convertDynamicRepSpecsWithDynamicConfig(resourceb *hclwrite.Body, dSpec, dC
278
251
regionConfigBody := regionConfigFile .Body ()
279
252
280
253
// Copy all attributes in deterministic order
281
- configAttrs := dConfig .content .Body ().Attributes ()
282
- var configAttrNames []string
283
- for name := range configAttrs {
284
- configAttrNames = append (configAttrNames , name )
285
- }
286
- slices .Sort (configAttrNames )
287
- for _ , name := range configAttrNames {
288
- attr := configAttrs [name ]
289
- regionConfigBody .SetAttributeRaw (name , hcl .TokensFromExpr (hcl .GetAttrExpr (attr )))
290
- }
254
+ copyAttributesSorted (regionConfigBody , dConfig .content .Body ().Attributes ())
291
255
292
256
// Add all blocks generically as objects
293
257
processRegionConfigBlocks (regionConfigBody , dConfig .content .Body ().Blocks (), diskSizeGB )
294
258
295
259
// Build the region_configs for expression
296
- regionForExpr := fmt . Sprintf ( "for %s in %s :" , nRegion , configForEach )
260
+ regionForExpr := buildForExpression ( nRegion , configForEach )
297
261
regionTokens := hcl .TokensFromExpr (regionForExpr )
298
262
regionTokens = append (regionTokens , hcl .TokensObject (regionConfigBody )... )
299
263
@@ -309,12 +273,12 @@ func convertDynamicRepSpecsWithDynamicConfig(resourceb *hclwrite.Body, dSpec, dC
309
273
repSpecBody .SetAttributeRaw (nConfig , hcl .EncloseBracketsNewLines (regionTokens ))
310
274
311
275
// Build the inner for expression with range
312
- innerForExpr := fmt .Sprintf ("for i in range(%s) : " , numShardsExpr )
276
+ innerForExpr := buildForExpressionWithIndex ( "i" , fmt .Sprintf ("range(%s)" , numShardsExpr ) )
313
277
innerTokens := hcl .TokensFromExpr (innerForExpr )
314
278
innerTokens = append (innerTokens , hcl .TokensObject (repSpecBody )... )
315
279
316
280
// Build the outer for expression
317
- outerForExpr := fmt . Sprintf ( "for %s in %s : " , nSpec , hcl .GetAttrExpr (dSpec .forEach ))
281
+ outerForExpr := buildForExpression ( nSpec , hcl .GetAttrExpr (dSpec .forEach ))
318
282
outerTokens := hcl .TokensFromExpr (outerForExpr )
319
283
outerTokens = append (outerTokens , hcl .EncloseBracketsNewLines (innerTokens )... )
320
284
@@ -332,21 +296,14 @@ func convertDynamicRepSpecsWithDynamicConfig(resourceb *hclwrite.Body, dSpec, dC
332
296
// Helper function to add attributes with transformation
333
297
func addAttributesWithTransform (targetBody * hclwrite.Body , sourceAttrs map [string ]* hclwrite.Attribute ,
334
298
configBlockName string ) {
335
- // Sort attribute names for deterministic output
336
- var names []string
337
- for name := range sourceAttrs {
338
- names = append (names , name )
339
- }
340
- slices .Sort (names )
341
- for _ , name := range names {
342
- attr := sourceAttrs [name ]
343
- expr := hcl .GetAttrExpr (attr )
344
- // First replace nested dynamic block references
345
- expr = replaceDynamicBlockReferences (expr , configBlockName , nRegion )
346
- // Then replace outer dynamic block references
347
- expr = replaceDynamicBlockReferences (expr , nRepSpecs , nSpec )
348
- targetBody .SetAttributeRaw (name , hcl .TokensFromExpr (expr ))
299
+ // Apply transformations in order
300
+ transform1 := func (expr string ) string {
301
+ return replaceDynamicBlockReferences (expr , configBlockName , nRegion )
302
+ }
303
+ transform2 := func (expr string ) string {
304
+ return replaceDynamicBlockReferences (expr , nRepSpecs , nSpec )
349
305
}
306
+ transformAttributesSorted (targetBody , sourceAttrs , transform1 , transform2 )
350
307
}
351
308
352
309
func convertDynamicRepSpecsWithoutNumShards (resourceb * hclwrite.Body , dSpec , dConfig dynamicBlock ,
@@ -375,26 +332,22 @@ func convertDynamicRepSpecsWithoutNumShards(resourceb *hclwrite.Body, dSpec, dCo
375
332
}
376
333
377
334
// Process specs
378
- fillSpecOpt (configb , nElectableSpecs , diskSizeGB )
379
- fillSpecOpt (configb , nReadOnlySpecs , diskSizeGB )
380
- fillSpecOpt (configb , nAnalyticsSpecs , diskSizeGB )
381
- fillSpecOpt (configb , nAutoScaling , nil )
382
- fillSpecOpt (configb , nAnalyticsAutoScaling , nil )
335
+ processAllSpecs (configb , diskSizeGB )
383
336
384
337
// Build the nested for expression for region_configs
385
338
// Use standardized property name (region_configs) instead of the actual for_each collection
386
339
configForEach := fmt .Sprintf ("%s.%s" , nSpec , nConfig )
387
340
388
341
// Build the region_configs for expression
389
- regionForExpr := fmt . Sprintf ( "for %s in %s :" , nRegion , configForEach )
342
+ regionForExpr := buildForExpression ( nRegion , configForEach )
390
343
regionTokens := hcl .TokensFromExpr (regionForExpr )
391
344
regionTokens = append (regionTokens , hcl .TokensObject (configb )... )
392
345
393
346
repSpecb .SetAttributeRaw (nConfig , hcl .EncloseBracketsNewLines (regionTokens ))
394
347
395
348
// Build the for expression as an array wrapped in flatten
396
349
// Format: flatten([for spec in ... : [ { ... } ] ])
397
- forExpr := fmt . Sprintf ( "for %s in %s : " , nSpec , hcl .GetAttrExpr (dSpec .forEach ))
350
+ forExpr := buildForExpression ( nSpec , hcl .GetAttrExpr (dSpec .forEach ))
398
351
innerTokens := hcl .TokensFromExpr (forExpr )
399
352
innerTokens = append (innerTokens , hcl .TokensArraySingle (repSpecb )... )
400
353
@@ -432,11 +385,7 @@ func convertConfig(repSpecs *hclwrite.Body, diskSizeGB hclwrite.Tokens) error {
432
385
}
433
386
repSpecs .RemoveBlock (block )
434
387
blockb := block .Body ()
435
- fillSpecOpt (blockb , nElectableSpecs , diskSizeGB )
436
- fillSpecOpt (blockb , nReadOnlySpecs , diskSizeGB )
437
- fillSpecOpt (blockb , nAnalyticsSpecs , diskSizeGB )
438
- fillSpecOpt (blockb , nAutoScaling , nil ) // auto_scaling doesn't need disk_size_gb
439
- fillSpecOpt (blockb , nAnalyticsAutoScaling , nil ) // analytics_auto_scaling doesn't need disk_size_gb
388
+ processAllSpecs (blockb , diskSizeGB )
440
389
configs = append (configs , blockb )
441
390
}
442
391
if len (configs ) == 0 {
@@ -454,14 +403,10 @@ func convertDynamicConfig(repSpecs *hclwrite.Body, dConfig dynamicBlock, diskSiz
454
403
transformDynamicBlockReferencesRecursive (dConfig .content .Body (), blockName , nRegion )
455
404
456
405
// Process specs
457
- fillSpecOpt (dConfig .content .Body (), nElectableSpecs , diskSizeGB )
458
- fillSpecOpt (dConfig .content .Body (), nReadOnlySpecs , diskSizeGB )
459
- fillSpecOpt (dConfig .content .Body (), nAnalyticsSpecs , diskSizeGB )
460
- fillSpecOpt (dConfig .content .Body (), nAutoScaling , nil )
461
- fillSpecOpt (dConfig .content .Body (), nAnalyticsAutoScaling , nil )
406
+ processAllSpecs (dConfig .content .Body (), diskSizeGB )
462
407
463
408
// Build the for expression
464
- forExpr := fmt . Sprintf ( "for %s in %s :" , nRegion , hcl .GetAttrExpr (dConfig .forEach ))
409
+ forExpr := buildForExpression ( nRegion , hcl .GetAttrExpr (dConfig .forEach ))
465
410
tokens := hcl .TokensFromExpr (forExpr )
466
411
tokens = append (tokens , hcl .TokensObject (dConfig .content .Body ())... )
467
412
tokens = hcl .EncloseBracketsNewLines (tokens )
@@ -473,36 +418,17 @@ func convertDynamicConfig(repSpecs *hclwrite.Body, dConfig dynamicBlock, diskSiz
473
418
474
419
func transformDynamicBlockReferencesRecursive (body * hclwrite.Body , blockName , varName string ) {
475
420
// Transform attributes in deterministic order
476
- attrs := body .Attributes ()
477
- var names []string
478
- for name := range attrs {
479
- names = append (names , name )
480
- }
481
- slices .Sort (names )
482
- for _ , name := range names {
483
- attr := attrs [name ]
484
- expr := replaceDynamicBlockReferences (hcl .GetAttrExpr (attr ), blockName , varName )
485
- body .SetAttributeRaw (name , hcl .TokensFromExpr (expr ))
421
+ transform := func (expr string ) string {
422
+ return replaceDynamicBlockReferences (expr , blockName , varName )
486
423
}
424
+ transformAttributesSorted (body , body .Attributes (), transform )
425
+
487
426
// Transform nested blocks
488
427
for _ , block := range body .Blocks () {
489
428
transformDynamicBlockReferencesRecursive (block .Body (), blockName , varName )
490
429
}
491
430
}
492
431
493
- func fillSpecOpt (resourceb * hclwrite.Body , name string , diskSizeGBTokens hclwrite.Tokens ) {
494
- block := resourceb .FirstMatchingBlock (name , nil )
495
- if block == nil {
496
- return
497
- }
498
- if diskSizeGBTokens != nil {
499
- blockb := block .Body ()
500
- blockb .RemoveAttribute (nDiskSizeGB )
501
- blockb .SetAttributeRaw (nDiskSizeGB , diskSizeGBTokens )
502
- }
503
- fillBlockOpt (resourceb , name )
504
- }
505
-
506
432
// hasExpectedBlocksAsAttributes checks if any of the expected block names
507
433
// exist as attributes in the resource body. In that case conversion is not done
508
434
// as advanced cluster is not in a valid SDKv2 configuration.
0 commit comments