From 358797fb4f5cdbf3f00479fda5572c5f7cdd991c Mon Sep 17 00:00:00 2001 From: Leo Antoli <430982+lantoli@users.noreply.github.com> Date: Thu, 11 Sep 2025 16:32:29 +0200 Subject: [PATCH 1/6] move out comment examples --- ...luster_with_count.in.tf => comments.in.tf} | 9 ++-- ...ster_with_count.out.tf => comments.out.tf} | 9 ++-- .../testdata/clu2adv/free_cluster.in.tf | 22 ++++++++ .../testdata/clu2adv/free_cluster.out.tf | 52 +++++++++++++++++++ .../free_cluster_missing_attribute.in.tf | 21 ++------ 5 files changed, 89 insertions(+), 24 deletions(-) rename internal/convert/testdata/clu2adv/{free_cluster_with_count.in.tf => comments.in.tf} (83%) rename internal/convert/testdata/clu2adv/{free_cluster_with_count.out.tf => comments.out.tf} (88%) create mode 100644 internal/convert/testdata/clu2adv/free_cluster.in.tf create mode 100644 internal/convert/testdata/clu2adv/free_cluster.out.tf diff --git a/internal/convert/testdata/clu2adv/free_cluster_with_count.in.tf b/internal/convert/testdata/clu2adv/comments.in.tf similarity index 83% rename from internal/convert/testdata/clu2adv/free_cluster_with_count.in.tf rename to internal/convert/testdata/clu2adv/comments.in.tf index 4702169..d3f38e8 100644 --- a/internal/convert/testdata/clu2adv/free_cluster_with_count.in.tf +++ b/internal/convert/testdata/clu2adv/comments.in.tf @@ -1,7 +1,3 @@ -resource "resource1" "res1" { - name = "name1" -} - resource "mongodbatlas_cluster" "free_cluster" { # comment in the resource # comment in own line in the beginning count = local.use_free_cluster ? 1 : 0 @@ -14,3 +10,8 @@ resource "mongodbatlas_cluster" "free_cluster" { # comment in the resource provider_instance_size_name = "M0" # comment in own line at the end happens before replication_specs } + +resource "another_resource" "res1" { + # comment in own line in the middle is not deleted in unprocessed resource + name = "name1" +} diff --git a/internal/convert/testdata/clu2adv/free_cluster_with_count.out.tf b/internal/convert/testdata/clu2adv/comments.out.tf similarity index 88% rename from internal/convert/testdata/clu2adv/free_cluster_with_count.out.tf rename to internal/convert/testdata/clu2adv/comments.out.tf index c7dbdbf..8a689a4 100644 --- a/internal/convert/testdata/clu2adv/free_cluster_with_count.out.tf +++ b/internal/convert/testdata/clu2adv/comments.out.tf @@ -1,7 +1,3 @@ -resource "resource1" "res1" { - name = "name1" -} - resource "mongodbatlas_advanced_cluster" "free_cluster" { # comment in the resource # comment in own line in the beginning count = local.use_free_cluster ? 1 : 0 @@ -28,3 +24,8 @@ resource "mongodbatlas_advanced_cluster" "free_cluster" { # comment in the resou # Generated by atlas-cli-plugin-terraform. # Please review the changes and confirm that references to this resource are updated. } + +resource "another_resource" "res1" { + # comment in own line in the middle is not deleted in unprocessed resource + name = "name1" +} diff --git a/internal/convert/testdata/clu2adv/free_cluster.in.tf b/internal/convert/testdata/clu2adv/free_cluster.in.tf new file mode 100644 index 0000000..a317811 --- /dev/null +++ b/internal/convert/testdata/clu2adv/free_cluster.in.tf @@ -0,0 +1,22 @@ +resource "mongodbatlas_cluster" "free_cluster" { + project_id = var.project_id + name = var.cluster_name + provider_name = "TENANT" + backing_provider_name = "AWS" + provider_region_name = var.region + provider_instance_size_name = "M0" +} + +resource "mongodbatlas_cluster" "count" { + count = local.use_free_cluster ? 1 : 0 + project_id = var.project_id + name = var.cluster_name + provider_name = "TENANT" + backing_provider_name = "AWS" + provider_region_name = var.region + provider_instance_size_name = "M0" +} + +resource "another_resource" "res1" { + name = "name1" +} diff --git a/internal/convert/testdata/clu2adv/free_cluster.out.tf b/internal/convert/testdata/clu2adv/free_cluster.out.tf new file mode 100644 index 0000000..9d40780 --- /dev/null +++ b/internal/convert/testdata/clu2adv/free_cluster.out.tf @@ -0,0 +1,52 @@ +resource "mongodbatlas_advanced_cluster" "free_cluster" { + project_id = var.project_id + name = var.cluster_name + cluster_type = "REPLICASET" + replication_specs = [ + { + region_configs = [ + { + priority = 7 + region_name = var.region + provider_name = "TENANT" + backing_provider_name = "AWS" + electable_specs = { + instance_size = "M0" + } + } + ] + } + ] + + # Generated by atlas-cli-plugin-terraform. + # Please review the changes and confirm that references to this resource are updated. +} + +resource "mongodbatlas_advanced_cluster" "count" { + count = local.use_free_cluster ? 1 : 0 + project_id = var.project_id + name = var.cluster_name + cluster_type = "REPLICASET" + replication_specs = [ + { + region_configs = [ + { + priority = 7 + region_name = var.region + provider_name = "TENANT" + backing_provider_name = "AWS" + electable_specs = { + instance_size = "M0" + } + } + ] + } + ] + + # Generated by atlas-cli-plugin-terraform. + # Please review the changes and confirm that references to this resource are updated. +} + +resource "another_resource" "res1" { + name = "name1" +} diff --git a/internal/convert/testdata/clu2adv/free_cluster_missing_attribute.in.tf b/internal/convert/testdata/clu2adv/free_cluster_missing_attribute.in.tf index 2f17b21..50ed2c1 100644 --- a/internal/convert/testdata/clu2adv/free_cluster_missing_attribute.in.tf +++ b/internal/convert/testdata/clu2adv/free_cluster_missing_attribute.in.tf @@ -1,19 +1,8 @@ -resource "resource1" "res1" { - name = "name1" -} - -resource "mongodbatlas_cluster" "free_cluster" { # comment in the resource - # comment in own line in the beginning - count = local.use_free_cluster ? 1 : 0 - project_id = var.project_id # inline comment kept - name = var.cluster_name - # comment in own line in the middle is deleted - provider_name = "TENANT" # inline comment for attribute moved is not kept +resource "mongodbatlas_cluster" "free_cluster" { + project_id = var.project_id + name = var.cluster_name + provider_name = "TENANT" provider_region_name = var.region provider_instance_size_name = "M0" - # comment in own line at the end happens before replication_specs -} - -data "mongodbatlas_cluster" "cluster2" { - name = "name4" + # missing backing_provider_name } From 48eb5d056cf2342fe2aa9e990f2ce398bc505d38 Mon Sep 17 00:00:00 2001 From: Leo Antoli <430982+lantoli@users.noreply.github.com> Date: Thu, 11 Sep 2025 16:43:59 +0200 Subject: [PATCH 2/6] failing tests with feature to implement --- .../testdata/clu2adv/free_cluster.in.tf | 20 ++++++++ .../testdata/clu2adv/free_cluster.out.tf | 46 +++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/internal/convert/testdata/clu2adv/free_cluster.in.tf b/internal/convert/testdata/clu2adv/free_cluster.in.tf index a317811..0e62d39 100644 --- a/internal/convert/testdata/clu2adv/free_cluster.in.tf +++ b/internal/convert/testdata/clu2adv/free_cluster.in.tf @@ -17,6 +17,26 @@ resource "mongodbatlas_cluster" "count" { provider_instance_size_name = "M0" } + +resource "mongodbatlas_cluster" "upgrade_from_free_cluster" { + # upgraded free cluster to dedicated + project_id = var.project_id + name = var.cluster_name + provider_name = "AWS" # changed from TENANT to AWS + provider_instance_size_name = "M10" # changed from M0 to M10 + # removed backing_provider_name = AWS" + provider_region_name = var.region +} + +resource "mongodbatlas_cluster" "upgrade_from_free_cluster_with_variables" { + # upgraded free cluster to dedicated, using variables in all attributes + project_id = var.project_id + name = var.cluster_name + provider_name = var.provider_name + provider_instance_size_name = var.instance_size + provider_region_name = var.region +} + resource "another_resource" "res1" { name = "name1" } diff --git a/internal/convert/testdata/clu2adv/free_cluster.out.tf b/internal/convert/testdata/clu2adv/free_cluster.out.tf index 9d40780..7fece6a 100644 --- a/internal/convert/testdata/clu2adv/free_cluster.out.tf +++ b/internal/convert/testdata/clu2adv/free_cluster.out.tf @@ -47,6 +47,52 @@ resource "mongodbatlas_advanced_cluster" "count" { # Please review the changes and confirm that references to this resource are updated. } +resource "mongodbatlas_advanced_cluster" "upgrade_from_free_cluster" { + project_id = var.project_id + name = var.cluster_name + cluster_type = "REPLICASET" + replication_specs = [ + { + region_configs = [ + { + priority = 7 + region_name = var.region + provider_name = "AWS" + electable_specs = { + instance_size = "M10" + } + } + ] + } + ] + + # Generated by atlas-cli-plugin-terraform. + # Please review the changes and confirm that references to this resource are updated. +} + +resource "mongodbatlas_advanced_cluster" "upgrade_from_free_cluster_with_variables" { + project_id = var.project_id + name = var.cluster_name + cluster_type = "REPLICASET" + replication_specs = [ + { + region_configs = [ + { + priority = 7 + region_name = var.region + provider_name = var.provider_name + electable_specs = { + instance_size = var.instance_size + } + } + ] + } + ] + + # Generated by atlas-cli-plugin-terraform. + # Please review the changes and confirm that references to this resource are updated. +} + resource "another_resource" "res1" { name = "name1" } From a80db2417f9a76f694da9b2860ac756b78654a91 Mon Sep 17 00:00:00 2001 From: Leo Antoli <430982+lantoli@users.noreply.github.com> Date: Thu, 11 Sep 2025 16:47:33 +0200 Subject: [PATCH 3/6] free cluster if providerName == "TENANT" --- internal/convert/clu2adv.go | 4 ++-- internal/convert/const.go | 1 + internal/convert/testdata/adv2v2/errors.json | 1 - .../convert/testdata/adv2v2/missing_replication_specs.in.tf | 6 ------ 4 files changed, 3 insertions(+), 9 deletions(-) delete mode 100644 internal/convert/testdata/adv2v2/missing_replication_specs.in.tf diff --git a/internal/convert/clu2adv.go b/internal/convert/clu2adv.go index 914ef64..9ad5d35 100644 --- a/internal/convert/clu2adv.go +++ b/internal/convert/clu2adv.go @@ -69,8 +69,8 @@ func convertResource(block *hclwrite.Block) (bool, error) { } func isFreeTierCluster(resourceb *hclwrite.Body) bool { - d, _ := getDynamicBlock(resourceb, nRepSpecs, true) - return resourceb.FirstMatchingBlock(nRepSpecs, nil) == nil && !d.IsPresent() + providerName, _ := hcl.GetAttrString(resourceb.GetAttribute(nProviderName)) + return providerName == nTenant } func convertDataSource(block *hclwrite.Block) bool { diff --git a/internal/convert/const.go b/internal/convert/const.go index 350f210..74670c5 100644 --- a/internal/convert/const.go +++ b/internal/convert/const.go @@ -80,4 +80,5 @@ const ( nSpec = "spec" nFailIndexKeyTooLong = "fail_index_key_too_long" nDefaultReadConcern = "default_read_concern" + nTenant = "TENANT" ) diff --git a/internal/convert/testdata/adv2v2/errors.json b/internal/convert/testdata/adv2v2/errors.json index a744913..e956619 100644 --- a/internal/convert/testdata/adv2v2/errors.json +++ b/internal/convert/testdata/adv2v2/errors.json @@ -1,7 +1,6 @@ { "configuration_file_error": "failed to parse Terraform config file", "replication_specs_missing_region_configs": "replication_specs must have at least one region_configs", - "missing_replication_specs": "must have at least one replication_specs", "dynamic_unsupported_tag": "dynamic blocks are not supported for advanced_configuration", "dynamic_regions_config_invalid_multiple_blocks": "dynamic block must be the only block", "dynamic_replication_specs_invalid_multiple_blocks": "dynamic block must be the only block", diff --git a/internal/convert/testdata/adv2v2/missing_replication_specs.in.tf b/internal/convert/testdata/adv2v2/missing_replication_specs.in.tf deleted file mode 100644 index 247a176..0000000 --- a/internal/convert/testdata/adv2v2/missing_replication_specs.in.tf +++ /dev/null @@ -1,6 +0,0 @@ -resource "mongodbatlas_advanced_cluster" "no_replication_specs" { - # missing replication_specs - project_id = var.project_id - name = "cluster-multi-region" - cluster_type = "REPLICASET" -} From 77d12d0724cbda9ad7de355023f67a4f214c8bf0 Mon Sep 17 00:00:00 2001 From: Leo Antoli <430982+lantoli@users.noreply.github.com> Date: Thu, 11 Sep 2025 18:47:31 +0200 Subject: [PATCH 4/6] implementation --- internal/convert/clu2adv.go | 28 +++++++++++++++++- internal/convert/const.go | 29 ++++++++++--------- .../testdata/clu2adv/free_cluster.out.tf | 5 ++++ 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/internal/convert/clu2adv.go b/internal/convert/clu2adv.go index 9ad5d35..9187f63 100644 --- a/internal/convert/clu2adv.go +++ b/internal/convert/clu2adv.go @@ -107,6 +107,32 @@ func fillMovedBlocks(body *hclwrite.Body, moveLabels []string) { } } +// createDefaultReplicationSpec creates a default replication_specs for clusters without any +// (e.g. upgraded from free tier). +func createDefaultReplicationSpec(resourceb *hclwrite.Body, root attrVals) error { + resourceb.SetAttributeValue(nClusterType, cty.StringVal(valClusterType)) + configb := hclwrite.NewEmptyFile().Body() + hcl.SetAttrInt(configb, nPriority, valMaxPriority) + if err := hcl.MoveAttr(resourceb, configb, nRegionNameSrc, nRegionName, errRoot); err != nil { + return err + } + if providerNameTokens, found := root.req[nProviderName]; found { + configb.SetAttributeRaw(nProviderName, providerNameTokens) + } + + electableSpecb := hclwrite.NewEmptyFile().Body() + if instanceSizeTokens, found := root.req[nInstanceSizeSrc]; found { + electableSpecb.SetAttributeRaw(nInstanceSize, instanceSizeTokens) + } + electableSpecb.SetAttributeValue(nNodeCount, cty.NumberIntVal(valDefaultNodeCount)) + configb.SetAttributeRaw(nElectableSpecs, hcl.TokensObject(electableSpecb)) + + repSpecsb := hclwrite.NewEmptyFile().Body() + repSpecsb.SetAttributeRaw(nConfig, hcl.TokensArraySingle(configb)) + resourceb.SetAttributeRaw(nRepSpecs, hcl.TokensArraySingle(repSpecsb)) + return nil +} + // fillFreeTierCluster is the entry point to convert clusters in free tier func processFreeTierCluster(resourceb *hclwrite.Body) error { resourceb.SetAttributeValue(nClusterType, cty.StringVal(valClusterType)) @@ -160,7 +186,7 @@ func processRepSpecsCluster(resourceb *hclwrite.Body, root attrVals) error { } repSpecBlocks := collectBlocks(resourceb, nRepSpecs) if len(repSpecBlocks) == 0 { - return fmt.Errorf("must have at least one replication_specs") + return createDefaultReplicationSpec(resourceb, root) } dConfig, err := processConfigsWithDynamicRegion(repSpecBlocks[0].Body(), root, false) if err != nil { diff --git a/internal/convert/const.go b/internal/convert/const.go index 74670c5..2337ea6 100644 --- a/internal/convert/const.go +++ b/internal/convert/const.go @@ -1,20 +1,21 @@ package convert const ( - resourceType = "resource" - dataSourceType = "data" - cluster = "mongodbatlas_cluster" - advCluster = "mongodbatlas_advanced_cluster" - clusterPlural = "mongodbatlas_clusters" - advClusterPlural = "mongodbatlas_advanced_clusters" - valClusterType = "REPLICASET" - valMaxPriority = 7 - valMinPriority = 0 - errFreeCluster = "free cluster (because no " + nRepSpecs + ")" - errRepSpecs = "setting " + nRepSpecs - errPriority = "setting " + nPriority - errNumShards = "setting " + nNumShards - errRoot = "setting root attributes" + resourceType = "resource" + dataSourceType = "data" + cluster = "mongodbatlas_cluster" + advCluster = "mongodbatlas_advanced_cluster" + clusterPlural = "mongodbatlas_clusters" + advClusterPlural = "mongodbatlas_advanced_clusters" + valClusterType = "REPLICASET" + valMaxPriority = 7 + valMinPriority = 0 + valDefaultNodeCount = 3 + errFreeCluster = "free cluster (because no " + nRepSpecs + ")" + errRepSpecs = "setting " + nRepSpecs + errPriority = "setting " + nPriority + errNumShards = "setting " + nNumShards + errRoot = "setting root attributes" commentGeneratedBy = "Generated by atlas-cli-plugin-terraform." commentConfirmReferences = "Please review the changes and confirm that references to this resource are updated." diff --git a/internal/convert/testdata/clu2adv/free_cluster.out.tf b/internal/convert/testdata/clu2adv/free_cluster.out.tf index 7fece6a..6cd06ee 100644 --- a/internal/convert/testdata/clu2adv/free_cluster.out.tf +++ b/internal/convert/testdata/clu2adv/free_cluster.out.tf @@ -47,7 +47,9 @@ resource "mongodbatlas_advanced_cluster" "count" { # Please review the changes and confirm that references to this resource are updated. } + resource "mongodbatlas_advanced_cluster" "upgrade_from_free_cluster" { + # upgraded free cluster to dedicated project_id = var.project_id name = var.cluster_name cluster_type = "REPLICASET" @@ -60,6 +62,7 @@ resource "mongodbatlas_advanced_cluster" "upgrade_from_free_cluster" { provider_name = "AWS" electable_specs = { instance_size = "M10" + node_count = 3 } } ] @@ -71,6 +74,7 @@ resource "mongodbatlas_advanced_cluster" "upgrade_from_free_cluster" { } resource "mongodbatlas_advanced_cluster" "upgrade_from_free_cluster_with_variables" { + # upgraded free cluster to dedicated, using variables in all attributes project_id = var.project_id name = var.cluster_name cluster_type = "REPLICASET" @@ -83,6 +87,7 @@ resource "mongodbatlas_advanced_cluster" "upgrade_from_free_cluster_with_variabl provider_name = var.provider_name electable_specs = { instance_size = var.instance_size + node_count = 3 } } ] From 8f784c3969f1458f80d39f256bd48b9e7383bc69 Mon Sep 17 00:00:00 2001 From: Leo Antoli <430982+lantoli@users.noreply.github.com> Date: Thu, 11 Sep 2025 18:54:22 +0200 Subject: [PATCH 5/6] undo changes in adv2v2 --- internal/convert/testdata/adv2v2/errors.json | 1 + .../convert/testdata/adv2v2/missing_replication_specs.in.tf | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 internal/convert/testdata/adv2v2/missing_replication_specs.in.tf diff --git a/internal/convert/testdata/adv2v2/errors.json b/internal/convert/testdata/adv2v2/errors.json index e956619..a744913 100644 --- a/internal/convert/testdata/adv2v2/errors.json +++ b/internal/convert/testdata/adv2v2/errors.json @@ -1,6 +1,7 @@ { "configuration_file_error": "failed to parse Terraform config file", "replication_specs_missing_region_configs": "replication_specs must have at least one region_configs", + "missing_replication_specs": "must have at least one replication_specs", "dynamic_unsupported_tag": "dynamic blocks are not supported for advanced_configuration", "dynamic_regions_config_invalid_multiple_blocks": "dynamic block must be the only block", "dynamic_replication_specs_invalid_multiple_blocks": "dynamic block must be the only block", diff --git a/internal/convert/testdata/adv2v2/missing_replication_specs.in.tf b/internal/convert/testdata/adv2v2/missing_replication_specs.in.tf new file mode 100644 index 0000000..247a176 --- /dev/null +++ b/internal/convert/testdata/adv2v2/missing_replication_specs.in.tf @@ -0,0 +1,6 @@ +resource "mongodbatlas_advanced_cluster" "no_replication_specs" { + # missing replication_specs + project_id = var.project_id + name = "cluster-multi-region" + cluster_type = "REPLICASET" +} From 7331af6dd96998b1a25c5fde025ceca6d5537667 Mon Sep 17 00:00:00 2001 From: Leo Antoli <430982+lantoli@users.noreply.github.com> Date: Fri, 12 Sep 2025 07:06:18 +0200 Subject: [PATCH 6/6] rename --- internal/convert/clu2adv.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/convert/clu2adv.go b/internal/convert/clu2adv.go index 9187f63..63862ee 100644 --- a/internal/convert/clu2adv.go +++ b/internal/convert/clu2adv.go @@ -107,9 +107,9 @@ func fillMovedBlocks(body *hclwrite.Body, moveLabels []string) { } } -// createDefaultReplicationSpec creates a default replication_specs for clusters without any +// createDefaultRepSpec creates a default replication_specs for clusters without any // (e.g. upgraded from free tier). -func createDefaultReplicationSpec(resourceb *hclwrite.Body, root attrVals) error { +func createDefaultRepSpec(resourceb *hclwrite.Body, root attrVals) error { resourceb.SetAttributeValue(nClusterType, cty.StringVal(valClusterType)) configb := hclwrite.NewEmptyFile().Body() hcl.SetAttrInt(configb, nPriority, valMaxPriority) @@ -186,7 +186,7 @@ func processRepSpecsCluster(resourceb *hclwrite.Body, root attrVals) error { } repSpecBlocks := collectBlocks(resourceb, nRepSpecs) if len(repSpecBlocks) == 0 { - return createDefaultReplicationSpec(resourceb, root) + return createDefaultRepSpec(resourceb, root) } dConfig, err := processConfigsWithDynamicRegion(repSpecBlocks[0].Body(), root, false) if err != nil {