listazureloopsdictionaryterraform

Terraform, create map where list elements are values


I am trying to parse this variable in terraform. The main goal is to create map of "group" = "member" type. Did i set type in variable correct? Required output provided below.

variable "iam" "this"{
  type = map(map(list(string)))
  default = {
    "admins" = {
      "user" = [
        "user1@gmail.com",
        "user2@gmail.com"
      ]
      "service_principal" = [
        "dpaf2-dev-sa"
      ]
    }
    "dev"   = {
      "user" = [
        "user1@gmail.com",
        "user2@gmail.com"
      ]
      "service_principal" = []
    }
    "ops"   = {
      "user" = [
        "user3@gmail.com",
      ]
      "service_principal" = [
        "dpaf2-dev-sa",
        "dpaf2-iacda-app-id",
      ]
    }
  }
}

Required output:

{
"admins" = "user1@gmail.com"
"admins" = "user2@gmail.com"
"admins" = "dpaf2-dev-sa"
"dev"    = "user1n@gmail.com"
"dev"    = "user2@gmail.com"
"ops"    = "user3@gmail.com"
"ops"    = "dpaf2-dev-sa"
"ops"    = "dpaf2-iacda-app-id"
}

Solution

  • Start with this and manipulate it to suit your exact needs. There are many ways to structure resources using maps, arrays and nesting.

    locals {
      service_principal = {
        admin = ["dpaf2-dev-sa"]
        dev   = []
        ops = [
          "dpaf2-dev-sa",
          "dpaf2-iacda-app-id",
        ]
      }
      users = {
        admin = [
          "oleh_mykolaishyn@gmail.com",
          "yevhen_plaksa@gmail.com"
        ]
        dev = [
          "yevhen_plaksa@gmail.com"
        ]
        ops = [
          "oleksandr_gorkun@gmail.com"
        ]
      }
      result = flatten([for role in keys(local.users) : [for user in local.users[role] :
      { role = role, user = user, principals = local.service_principal[role] }]])
    }
    
    resource "null_resource" "users" {
      count = length(local.result)
      provisioner "local-exec" {
        command = "echo user: $USER has role: $ROLE and principals: $SERVICE_PRINCIPAL >> ouput.txt"
    
        environment = {
          USER              = local.result[count.index].user
          ROLE              = local.result[count.index].role
          SERVICE_PRINCIPAL = join(", ", local.result[count.index].principals)
        }
      }
    }
    

    If you run:

    1. terraform init
    2. terraform plan
    3. terraform apply --auto-approve

    Then check your directory for a file named output.txt which will contain

    user:oleh_mykolaishyn@gmail.com has role:admin and principals: dpaf2-dev-sa
    user:yevhen_plaksa@gmail.com has role:dev and principals:
    user:oleksandr_gorkun@gmail.com has role:ops and principals: dpaf2-dev-sa, dpaf2-iacda-app-id
    user:yevhen_plaksa@gmail.com has role:admin and principals: dpaf2-dev-sa
    

    I know the text file isn't your desired output but the loop is just a demonstration of how you can iterate over the local variable.

    Again, many ways to sort and slice it. I avoided your desired output because maps cannot have duplicate keys so it'll never work.

    If you want to see the result in isolation you can do:

    1. terraform console
    2. local.result

    And it will appear in the terminal. To exit the console type exit.