Working with list of maps

Hi,

In order to create a mongodb cluster I’ll need to create a resource which contains some static and dynamic configuration.

I would like to take the dynamic configuration and insert 2 different values to this section.

Let me clarify, please check the following resource:

resource "mongodbatlas_cluster" "mongo_cluster_two_regions" {

  project_id                  = var.mongo_project_id
  name                        = var.mongo_cluster_name
  num_shards                  = var.mongo_num_shards
  replication_factor          = var.mongo_replication_factor
  backup_enabled              = var.mongo_backup_boolean
  mongo_db_major_version      = var.mongo_version
  provider_name               = var.mongo_provider_name
  disk_size_gb                = var.mongo_disk_size
  provider_disk_iops          = var.mongo_disk_iops
  provider_volume_type        = var.mongo_volume_type
  provider_encrypt_ebs_volume = var.mongo_encryption_boolean
  provider_instance_size_name = var.mongo_instance_size
  cluster_type                = var.mongo_cluster_type
  replication_specs {
    num_shards                = var.mongo_replication_num_shards
    regions_config {
      region_name = regions_config.region
      electable_nodes = regions_config.electable_nodes
      priority = regions_config.priority
      read_only_nodes = regions_config.read_only_nodes
      }
    }
  }
}

For my purposes I would like to create a list of maps which will look like this:

regions_config = [
{
  region_name = "eu-west-1"
  electable_nodes = "2"
  priority = "7"
  read_only_nodes = "0"
},
{
  region_name = "eu-central-1"
  electable_nodes = "1"
  priority = "6"
  read_only_nodes = "0"
}
]

Node that I don’t want to create several clusters so I guess the “count” function won’t help me, I just want to add another “regions_config” section to the specified cluster.

The resource should look like this:

resource "mongodbatlas_cluster" "cluster-test" {
  project_id     = "<YOUR-PROJECT-ID>"
  name           = "cluster-test-multi-region"
  disk_size_gb   = 100
  num_shards     = 1
  backup_enabled = true
  cluster_type   = "REPLICASET"

  //Provider Settings "block"
  provider_name               = "AWS"
  provider_disk_iops          = 300
  provider_volume_type        = "STANDARD"
  provider_instance_size_name = "M10"

  replication_specs {
    num_shards = 1
    regions_config {
      region_name     = "US_EAST_1"
      electable_nodes = 3
      priority        = 7
      read_only_nodes = 0
    }
    regions_config {
      region_name     = "US_EAST_2"
      electable_nodes = 2
      priority        = 6
      read_only_nodes = 0
    }
    regions_config {
      region_name     = "US_WEST_1"
      electable_nodes = 2
      priority        = 5
      read_only_nodes = 2
    }
  }
}

Please assist.

Thanks !

Is there any update regarding this thread?

Hi @eladazary,

You can create one regions_config block per element of var.regions_config like this:

  dynamic "regions_config" {
    for_each = var.regions_config
    content {
      region_name     = regions_config.value.region_name
      electable_nodes = regions_config.value.electable_nodes
      priority        = regions_config.value.priority
      read_only_nodes = regions_config.value.read_only_nodes
    }
  }

Since this regions_config variable works with objects of a particular structure, I recommend declaring it as a set of objects rather than a set of maps, because then Terraform can check that all of the attributes are present and have suitably-typed values:

variable "regions_config" {
  type = set(object({
    region_name     = string
    electable_nodes = number
    priority        = number
    read_only_nodes = number
  }))
}

I used a set rather than a list here to indicate that the order of these blocks isn’t important, since it looks like they are identified by the region_name attributes rather than their positions in the list. You can still populate this variable using the [ ... ] syntax, because the result of that can convert to either a list or a set as long as the element types are all correct.

Thanks man, it’s working !

Full variable would look like this right ?

variable "regions_config" {
  type = set(object({
    region_name     = string
    electable_nodes = number
    priority        = number
    read_only_nodes = number
  }))
  default = (
    {
      region_name     = "US_EAST_1"
      electable_nodes = 3
      priority        = 7
      read_only_nodes = 0
    },
    {
      region_name     = "US_EAST_2"
      electable_nodes = 2
      priority        = 6
      read_only_nodes = 0
    },
    {
      region_name     = "US_WEST_1"
      electable_nodes = 2
      priority        = 5
      read_only_nodes = 2
    }
  )
}