Nested for loop

Team,

We need help with fixing the nested for_loop. We tried to use the loop based on the object_type is working fine. When we try to loop based on the schema we encounter errors (have tried multiple methods, but nothing worked. ).

Code:


resource "postgresql_grant" "schema_privileges" {
  for_each      = var.postgres_grants
  database     = postgresql_database.pg_db.name
  role              = postgresql_role.pg_role.name
  schema        = "public"
  object_type = each.key
  privileges     = each.value
 }

variable "schema_privileges" {
  type = map(list(string))
  default = {
    "schema" = ["USAGE"]
    "table"  = ["SELECT"]
  }

Terraform plan:

+ resource "postgresql_grant" "schema_privileges" {
      + database          = "production_db1"
      + id                = (known after apply)
      + object_type       = "schema"
      + privileges        = [
          + "USAGE",
        ]
      + role              = "production_role"
      + schema            = "public"
      + with_grant_option = false
    }

  # module.db_replica["db1"].postgresql_grant.schema_privileges["table"] will be created
  + resource "postgresql_grant" "schema_privileges" {
      + database          = "production_db1"
      + id                = (known after apply)
      + object_type       = "table"
      + privileges        = [
          + "SELECT",
        ]
      + role              = "production_role"
      + schema            = "public"
      + with_grant_option = false
    }

The above code is working as expected, however when we try to loop based on the schema, which throws errors.


locals {
  privileges = flatten([

    for schema_type_key, schema_type in var.postgres_grants : [
      for object_type in schema_type.object_type : {
        schema_type_key = schema_type_key
        object_type_key = object_type
        object_type_value = object_type.value
      }
    ]
  ])
}

resource "postgresql_grant" "schema_privileges" {
  for_each    = { for idx, pg in local.privileges : idx => pg }
  database    = postgresql_database.pg_db.name
  role        = postgresql_role.pg_role.name
  schema      = each.value.schema_type_key
  object_type = each.value.object_type_key
  privileges  = each.value.object_type_value
}


variable "postgres_grants" {
type = map(map(list(string)))
  default = {
    public = {
      "schema" = ["USAGE"]
      "table"  = ["SELECT"]
    }
  non-public = {
    "schema" = ["ALTER", "EXECUTE"]
     "table"  = ["SELECT"]
    "sequence" = ["EXECUTE"]
    }
  test = {
    "sequence" = ["TEMPORARY"]
  }

  }
}

Error:

Error: Unsupported attribute

  on .terraform/modules/db_replica/main.tf line 64, in locals:
  64:       for object_type in schema_type.object_type : {

This object does not have an attribute named "object_type".


Error: Unsupported attribute

  on .terraform/modules/db_replica/main.tf line 64, in locals:
  64:       for object_type in schema_type.object_type : {

This object does not have an attribute named "object_type".

How to handle this nested loop? Any suggestions?

It’s fixed.

locals {
  privileges = flatten([
    for schema_key, schemas in var.postgres_grants : [
      for object_type_key, object_type_value in schemas : {
        schema_key        = schema_key
        object_type_key   = object_type_key
        object_type_value = object_type_value
      }
    ]
  ])
}

resource "postgresql_grant" "schema_privileges" {
  for_each    = { for index, sp in local.privileges : index => sp }
  database    = postgresql_database.pg_db.name
  role        = postgresql_role.pg_role.name
  schema      = each.value.schema_key
  object_type = each.value.object_type_key
  privileges  = each.value.object_type_value
}

variable "postgres_grants" {
type = map(map(list(string)))
  default = {
    public = {
      "schema" = ["USAGE"]
      "table"  = ["SELECT"]
    }
  non-public = {
    "schema" = ["ALTER", "EXECUTE"]
     "table"  = ["SELECT"]
    "sequence" = ["EXECUTE"]
    }
  test = {
    "sequence" = ["TEMPORARY"]
  }