How to convert map of list to map of map?

I am new to Terraform.

variable "list" {
    default = {
        a = ["10"]
        b = ["20"]
    }
}
variable "list1" {
    default = {
        a = {
            c = "hello"
        }
        b  = {
            d = "world"
        }
    }
}

I’d like to have this as output.

out = {
   a = {
     e = ["10"],
     c = "hello"
    }
   b = {
      f = ["20"],
      d = "world"
   }
}

When i do this, it only prints out the hello world

output "out" {
    value = {for k,v in merge(var.list, var.list1): k => v}
} 
out = {
      a = {
          c = "hello"
        }
      b = {
          d = "world"
        }
    }

How to achieve this?
I think I don’t know how to convert var.list from map of list to map of map?

Thanks.

###########Update: thanks @apparentlymart
Currently, I already have an output can produce this:

  subnets_output = {
        "EU2" = {
           aks = [
              "10.1.1.0/24",
            ]
          private_endpoints = [
              "10.1.1.2/24",
            ]
        }
    }

I would love to achieve an output look like this,

subnets_output2 = {
      aks = { 
          cider = ["10.1.1.0/24"], 
          type = "test" 
       },
      private_endpoints = { 
          cider = ["10.1.2.0/24"], 
          type = "base" 
       }
}

What I have now is:

##from local value
locals = {
    aks = {
      type = "test"
    }
    private_endpoints = {
      type = "base"
    }
}

Hi @BlueJapan,

There isn’t a single function for this situation, because what you want to achieve here is quite a specialized operation. I’m also not sure I fully understand your requirement, because I don’t see any rule in your description to decide the attribute names e and f.

It might be easier to talk about this if we have realistic names for whatever problem you are really trying to solve, but I’ve made a guess at what might be a suitable answer for you here:

locals {
  all_keys = setunion(keys(var.list), keys(var.list2))

  out = {
    for k in local.all_keys : k => {
      from_list  = try(var.list[k], null)
      from_list1 = try(var.list1[k], null)
    }
  }
}

The value of local.out should then be the following:

{
  a = {
    from_list = ["10"]
    from_list1 = {
      c = "hello"
    }
  }
  a = {
    from_list = ["20"]
    from_list1 = {
      d = "world"
    }
  }
}

This is the closest I can understand what you mean by your requirements, but I know that this doesn’t exactly match your example output. If the above doesn’t help you make progress, it would help if you could share a different example that is more realistic for what you are trying to achieve, using the real nouns that are involved, so that I can see more clearly how your intended result should relate to your input data.

1 Like

Just updated my question above. Thanks a lot.

(1)

output "lst_output2" {
    value = merge({for key in keys(var.lst): key => var.lst[key]}, {for key in keys(var.lst1) : key => var.lst1[key]})
}

Still not working…

(2)
But this is the closest i got

value = {for key in keys(var.lst): key => merge(var.lst[key], {key:var.lst1[key]})}

The output look like this:

output2 = {
      + aks        = {
          + key  = [
              + "10.1.1.0/24",
            ]
          + type = "test"
        }
      + production = {
          + key  = [
              + "10.1.2.0/24",
            ]
          + type = "base"
        }
    }

Hi @BlueJapan,

I think you are saying that the subnets_output you included is a local value, so would be local.subnets_output. You then have another local value whose name you didn’t include which contains the aks and private_endpoints attributes, with type attributes inside each one. Let’s call that local.other_attributes just so I have something to call it in this example.

So my understanding of the requirement is that you want to add an extra attribute called cider to each of the objects in local.other_attributes, while preserving the type attribute and presumably any other attributes that might appear there.

Here’s what I would do for that requirement:

locals {
  result = {
    for k, attrs in local.other_attributes : k => merge(
      attrs,
      { cider = local.subnets_output["EU2"][k] }
    )
  }
}