Skip to content

Commit 658e124

Browse files
committed
allow different names
1 parent e2b2c9f commit 658e124

File tree

3 files changed

+221
-70
lines changed

3 files changed

+221
-70
lines changed

internal/convert/adv2v2.go

Lines changed: 123 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,55 @@ func convertDynamicRepSpecs(resourceb *hclwrite.Body, dSpec dynamicBlock, diskSi
200200
return nil
201201
}
202202

203+
// Helper function to add attributes in order
204+
func addAttributesInOrder(targetBody *hclwrite.Body, sourceAttrs map[string]*hclwrite.Attribute,
205+
orderedNames []string) {
206+
// Add ordered attributes first
207+
for _, name := range orderedNames {
208+
if attr, exists := sourceAttrs[name]; exists {
209+
targetBody.SetAttributeRaw(name, hcl.TokensFromExpr(hcl.GetAttrExpr(attr)))
210+
}
211+
}
212+
213+
// Add any remaining attributes alphabetically
214+
var remainingAttrs []string
215+
for name := range sourceAttrs {
216+
found := false
217+
for _, orderedName := range orderedNames {
218+
if name == orderedName {
219+
found = true
220+
break
221+
}
222+
}
223+
if !found {
224+
remainingAttrs = append(remainingAttrs, name)
225+
}
226+
}
227+
slices.Sort(remainingAttrs)
228+
for _, name := range remainingAttrs {
229+
attr := sourceAttrs[name]
230+
targetBody.SetAttributeRaw(name, hcl.TokensFromExpr(hcl.GetAttrExpr(attr)))
231+
}
232+
}
233+
234+
// Helper function to process blocks for region configs
235+
func processRegionConfigBlocks(targetBody *hclwrite.Body, blocks []*hclwrite.Block) {
236+
for _, block := range blocks {
237+
blockType := block.Type()
238+
blockFile := hclwrite.NewEmptyFile()
239+
blockBody := blockFile.Body()
240+
241+
// For electable_specs, use specific order: instance_size, node_count
242+
var attrOrder []string
243+
if blockType == "electable_specs" {
244+
attrOrder = []string{"instance_size", "node_count"}
245+
}
246+
247+
addAttributesInOrder(blockBody, block.Body().Attributes(), attrOrder)
248+
targetBody.SetAttributeRaw(blockType, hcl.TokensObject(blockBody))
249+
}
250+
}
251+
203252
func convertDynamicRepSpecsWithDynamicConfig(resourceb *hclwrite.Body, dSpec, dConfig dynamicBlock,
204253
diskSizeGB hclwrite.Tokens) error {
205254
// Get the block name from the dynamic block
@@ -226,51 +275,20 @@ func convertDynamicRepSpecsWithDynamicConfig(resourceb *hclwrite.Body, dSpec, dC
226275
}
227276
}
228277

229-
// Don't convert specs blocks to attributes - we'll handle them manually in the string building
230-
231278
// Build the expression using HCL functions
232-
configForEach := replaceDynamicBlockReferences(hcl.GetAttrExpr(dConfig.forEach), nRepSpecs, nSpec)
279+
// Use standardized property name (region_configs) instead of the actual for_each collection
280+
configForEach := fmt.Sprintf("%s.%s", nSpec, nConfig)
233281

234282
// Create the inner region_configs body
235283
regionConfigFile := hclwrite.NewEmptyFile()
236284
regionConfigBody := regionConfigFile.Body()
237285

238-
// Add all attributes generically in alphabetical order
239-
attrs := dConfig.content.Body().Attributes()
240-
attrNames := make([]string, 0, len(attrs))
241-
for name := range attrs {
242-
attrNames = append(attrNames, name)
243-
}
244-
slices.Sort(attrNames)
245-
246-
for _, name := range attrNames {
247-
attr := attrs[name]
248-
regionConfigBody.SetAttributeRaw(name, hcl.TokensFromExpr(hcl.GetAttrExpr(attr)))
249-
}
286+
// Add attributes in a specific order for consistency
287+
orderedAttrs := []string{"priority", "provider_name", "region_name"}
288+
addAttributesInOrder(regionConfigBody, dConfig.content.Body().Attributes(), orderedAttrs)
250289

251290
// Add all blocks generically as objects
252-
for _, block := range dConfig.content.Body().Blocks() {
253-
blockType := block.Type()
254-
255-
// Create a new body for the block
256-
blockFile := hclwrite.NewEmptyFile()
257-
blockBody := blockFile.Body()
258-
259-
// Add block attributes in alphabetical order
260-
blockAttrs := block.Body().Attributes()
261-
blockAttrNames := make([]string, 0, len(blockAttrs))
262-
for name := range blockAttrs {
263-
blockAttrNames = append(blockAttrNames, name)
264-
}
265-
slices.Sort(blockAttrNames)
266-
267-
for _, attrName := range blockAttrNames {
268-
attr := blockAttrs[attrName]
269-
blockBody.SetAttributeRaw(attrName, hcl.TokensFromExpr(hcl.GetAttrExpr(attr)))
270-
}
271-
272-
regionConfigBody.SetAttributeRaw(blockType, hcl.TokensObject(blockBody))
273-
}
291+
processRegionConfigBlocks(regionConfigBody, dConfig.content.Body().Blocks())
274292

275293
// Build the region_configs for expression
276294
regionForExpr := fmt.Sprintf("for %s in %s :", nRegion, configForEach)
@@ -306,8 +324,46 @@ func convertDynamicRepSpecsWithDynamicConfig(resourceb *hclwrite.Body, dSpec, dC
306324
return nil
307325
}
308326
// No num_shards, handle like without nested shards
309-
// Reuse the block name from the dynamic block that was already obtained
327+
return convertDynamicRepSpecsWithoutNumShards(resourceb, dSpec, dConfig, diskSizeGB, configBlockName)
328+
}
310329

330+
// Helper function to add attributes with transformation
331+
func addAttributesWithTransform(targetBody *hclwrite.Body, sourceAttrs map[string]*hclwrite.Attribute,
332+
orderedNames []string, configBlockName string, transformFunc func(string) string) {
333+
// Add ordered attributes first
334+
for _, name := range orderedNames {
335+
if attr, exists := sourceAttrs[name]; exists {
336+
expr := hcl.GetAttrExpr(attr)
337+
// First replace nested dynamic block references
338+
expr = replaceDynamicBlockReferences(expr, configBlockName, nRegion)
339+
// Then replace outer dynamic block references
340+
expr = replaceDynamicBlockReferences(expr, nRepSpecs, nSpec)
341+
targetBody.SetAttributeRaw(name, hcl.TokensFromExpr(expr))
342+
}
343+
}
344+
345+
// Add any remaining attributes
346+
for name, attr := range sourceAttrs {
347+
found := false
348+
for _, orderedName := range orderedNames {
349+
if name == orderedName {
350+
found = true
351+
break
352+
}
353+
}
354+
if !found {
355+
expr := hcl.GetAttrExpr(attr)
356+
// First replace nested dynamic block references
357+
expr = replaceDynamicBlockReferences(expr, configBlockName, nRegion)
358+
// Then replace outer dynamic block references
359+
expr = replaceDynamicBlockReferences(expr, nRepSpecs, nSpec)
360+
targetBody.SetAttributeRaw(name, hcl.TokensFromExpr(expr))
361+
}
362+
}
363+
}
364+
365+
func convertDynamicRepSpecsWithoutNumShards(resourceb *hclwrite.Body, dSpec, dConfig dynamicBlock,
366+
diskSizeGB hclwrite.Tokens, configBlockName string) error {
311367
// Get zone_name if present
312368
repSpecFile := hclwrite.NewEmptyFile()
313369
repSpecb := repSpecFile.Body()
@@ -321,28 +377,22 @@ func convertDynamicRepSpecsWithDynamicConfig(resourceb *hclwrite.Body, dSpec, dC
321377
configFile := hclwrite.NewEmptyFile()
322378
configb := configFile.Body()
323379

324-
// Copy and transform attributes
325-
for name, attr := range dConfig.content.Body().Attributes() {
326-
expr := hcl.GetAttrExpr(attr)
327-
// First replace nested dynamic block references
328-
expr = replaceDynamicBlockReferences(expr, configBlockName, nRegion)
329-
// Then replace outer dynamic block references
330-
expr = replaceDynamicBlockReferences(expr, nRepSpecs, nSpec)
331-
configb.SetAttributeRaw(name, hcl.TokensFromExpr(expr))
332-
}
380+
// Copy and transform attributes in a specific order for consistency
381+
orderedAttrs := []string{"priority", "provider_name", "region_name"}
382+
addAttributesWithTransform(configb, dConfig.content.Body().Attributes(), orderedAttrs, configBlockName, nil)
333383

334384
// Process blocks and transform their references
335385
for _, block := range dConfig.content.Body().Blocks() {
336386
newBlock := configb.AppendNewBlock(block.Type(), block.Labels())
337387
newBlockb := newBlock.Body()
338-
for name, attr := range block.Body().Attributes() {
339-
expr := hcl.GetAttrExpr(attr)
340-
// First replace nested dynamic block references
341-
expr = replaceDynamicBlockReferences(expr, configBlockName, nRegion)
342-
// Then replace outer dynamic block references
343-
expr = replaceDynamicBlockReferences(expr, nRepSpecs, nSpec)
344-
newBlockb.SetAttributeRaw(name, hcl.TokensFromExpr(expr))
388+
389+
// Order attributes for consistency
390+
var attrOrder []string
391+
if block.Type() == "electable_specs" {
392+
attrOrder = []string{"instance_size", "node_count"}
345393
}
394+
395+
addAttributesWithTransform(newBlockb, block.Body().Attributes(), attrOrder, configBlockName, nil)
346396
}
347397

348398
// Process specs
@@ -353,22 +403,25 @@ func convertDynamicRepSpecsWithDynamicConfig(resourceb *hclwrite.Body, dSpec, dC
353403
fillSpecOpt(configb, nAnalyticsAutoScaling, nil)
354404

355405
// Build the nested for expression for region_configs
356-
configForEach := replaceDynamicBlockReferences(hcl.GetAttrExpr(dConfig.forEach), nRepSpecs, nSpec)
357-
var regionTokens2 hclwrite.Tokens
358-
regionTokens2 = append(regionTokens2, hcl.TokensFromExpr("[\n")...)
359-
forExpr := fmt.Sprintf(" for %s in %s : ", nRegion, configForEach)
360-
regionTokens2 = append(regionTokens2, hcl.TokensFromExpr(forExpr)...)
361-
regionTokens2 = append(regionTokens2, hcl.TokensObject(configb)...)
362-
regionTokens2 = append(regionTokens2, hcl.TokensFromExpr("\n ]")...)
363-
repSpecb.SetAttributeRaw(nConfig, regionTokens2)
364-
365-
// Build the for expression without range
366-
var tokens hclwrite.Tokens
367-
tokens = append(tokens, hcl.TokensFromExpr("[\n")...)
368-
specForExpr := fmt.Sprintf(" for %s in %s : ", nSpec, hcl.GetAttrExpr(dSpec.forEach))
369-
tokens = append(tokens, hcl.TokensFromExpr(specForExpr)...)
370-
tokens = append(tokens, hcl.TokensObject(repSpecb)...)
371-
tokens = append(tokens, hcl.TokensFromExpr("\n ]")...)
406+
// Use standardized property name (region_configs) instead of the actual for_each collection
407+
configForEach := fmt.Sprintf("%s.%s", nSpec, nConfig)
408+
409+
// Build the region_configs for expression
410+
regionForExpr := fmt.Sprintf("for %s in %s :", nRegion, configForEach)
411+
regionTokens := hcl.TokensFromExpr(regionForExpr)
412+
regionTokens = append(regionTokens, hcl.TokensObject(configb)...)
413+
414+
repSpecb.SetAttributeRaw(nConfig, hcl.EncloseBracketsNewLines(regionTokens))
415+
416+
// Build the for expression as an array wrapped in flatten
417+
// Format: flatten([for spec in ... : [ { ... } ] ])
418+
forExpr := fmt.Sprintf("for %s in %s : [\n ", nSpec, hcl.GetAttrExpr(dSpec.forEach))
419+
innerTokens := hcl.TokensFromExpr(forExpr)
420+
innerTokens = append(innerTokens, hcl.TokensObject(repSpecb)...)
421+
innerTokens = append(innerTokens, hcl.TokensFromExpr("\n ]")...)
422+
423+
// Apply flatten to the entire expression
424+
tokens := hcl.TokensFuncFlatten(innerTokens)
372425

373426
resourceb.RemoveBlock(dSpec.block)
374427
resourceb.SetAttributeRaw(nRepSpecs, tokens)
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
resource "mongodbatlas_advanced_cluster" "different_var_names" {
2+
project_id = var.project_id
3+
name = var.cluster_name
4+
cluster_type = var.cluster_type
5+
dynamic "replication_specs" {
6+
for_each = var.my_rep_specs
7+
content {
8+
num_shards = replication_specs.value.my_shards
9+
zone_name = replication_specs.value.my_zone
10+
11+
dynamic "region_configs" {
12+
for_each = replication_specs.value.my_regions
13+
content {
14+
priority = region_configs.value.prio
15+
provider_name = region_configs.value.provider_name
16+
region_name = region_configs.value.my_region_name
17+
electable_specs {
18+
instance_size = region_configs.value.instance_size
19+
node_count = region_configs.value.my_electable_node_count
20+
}
21+
}
22+
}
23+
}
24+
}
25+
}
26+
27+
resource "mongodbatlas_advanced_cluster" "different_var_names_no_zone_name_no_num_shards" {
28+
project_id = var.project_id
29+
name = var.cluster_name
30+
cluster_type = var.cluster_type
31+
dynamic "replication_specs" {
32+
for_each = var.my_rep_specs
33+
content {
34+
dynamic "region_configs" {
35+
for_each = replication_specs.value.my_regions
36+
content {
37+
priority = region_configs.value.prio
38+
provider_name = region_configs.value.provider_name
39+
region_name = region_configs.value.my_region_name
40+
electable_specs {
41+
instance_size = region_configs.value.instance_size
42+
node_count = region_configs.value.my_electable_node_count
43+
}
44+
}
45+
}
46+
}
47+
}
48+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
resource "mongodbatlas_advanced_cluster" "different_var_names" {
2+
project_id = var.project_id
3+
name = var.cluster_name
4+
cluster_type = var.cluster_type
5+
replication_specs = flatten([
6+
for spec in var.my_rep_specs : [
7+
for i in range(spec.my_shards) : {
8+
zone_name = spec.my_zone
9+
region_configs = [
10+
for region in spec.region_configs : {
11+
priority = region.prio
12+
provider_name = region.provider_name
13+
region_name = region.my_region_name
14+
electable_specs = {
15+
instance_size = region.instance_size
16+
node_count = region.my_electable_node_count
17+
}
18+
}
19+
]
20+
}
21+
]
22+
])
23+
24+
# Updated by atlas-cli-plugin-terraform, please review the changes.
25+
}
26+
27+
resource "mongodbatlas_advanced_cluster" "different_var_names_no_zone_name_no_num_shards" {
28+
project_id = var.project_id
29+
name = var.cluster_name
30+
cluster_type = var.cluster_type
31+
replication_specs = flatten([
32+
for spec in var.my_rep_specs : [
33+
{
34+
region_configs = [
35+
for region in spec.region_configs : {
36+
priority = region.prio
37+
provider_name = region.provider_name
38+
region_name = region.my_region_name
39+
electable_specs = {
40+
instance_size = region.instance_size
41+
node_count = region.my_electable_node_count
42+
}
43+
}
44+
]
45+
}
46+
]
47+
])
48+
49+
# Updated by atlas-cli-plugin-terraform, please review the changes.
50+
}

0 commit comments

Comments
 (0)