Reduce map(map(map(list(string)))) terraform

Viewed 395

Hi there is there any neat way to convert a map(map(map(list(string)))) into a map(map(list(string))) with terraform .

Here's what my input structure looks like :

   exception_expr_rule = {
   "project" = {
     "user" = {
       sqli-stable = [
         "value",
       ],
       xss-stable = [
         "value",
         "value",
         "value"
       ],
       rce-stable = [
         "value"
       ],
       ...... = []
     },
     "user2" = {
       xss-stable = [
         "value",
       ],
       other-subsubkey = [
         "value"
       ],
       other-subsubkey = [
         "value"
       ],
       other-subsubkey = [
         "value"
       ],
      }
      "userN" = {....}
   }}

and here's what i want it to look like :

exception_expr_rule = {
 "project.user" = {
    sqli-stable = [
      "value",
    ],
    xss-stable = [
      "value",
      "value",
      "value"
    ],
    rce-stable = [
      "value"
    ]
  },
"project.user2" = {
    xss-stable = [
      "value",
    ],
    other-subsubkey = [
       "value"
     ],
     .....
   }
"project.userN" = {.....}
}

Can you guys help me achieve this please ?

I tried via

    exception_expr_rule_list = flatten([
    for projects,value in var.expr_rule_list : [
      for user_name,exceptions in value: {
          key = "${projects}.${user_name}"
          value = exceptions
        }
    ]
  ])

But is not wat i want.

2 Answers

Tricky but a combination of flatten and for loops gets you there.

I've tested this with Terraform v0.14.5 in the console.

First I defined a variable copying your input structure:

variable "exception_expr_rule" {
  type = map

  default = {
    "project" = {
      "user" = {
        sqli-stable = [
          "value"
        ],
        xss-stable = [
          "value",
          "value",
          "value"
        ],
        rce-stable = [
          "value"
        ]
      }
    }
  }
}

Then I created a new new local variable which combines and flattens it:

locals {
  new = flatten([
    for key in keys(var.exception_expr_rule): [
      for subkey, subvalue in var.exception_expr_rule[key]: {
        "${key}.${subkey}" = subvalue
      }
    ]
  ])
}

If I access it via local.new[0] I get the desired output:

> local.new[0]
{
  "project.user" = {
    "rce-stable" = [
      "value",
    ]
    "sqli-stable" = [
      "value",
    ]
    "xss-stable" = [
      "value",
      "value",
      "value",
    ]
  }
}

Solved doing

    new = {for pair in flatten([ 
       for key in keys(var.exception_expr_rule_list): [ 
          for subkey, subvalue in var.exception_expr_rule_list[key]: { 
              key = "${key}.${subkey}" 
              value = subvalue 
          } 
        ] 
       ]): "${pair.key}" => pair.value 
} 
Related