Skip to content
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
1459a03
initial doc
lantoli Aug 25, 2025
da42d28
remove guide_clu2adv_dynamic_block
lantoli Aug 25, 2025
e27d5a4
move info in file guide_adv2v2_dynamic_block.md to command_adv2v2.md
lantoli Aug 25, 2025
0ec0ed7
update clu2adv doc
lantoli Aug 26, 2025
88653b0
update adv2v2 doc
lantoli Aug 26, 2025
0c349b1
typos
lantoli Aug 26, 2025
1a508f3
fix individual region
lantoli Aug 26, 2025
2eb0958
typo
lantoli Aug 26, 2025
52c69e8
Update docs/command_adv2v2.md
lantoli Aug 26, 2025
646a4e2
installation first
lantoli Aug 26, 2025
23593a5
Update docs/command_clu2adv.md
lantoli Aug 26, 2025
3a64a89
change dynamic block section name
lantoli Aug 26, 2025
3ed0cde
add doc clarification about underlaying resources not being changed
lantoli Aug 26, 2025
e643483
Update docs/command_adv2v2.md
lantoli Aug 28, 2025
ed10890
Update docs/command_adv2v2.md
lantoli Aug 28, 2025
a9eaa90
Update docs/command_adv2v2.md
lantoli Aug 28, 2025
0c68989
Update docs/command_clu2adv.md
lantoli Aug 28, 2025
b58b254
Update docs/command_clu2adv.md
lantoli Aug 28, 2025
57f8832
Update docs/command_clu2adv.md
lantoli Aug 28, 2025
64c0774
Update docs/command_adv2v2.md
lantoli Aug 28, 2025
a6be82a
Update docs/command_clu2adv.md
lantoli Aug 28, 2025
7fd7785
Update docs/command_clu2adv.md
lantoli Aug 28, 2025
a6df286
Update docs/command_adv2v2.md
lantoli Aug 28, 2025
f5f57f1
Update docs/command_adv2v2.md
lantoli Aug 28, 2025
6c0a7cb
Update docs/command_adv2v2.md
lantoli Aug 28, 2025
2c6afef
Update docs/command_clu2adv.md
lantoli Aug 28, 2025
3f5d2b2
apply feedback
lantoli Aug 28, 2025
eddaa86
apply more feedback
lantoli Aug 28, 2025
2459d09
Update docs/command_adv2v2.md
lantoli Aug 29, 2025
45ce5d8
doc replaceOutput
lantoli Aug 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 15 additions & 86 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@

This repository contains the Atlas CLI plugin for [Terraform's MongoDB Atlas Provider](https://registry.terraform.io/providers/mongodb/mongodbatlas/latest/docs).

It has the following commands to help with your Terraform configurations:
- **clusterToAdvancedCluster**: Convert a `mongodbatlas_cluster` Terraform configuration to `mongodbatlas_advanced_cluster` (preview provider 2.0.0).

## Installation

Install the [Atlas CLI](https://github.com/mongodb/mongodb-atlas-cli) if you haven't done it yet.
Expand All @@ -26,101 +23,33 @@ If you want to see the list of installed plugins or check if this plugin is inst
atlas plugin list
```

## Convert mongodbatlas_cluster to mongodbatlas_advanced_cluster (preview provider 2.0.0)

### Usage
## Available Commands
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be after installation perhaps?

Copy link
Collaborator Author

@lantoli lantoli Aug 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's fair, changed here: 646a4e2


You can find more information in the [Migration Guide: Cluster to Advanced Cluster](https://registry.terraform.io/providers/mongodb/mongodbatlas/latest/docs/guides/cluster-to-advanced-cluster-migration-guide).
The plugin provides the following commands to help with your Terraform configurations:

**Note**: In order to use the **Preview for MongoDB Atlas Provider 2.0.0** of `mongodbatlas_advanced_cluster`, you need to set the environment variable `MONGODB_ATLAS_PREVIEW_PROVIDER_V2_ADVANCED_CLUSTER` to `true`.
### 1. clusterToAdvancedCluster (clu2adv)
Convert `mongodbatlas_cluster` resources to `mongodbatlas_advanced_cluster` Provider 2.0.0 schema.

If you want to convert a Terraform configuration from `mongodbatlas_cluster` to `mongodbatlas_advanced_cluster`, use the following command:
**Quick Start:**
```bash
atlas terraform clusterToAdvancedCluster --file in.tf --output out.tf
```

you can also use shorter aliases, e.g.:
```bash
# or using alias
atlas tf clu2adv -f in.tf -o out.tf
```

If you want to include the `moved blocks` in the output file, use the `--includeMoved` or the `-m` flag.

If you want to overwrite the output file if it exists, or even use the same output file as the input file, use the `--replaceOutput` or the `-r` flag.

You can use the `--watch` or the `-w` flag to keep the plugin running and watching for changes in the input file. You can have input and output files open in an editor and see easily how changes to the input file affect the output file.

You can find [here](https://github.com/mongodb-labs/atlas-cli-plugin-terraform/tree/main/internal/convert/testdata/clu2adv) some examples of input files (suffix .in.tf) and the corresponding output files (suffix .out.tf).
[📖 Full Documentation](./docs/command_clu2adv.md) | [🔄 Migration Guide: Cluster to Advanced Cluster](https://registry.terraform.io/providers/mongodb/mongodbatlas/latest/docs/guides/cluster-to-advanced-cluster-migration-guide)

### Dynamic blocks
### 2. advancedClusterToV2 (adv2v2)
Convert previous `mongodbatlas_advanced_cluster` configurations to the new Provider 2.0.0 schema with simplified structure.

`dynamic` blocks are used to generate multiple nested blocks based on a set of values.
Given the different ways of using dynamic blocks, we recommend reviewing the output and making sure it fits your needs.

#### Dynamic blocks in tags and labels

You can use `dynamic` blocks for `tags` and `labels`. The plugin assumes that `for_each` has an expression which is evaluated to a `map` of strings.
You can also combine the use of dynamic blocks in `tags` and `labels` with individual blocks in the same cluster definition, e.g.:
```hcl
tags {
key = "environment"
value = var.environment
}
dynamic "tags" {
for_each = var.tags
content {
key = tags.key
value = replace(tags.value, "/", "_")
}
}
```

#### Dynamic blocks in regions_config

You can use `dynamic` blocks for `regions_config`. The plugin assumes that `for_each` has an expression which is evaluated to a `list` or `set` of objects. See this [guide](./docs/guide_clu2adv_dynamic_block.md) to learn more about some limitations.
This is an example of how to use dynamic blocks in `regions_config`:
```hcl
replication_specs {
num_shards = var.replication_specs.num_shards
zone_name = var.replication_specs.zone_name # only needed if you're using zones
dynamic "regions_config" {
for_each = var.replication_specs.regions_config
content {
priority = regions_config.value.priority
region_name = regions_config.value.region_name
electable_nodes = regions_config.value.electable_nodes
read_only_nodes = regions_config.value.read_only_nodes
}
}
}
```

#### Dynamic blocks in replication_specs

You can use `dynamic` blocks for `replication_specs`. The plugin assumes that `for_each` has an expression which is evaluated to a `list` of objects. See this [guide](./docs/guide_clu2adv_dynamic_block.md) to learn more about some limitations.
This is an example of how to use dynamic blocks in `replication_specs`:
```hcl
dynamic "replication_specs" {
for_each = var.replication_specs
content {
num_shards = replication_specs.value.num_shards
zone_name = replication_specs.value.zone_name # only needed if you're using zones
dynamic "regions_config" {
for_each = replication_specs.value.regions_config
content {
electable_nodes = regions_config.value.electable_nodes
priority = regions_config.value.priority
read_only_nodes = regions_config.value.read_only_nodes
region_name = regions_config.value.region_name
}
}
}
}
**Quick Start:**
```bash
atlas terraform advancedClusterToV2 --file in.tf --output out.tf
# or using alias
atlas tf adv2v2 -f in.tf -o out.tf
```

### Limitations

- `dynamic` blocks are supported with some [limitations](./docs/guide_clu2adv_dynamic_block.md).
[📖 Full Documentation](./docs/command_adv2v2.md)

## Feedback

Expand Down
217 changes: 217 additions & 0 deletions docs/command_adv2v2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
# Convert mongodbatlas_advanced_cluster to Provider 2.0.0 schema

advancedClusterToV2 (adv2v2) command helps you migrate previous `mongodbatlas_advanced_cluster` configurations to the new Provider 2.0.0 schema.

MongoDB Atlas Provider 2.0.0 introduces a new, cleaner structure for `mongodbatlas_advanced_cluster` resources. The main changes include the use of nested attributes instead of blocks and deletion of deprecated attributes like `disk_size_gb` at root level or `num_shards`.

## Usage

To convert a Terraform configuration from the previous `mongodbatlas_advanced_cluster` schema to the Provider 2.0.0 schema, use the following command:

```bash
atlas terraform advancedClusterToV2 --file in.tf --output out.tf
```

You can also use shorter aliases:
```bash
atlas tf adv2v2 -f in.tf -o out.tf
```

### Command Options

- `--file` or `-f`: Input file path containing the `mongodbatlas_advanced_cluster` configuration
- `--output` or `-o`: Output file path for the converted Provider 2.0.0 configuration
- `--replaceOutput` or `-r`: Overwrite the output file if it exists, or even use the same output file as the input file
- `--watch` or `-w`: Keep the plugin running and watching for changes in the input file

## Examples

You can find [here](https://github.com/mongodb-labs/atlas-cli-plugin-terraform/tree/main/internal/convert/testdata/adv2v2) examples of input files (suffix .in.tf) and the corresponding output files (suffix .out.tf).

## Dynamic Blocks

`dynamic` blocks are used to generate multiple nested blocks based on a set of values.
Given the different ways of using dynamic blocks, we recommend reviewing the output and making sure it fits your needs.

### Dynamic blocks in tags and labels

You can use `dynamic` blocks for `tags` and `labels`. The plugin assumes that `for_each` has an expression which is evaluated to a `map` of strings.
You can also combine the use of dynamic blocks in `tags` and `labels` with individual blocks in the same cluster definition, e.g.:
```hcl
tags {
key = "environment"
value = var.environment
}
dynamic "tags" {
for_each = var.tags
content {
key = tags.key
value = replace(tags.value, "/", "_")
}
}
```

### Dynamic blocks in region_configs

You can use `dynamic` blocks for `region_configs`. The plugin assumes that `for_each` has an expression which is evaluated to a `list` of objects.

This is an example of how to use dynamic blocks in `region_configs`:
```hcl
replication_specs {
num_shards = var.replication_specs.num_shards
zone_name = var.replication_specs.zone_name # only needed if you're using zones
dynamic "region_configs" {
for_each = var.replication_specs.region_configs
content {
priority = region_configs.value.priority
provider_name = region_configs.value.provider_name
region_name = region_configs.value.region_name
electable_specs {
instance_size = region_configs.value.instance_size
node_count = region_configs.value.electable_node_count
}
# read_only_specs, analytics_specs, auto_scaling and analytics_auto_scaling can also be defined
}
}
}
```

### Dynamic blocks in replication_specs

You can use `dynamic` blocks for `replication_specs`. The plugin assumes that `for_each` has an expression which is evaluated to a `list` of objects.

This is an example of how to use dynamic blocks in `replication_specs`:
```hcl
dynamic "replication_specs" {
for_each = var.replication_specs
content {
num_shards = replication_specs.value.num_shards
zone_name = replication_specs.value.zone_name # only needed if you're using zones
dynamic "region_configs" {
for_each = replication_specs.value.region_configs
priority = region_configs.value.priority
provider_name = region_configs.value.provider_name
region_name = region_configs.value.region_name
electable_specs {
instance_size = region_configs.value.instance_size
node_count = region_configs.value.electable_node_count
}
# read_only_specs, analytics_specs, auto_scaling and analytics_auto_scaling can also be defined
}
}
}
```

### Limitations

If you need to use the plugin for `dynamic` block use cases not yet supported, please send us [feedback](https://github.com/mongodb-labs/atlas-cli-plugin-terraform/issues).

#### Dynamic block and individual blocks in the same resource

Dynamic block and individual blocks for `region_configs` or `replication_specs` are not supported at the same time. The recommended way to handle this is to remove the individual `region_configs` or `replication_specs` blocks and use a local `list` variable with [concat](https://developer.hashicorp.com/terraform/language/functions/concat) to add the individual block information to the variable you're using in the `for_each` expression.

Let's see an example with `region_configs`, it is the same idea for `replication_specs`. In the original configuration file, the `mongodb_cluster` resource is used inside a module that receives the `region_configs` elements in a `list` variable and we want to add an additional `region_configs` with a read-only node.
```hcl
variable "replication_specs" {
type = object({
num_shards = number
region_configs = list(object({
priority = number
provider_name = string
region_name = string
instance_size = string
electable_node_count = number
read_only_node_count = number
}))
})
}

resource "mongodbatlas_advanced_cluster" "this" {
project_id = var.project_id
name = var.cluster_name
cluster_type = var.cluster_type
replication_specs {
num_shards = var.replication_specs.num_shards
dynamic "region_configs" {
for_each = var.replication_specs.region_configs
priority = region_configs.value.priority
provider_name = region_configs.value.provider_name
region_name = region_configs.value.region_name
electable_specs {
instance_size = region_configs.value.instance_size
node_count = region_configs.value.electable_node_count
}
read_only_specs {
instance_size = region_configs.value.instance_size
node_count = region_configs.value.read_only_node_count
}
}
region_configs { # individual region
priority = 0
provider_name = "AWS"
region_name = "US_EAST_1"
read_only_specs {
instance_size = var.instance_size
node_count = 1
}
}
}
}
```

We modify the configuration file to create an intermediate `local` variable to merge the `region_configs` variable elements and the additional `region_configs`:
```hcl
variable "replication_specs" {
type = object({
num_shards = number
region_configs = list(object({
priority = number
provider_name = string
region_name = string
instance_size = string
electable_node_count = number
read_only_node_count = number
}))
})
}

locals {
region_configs_all = concat(
var.replication_specs.region_configs,
[
{
priority = 0
provider_name = "AWS"
region_name = "US_EAST_1"
instance_size = var.instance_size
electable_node_count = 0
read_only_node_count = 1
},
]
)
}

resource "mongodbatlas_advanced_cluster" "this" {
project_id = var.project_id
name = var.cluster_name
cluster_type = var.cluster_type
replication_specs {
num_shards = var.replication_specs.num_shards
dynamic "region_configs" {
for_each = local.region_configs_all # changed to use the local variable
priority = region_configs.value.priority
provider_name = region_configs.value.provider_name
region_name = region_configs.value.region_name
electable_specs {
instance_size = region_configs.value.instance_size
node_count = region_configs.value.electable_node_count
}
read_only_specs {
instance_size = region_configs.value.instance_size
node_count = region_configs.value.read_only_node_count
}
}
}
}
```
This modified configuration file has the same behavior as the original one, but it doesn't have individual blocks anymore, only the `dynamic` block, so it is supported by the plugin.
Loading