Mukesh Santhanam
Mukesh Santhanam

Reputation: 303

Terraform Merge two list with identical structure

Need help on this : How to merge two identical app - id & Values [App Role & Oauth scope] for same app.

Any help is appreciated !!!

 oauth_merge_permissions  = [
       {
           App1 = {
               role1 = "729e1819-d582-d503-deff-2be33394cee5"
               role2     = "fb9b9a2d-2653-ad21-556b-67b40742f4e1"
               role3    = "f9dbd854-e42e-298e-c7d6-ba068d67261d"
               role4   = "5324f064-ac54-db19-16c0-0510a3b979dc"
               role5  = "d1577294-3870-e465-c433-e036bd2d624c"
               role6     = "c13d1bc7-ffc2-dd8c-001e-c42c7c1b32cc"
            }
        },
       {
           App1 = {
               test               = "da2a01d8-9865-412b-b7ef-f48f1e56e481"
               user_impersonation = "7b31ca60-1333-4620-9582-012f25f4da05"
            }
        },
        {
           App2 = {
               role5  = "d1577294-3870-e465-c433-e036bd2d624c"
               role6     = "c13d1bc7-ffc2-dd8c-001e-c42c7c1b32cc"
            }
        }
    ]

Desired Output: I would get below output so that i can able to utilize this output in azuread_application API permission.

Result = [
       {
           App1 = {
               role1 = "729e1819-d582-d503-deff-2be33394cee5"
               role2     = "fb9b9a2d-2653-ad21-556b-67b40742f4e1"
               role3    = "f9dbd854-e42e-298e-c7d6-ba068d67261d"
               role4   = "5324f064-ac54-db19-16c0-0510a3b979dc"
               role5  = "d1577294-3870-e465-c433-e036bd2d624c"
               role6     = "c13d1bc7-ffc2-dd8c-001e-c42c7c1b32cc"
               test               = "70efda02-14a2-48f2-9297-8d86e7737438"
               user_impersonation = "e100b04b-fb46-b764-8ae9-513e1f1cd469"
            }
        },       
        {
           App2 = {
               role5  = "d1577294-3870-e465-c433-e036bd2d624c"
               role6     = "7b31ca60-1333-4620-9582-012f25f4da05"
            }
        }
    ]

Upvotes: 0

Views: 1167

Answers (1)

Martin Atkins
Martin Atkins

Reputation: 74694

I think to get this done will take two steps: first to gather objects together by app name, and then second to merge the objects together within those groups.

Let's start with step one:

locals {
  oauth_merge_permissions = [
    {
      App1 = {
        role1 = "729e1819-d582-d503-deff-2be33394cee5"
        role2 = "fb9b9a2d-2653-ad21-556b-67b40742f4e1"
        role3 = "f9dbd854-e42e-298e-c7d6-ba068d67261d"
        role4 = "5324f064-ac54-db19-16c0-0510a3b979dc"
        role5 = "d1577294-3870-e465-c433-e036bd2d624c"
        role6 = "c13d1bc7-ffc2-dd8c-001e-c42c7c1b32cc"
      }
    },
    {
      App1 = {
        test               = "da2a01d8-9865-412b-b7ef-f48f1e56e481"
        user_impersonation = "7b31ca60-1333-4620-9582-012f25f4da05"
      }
    },
    {
      App2 = {
        role5 = "d1577294-3870-e465-c433-e036bd2d624c"
        role6 = "c13d1bc7-ffc2-dd8c-001e-c42c7c1b32cc"
      }
    }
  ]

  role_maps_by_app = {
    for m in local.oauth_merge_permissions : one(keys(m)) => one(values(m))...
  }
}

The value of objects_by_app would be the following, with the input shown here:

role_maps_by_app = {
  "App1" = [
    {
      "role1" = "729e1819-d582-d503-deff-2be33394cee5"
      "role2" = "fb9b9a2d-2653-ad21-556b-67b40742f4e1"
      "role3" = "f9dbd854-e42e-298e-c7d6-ba068d67261d"
      "role4" = "5324f064-ac54-db19-16c0-0510a3b979dc"
      "role5" = "d1577294-3870-e465-c433-e036bd2d624c"
      "role6" = "c13d1bc7-ffc2-dd8c-001e-c42c7c1b32cc"
    },
    {
      "test"               = "da2a01d8-9865-412b-b7ef-f48f1e56e481"
      "user_impersonation" = "7b31ca60-1333-4620-9582-012f25f4da05"
    },
  ]
  "App2" = [
    {
      "role5" = "d1577294-3870-e465-c433-e036bd2d624c"
      "role6" = "c13d1bc7-ffc2-dd8c-001e-c42c7c1b32cc"
    },
  ]
}

I've made two assumptions here:

  • Each of the top-level maps will only have one element in it.
  • You're using Terraform v0.15.0 or later, so you can use the one function. If not, you can use an expression like keys(m)[0], with the only difference being that it'll ignore multiple elements in the maps, rather than raising an error.

Now we have a map of lists of maps, we can write the second step of merging all of the maps in each list into a single map each:

locals {
  # (keep the other local values from above too)

  roles_by_app = {
    for app, role_maps in local.role_maps_by_app : app => merge(role_maps...)
  }  
}

local.roles_by_app will then have the following value, which seems to match your requirement:

roles_by_app = {
  "App1" = {
    "role1"              = "729e1819-d582-d503-deff-2be33394cee5"
    "role2"              = "fb9b9a2d-2653-ad21-556b-67b40742f4e1"
    "role3"              = "f9dbd854-e42e-298e-c7d6-ba068d67261d"
    "role4"              = "5324f064-ac54-db19-16c0-0510a3b979dc"
    "role5"              = "d1577294-3870-e465-c433-e036bd2d624c"
    "role6"              = "c13d1bc7-ffc2-dd8c-001e-c42c7c1b32cc"
    "test"               = "da2a01d8-9865-412b-b7ef-f48f1e56e481"
    "user_impersonation" = "7b31ca60-1333-4620-9582-012f25f4da05"
  }
  "App2" = {
    "role5" = "d1577294-3870-e465-c433-e036bd2d624c"
    "role6" = "c13d1bc7-ffc2-dd8c-001e-c42c7c1b32cc"
  }
}

For this second step I used the merge function, which takes a number of maps as arguments and returns a single map with the elements all merged together by key. Because merge expects a variable number of arguments rather than a single argument that's a list, I used the ... modifier on the role_maps argument to tell Terraform to use each element of that list as a separate argument to the function.

Upvotes: 1

Related Questions