Search code examples
terraformterraform-template-fileterraform-modules

for_each through a object in Terraform 0.12


I want to call terraform module in the next way:

module "database_role" {
 source = "modules/roles"

 project_id = "testid"
 role_name = "testrole"

 actions = {
   action: ["ENABLE_PROFILER", "DROP_DATABASE"]
   database_name: "test_db"
 }

roles module definition i created is:

resource "mongodbatlas_custom_db_role" "custom_role" {
  project_id = var.project_id
  role_name  = var.role_name

  dynamic "actions" {
    for_each = [for item in [var.actions] : item]
      content {
        actions {
          action = lookup(actions.value, "action")

          resources {
            cluster = "false"
            database_name = lookup(actions.value, "database_name")
          }
        }
      }
    }
  }

as result i want to see actions properly generated:

 actions {
   action = "ENABLE_PROFILER"
   resources {
     cluster         = "false"
     database_name   = "test_db"
   }
 }


 actions {
   action = "DROP_DATABASE"
   resources {
     cluster         = "false"
     database_name   = "test_db"
   }
 }

I'm getting error: The given value is not suitable for child module variable "actions". What i'm doing wrong in module dynamic resource? Thanks


Solution

  • The flatten function could be used here.

    I've below actions local var::

    locals {
      actions = {
        action = ["ENABLE_PROFILER", "DROP_DATABASE"]
        database_name = "test_db"
      }
    }
    

    Now, I'll flatten based on the size of local.actions["action"] to achieve the desired result. Once, I get the flattened list, I would loop through the list to create dynamic blocks.

    resource "mongodbatlas_custom_db_role" "custom_role" {
      project_id = "xxx-xxx"
      role_name  = "yyy-yyy"
    
      dynamic "actions" {
        for_each = flatten([
          for item in range(length(local.actions["action"])): {
            act = local.actions["action"][item]
            db_name = local.actions.database_name
          }
         ])
         content {
           action = actions.value.act
           resources {
             cluster = "false"
             database_name = actions.value.db_name
           }
         }
       }
     }
    

    This would produce the required number of blocks I like::

    Harshas-MBP:mongo harshavmb$ terraform plan
    Refreshing Terraform state in-memory prior to plan...
    The refreshed state will be used to calculate this plan, but will not be
    persisted to local or remote state storage.
    
    
    ------------------------------------------------------------------------
    
    An execution plan has been generated and is shown below.
    Resource actions are indicated with the following symbols:
      + create
    
    Terraform will perform the following actions:
    
      # mongodbatlas_custom_db_role.custom_role will be created
      + resource "mongodbatlas_custom_db_role" "custom_role" {
          + id         = (known after apply)
          + project_id = "xxx-xxx"
          + role_name  = "yyy-yyy"
    
          + actions {
              + action = "ENABLE_PROFILER"
    
              + resources {
                  + cluster       = false
                  + database_name = "test_db"
                }
            }
          + actions {
              + action = "DROP_DATABASE"
    
              + resources {
                  + cluster       = false
                  + database_name = "test_db"
                }
            }
        }
    
    Plan: 1 to add, 0 to change, 0 to destroy.
    
    ------------------------------------------------------------------------
    
    Note: You didn't specify an "-out" parameter to save this plan, so Terraform
    can't guarantee that exactly these actions will be performed if
    "terraform apply" is subsequently run.
    

    This could be applied to create resources too. The key idea of working with nested or complicated loops is to flatten them into a list of resources or blocks, we create and then iterate through the flattened list with unique indexes as shown in above example.