|
1 | 1 | # Module Maintainer - `mongodbatlas_cluster` to `mongodbatlas_advanced_cluster`
|
2 | 2 |
|
3 | 3 | The purpose of this example is to demonstrate how a Terraform module can help in the migration from `mongodbatlas_cluster` to `mongodbatlas_advanced_cluster`.
|
4 |
| -The example contains three module versions: |
| 4 | +The example contains three module versions which represent the three steps of the migration: |
5 | 5 |
|
6 |
| -<!-- Update Variable count --> |
7 |
| -Version | Purpose | Variables | Resources |
| 6 | +Step | Purpose | Resources |
8 | 7 | --- | --- | --- | ---
|
9 |
| -[v1](./v1) | Baseline | 5 | `mongodbatlas_cluster` |
10 |
| -[v2](./v2) | Migrate to advanced_cluster with no change in variables or plan | 5 | `mongodbatlas_advanced_cluster` |
11 |
| -[v3](./v3) | Use the latest features of advanced_cluster | 10 | `mongodbatlas_advanced_cluster` |
| 8 | +[Step 1](./v1) | Baseline | `mongodbatlas_cluster` |
| 9 | +[Step 2](./v2) | Migrate to advanced_cluster with no change in variables or plan | `mongodbatlas_advanced_cluster` |
| 10 | +[Step 3](./v3) | Use the latest features of advanced_cluster | `mongodbatlas_advanced_cluster` |
12 | 11 |
|
13 |
| -<!-- TODO: Add highlights of module implementations --> |
| 12 | +The rest of this document summarizes the different implementations: |
| 13 | + |
| 14 | +- [Step 1: Module `v1` Implementation Summary](#step-1-module-v1-implementation-summary) |
| 15 | + - [`variables.tf`](#variablestf) |
| 16 | + - [`main.tf`](#maintf) |
| 17 | + - [`outputs.tf`](#outputstf) |
| 18 | +- [Step 2: Module `v2` Implementation Changes and Highlights](#step-2-module-v2-implementation-changes-and-highlights) |
| 19 | + - [`variables.tf` unchanged from `v1`](#variablestf-unchanged-from-v1) |
| 20 | + - [`versions.tf`](#versionstf) |
| 21 | + - [`main.tf`](#maintf-1) |
| 22 | + - [`outputs.tf`](#outputstf-1) |
| 23 | +- [Step 3: Module `v3` Implementation Changes and Highlights](#step-3-module-v3-implementation-changes-and-highlights) |
| 24 | + - [`variables.tf`](#variablestf-1) |
| 25 | + - [`main.tf`](#maintf-2) |
| 26 | + - [`outputs.tf`](#outputstf-2) |
| 27 | + |
| 28 | + |
| 29 | +## Step 1: Module `v1` Implementation Summary |
| 30 | +This module creates a `mongodbatlas_cluster` |
| 31 | + |
| 32 | +### [`variables.tf`](v1/variables.tf) |
| 33 | +An abstraction for the `mongodbatlas_cluster` resource: |
| 34 | +- Not all arguments are exposed, but the arguments follow the schema closely |
| 35 | +- `disk_size` and `auto_scaling_disk_gb_enabled` are mutually exclusive and validated in the `precondition` in `main.tf` |
| 36 | + |
| 37 | +### [`main.tf`](v1/main.tf) |
| 38 | +It uses `dynamic` blocks to represent: |
| 39 | +- `tags` |
| 40 | +- `replication_specs` |
| 41 | +- `regions_config` (nested inside replication_specs) |
| 42 | + |
| 43 | +### [`outputs.tf`](v1/outputs.tf) |
| 44 | +- Expose some attributes of `mongodbatlas_cluster` but also the full resource with `mongodbatlas_cluster` output variable: |
| 45 | +```terraform |
| 46 | +output "mongodbatlas_cluster" { |
| 47 | + value = mongodbatlas_cluster.this |
| 48 | + description = "Full cluster configuration for mongodbatlas_cluster resource" |
| 49 | +} |
| 50 | +``` |
| 51 | + |
| 52 | +## Step 2: Module `v2` Implementation Changes and Highlights |
| 53 | +This module uses HCL code to create a `mongodbatlas_advanced_cluster` resource that is compatible with the input variables of `v1`. |
| 54 | +The module supports standalone usage when there is no existing `mongodbatlas_cluster` and also upgrading from `v1` using a `moved` block. |
| 55 | + |
| 56 | +### [`variables.tf`](v2/variables.tf) unchanged from `v1` |
| 57 | +### [`versions.tf`](v2/versions.tf) |
| 58 | +- `required_version` of Terraform CLI bumped to `# todo: minimum moved block supported version` for `moved` block support |
| 59 | +- `mongodbatlas.version` bumped to `# todo: PLACEHOLDER_TPF_RELEASE` for new `mongodbatlas_advanced_cluster` v2 schema support |
| 60 | + |
| 61 | +### [`main.tf`](v2/main.tf) |
| 62 | +<!-- TODO: Update link to (schema v2) docs page --> |
| 63 | +- `locals.replication_specs` an intermediate variable transforming the `variables` to a compatible [replication_specs](https://registry.terraform.io/providers/mongodb/mongodbatlas/latest/docs/resources/advanced_cluster#replication_specs-1) for `mongodbatlas_advanced_cluster` |
| 64 | + - We use the Terraform builtin [range](https://developer.hashicorp.com/terraform/language/functions/range) function (`range(old_spec.num_shards)`) to flatten `num_shards` |
| 65 | + - We expand `read_only_specs` and `electable_specs` into nested attributes |
| 66 | + - We use the `var.provider_name` in the `region_configs.*.instance_size` |
| 67 | +- `moved` block: |
| 68 | +```terraform |
| 69 | +moved { |
| 70 | + from = mongodbatlas_cluster.this |
| 71 | + to = mongodbatlas_advanced_cluster.this |
| 72 | +} |
| 73 | +``` |
| 74 | +- `resource "mongodbatlas_advanced_cluster" "this"` |
| 75 | + - We reference the `local.replication_specs` as input to `replication_specs` (`replication_specs = local.replication_specs`) |
| 76 | + - Tags can be passed directly instead of the dynamic block (`tags = var.tags`) |
| 77 | +- Adds `data "mongodbatlas_cluster" "this"` to avoid breaking changes in `outputs.tf` (see below) |
| 78 | + |
| 79 | +### [`outputs.tf`](v2/outputs.tf) |
| 80 | +- All outputs can use `mongodbatlas_advanced_cluster` except for |
| 81 | + - `replication_specs`, we use the `data.mongodbatlas_cluster.this.replication_specs` to keep the same format |
| 82 | + - `mongodbatlas_cluster`, we use the `data.mongodbatlas_cluster.this` to keep the same format |
| 83 | + |
| 84 | + |
| 85 | +## Step 3: Module `v3` Implementation Changes and Highlights |
| 86 | +This module adds variables to support the latest `mongodbatlas_advanced_cluster` features while staying compatible with the old input variables. |
| 87 | +The module supports standalone usage when there is no existing `mongodbatlas_cluster` and also upgrading from `v1` using a `moved` block. |
| 88 | +The module also supports changing an existing `mongodbatlas_advanced_cluster` created in `v2`. |
| 89 | + |
| 90 | +### [`variables.tf`](v3/variables.tf) |
| 91 | +- Add `replication_specs_new`, this is almost a full mirror of the `replication_specs` of the latest `mongodbatlas_advanced_cluster` schema |
| 92 | + - Use a `[]` for default to allow continued usage of the old `replication_specs` |
| 93 | + - Usage of `optional` to simplify the caller |
| 94 | +- Add `default` to `instance_size` and `provider_name` as these are not required when `replication_specs_new` is used |
| 95 | +- Change `[]` default to `replication_specs` to allow usage of `replication_specs_new` |
| 96 | + |
| 97 | +### [`main.tf`](v3/main.tf) |
| 98 | +- Add *defaults* to old variables in `locals`: |
| 99 | + - `old_disk_size` |
| 100 | + - `old_instance_size` |
| 101 | + - `old_provider_name` |
| 102 | +- Add `_old` suffix to `locals.replication_specs` to make conditional code (see below) more readable |
| 103 | +- Add `precondition` for `replication_specs` to validate only `var.replication_specs_new` or `replication_specs` is used |
| 104 | +```terraform |
| 105 | + precondition { |
| 106 | + condition = !((local.use_new_replication_specs && length(var.replication_specs) > 0) || (!local.use_new_replication_specs && length(var.replication_specs) == 0)) |
| 107 | + error_message = "Must use either replication_specs_new or replication_specs, not both." |
| 108 | + } |
| 109 | +``` |
| 110 | +- Use a conditional for`replication_specs` in `resource "mongodbatlas_advanced_cluster" "this"`: |
| 111 | +```terraform |
| 112 | + # other attributes... |
| 113 | + replication_specs = local.use_new_replication_specs ? var.replication_specs_new : local.replication_specs_old |
| 114 | + tags = var.tags |
| 115 | +} |
| 116 | +``` |
| 117 | +- Use `count` for data source to avoid error when Asymmetric Shards are used: |
| 118 | +```terraform |
| 119 | +data "mongodbatlas_cluster" "this" { |
| 120 | + count = local.use_new_replication_specs ? 0 : 1 # Not safe when Asymmetric Shards are used |
| 121 | + name = mongodbatlas_advanced_cluster.this.name |
| 122 | + project_id = mongodbatlas_advanced_cluster.this.project_id |
| 123 | +
|
| 124 | + depends_on = [mongodbatlas_advanced_cluster.this] |
| 125 | +} |
| 126 | +``` |
| 127 | + |
| 128 | +### [`outputs.tf`](v3/outputs.tf) |
| 129 | +- Update `replication_specs` and `mongodbatlas_cluster` to handle the case when the new schema is used: |
| 130 | +```terraform |
| 131 | +output "replication_specs" { |
| 132 | + value = local.use_new_replication_specs ? [] : data.mongodbatlas_cluster.this[0].replication_specs # updated |
| 133 | + description = "Replication Specs for cluster, will be empty if var.replication_specs_new is set" |
| 134 | +} |
| 135 | +
|
| 136 | +output "mongodbatlas_cluster" { |
| 137 | + value = local.use_new_replication_specs ? null : data.mongodbatlas_cluster.this[0] # updated |
| 138 | + description = "Full cluster configuration for mongodbatlas_cluster resource, will be null if var.replication_specs_new is set" |
| 139 | +} |
| 140 | +``` |
0 commit comments