反转Terraform中的嵌套映射和列表

huangapple go评论53阅读模式
英文:

Invert nested maps and list in Terraform

问题

{
"我在Terraform中有这样的结构:": {
"us1": {
"0": "192.168.1.1"
},
"europe2": {
"0": "192.168.10.1",
"1": "10.0.0.1"
}
},
"我想将其转换为这种结构:": {
"0": {
"europe2": "192.168.1.1",
"us1": "192.168.10.1"
},
"1": {
"europe2": "10.0.0.1"
}
},
"我在这里使用了带有01作为索引的映射,但在起始和结束结构中都可以使用列表。有没有人知道如何做到这一点?": "我看到了像省略号这样的运算符,或者像setproduct()这样的函数,但我没能弄清楚如何解决这个问题。"
}

英文:

I have this structure in Terraform:

{
    "us1" : {
        "0": "192.168.1.1"
    },
    "europe2" : {
        "0": "192.168.10.1",
        "1": "10.0.0.1"
    }
}

I want to transform it into this structure:

{
    "0": {
        "europe2": "192.168.1.1",
        "us1": "192.168.10.1"
    },
    "1": {
        "europe2": "10.0.0.1"
    }
}

I used maps with 0 and 1 as indexing for clarity, but lists can be used instead in both starting and ending structure. Anyone has an idea how to do this ?

I saw operators like ellipsis, or functions like setproduct() but I didn't managed to sort this out.

答案1

得分: 1

这是您要寻找的构建方式:

variable "test" {

  default = {
    "us1" : {
      "0": "192.168.1.1"
    },
    "europe2" : {
      "0": "192.168.10.1",
      "1": "10.0.0.1"
    }
  }
}

locals {

  # in three steps
  flatten_map = merge([
    for key, val in var.test : 
      { for idx, sub_val in val : "${key}-${idx}" => sub_val }
  ]...)
  pre_final_map = {
    for k, v in local.flatten_map : 
      "${split("-", k)[1]}" => { "${split("-", k)[0]}" = v }...
  }
  final_map = {
    for k, v in local.pre_final_map:
      k => merge(v...)
  }

  # all in one
  all_in_one_map = {
    for k0, v0 in {
      for k, v in merge([
        for key, val in var.test :
          { for idx, sub_val in val : "${key}-${idx}" => sub_val }
      ]...) : "${split("-", k)[1]}" => { "${split("-", k)[0]}" = v }...
    } : "${k0}" => merge(v0...)
  }

  # convert to list
  as_list = [
    for k0, v0 in {
      for k, v in merge([
        for key, val in var.test :
          { for idx, sub_val in val : "${key}-${idx}" => sub_val }
      ]...) : "${split("-", k)[1]}" => { "${split("-", k)[0]}" = v }...
    } : merge(v0...)
  ]
}

output in_three_steps {
  value = local.final_map
}

output in_one_step {
  value = local.all_in_one_map
}

output list_representation {
  value = local.as_list
}

输出:

in_one_step = {
  "0" = {
    "europe2" = "192.168.10.1",
    "us1" = "192.168.1.1"
  }
  "1" = {
    "europe2" = "10.0.0.1"
  }
}
in_three_steps = {
  "0" = {
    "europe2" = "192.168.10.1",
    "us1" = "192.168.1.1"
  }
  "1" = {
    "europe2" = "10.0.0.1"
  }
}
list_representation = [
  {
    "europe2" = "192.168.10.1",
    "us1" = "192.168.1.1"
  },
  {
    "europe2" = "10.0.0.1"
  }
]
英文:

This construction is what you are looking for:

variable "test" {

  default = {
    "us1" : {
      "0": "192.168.1.1"
    },
    "europe2" : {
      "0": "192.168.10.1",
      "1": "10.0.0.1"
    }
  }
}

locals {

  # in three steps
  flatten_map = merge([
    for key, val in var.test : 
      { for idx, sub_val in val : "${key}-${idx}" => sub_val }
  ]...)
  pre_final_map = {
    for k, v in local.flatten_map : 
      "${split("-", k)[1]}" => { "${split("-", k)[0]}" = v }...
  }
  final_map = {
    for k, v in local.pre_final_map:
      k => merge(v...)
  }

  # all in one
  all_in_one_map = {
    for k0, v0 in {
      for k, v in merge([
        for key, val in var.test :
          { for idx, sub_val in val : "${key}-${idx}" => sub_val }
      ]...) : "${split("-", k)[1]}" => { "${split("-", k)[0]}" = v }...
    } : "${k0}" => merge(v0...)
  }

  # convert to list
  as_list = [
    for k0, v0 in {
      for k, v in merge([
        for key, val in var.test :
          { for idx, sub_val in val : "${key}-${idx}" => sub_val }
      ]...) : "${split("-", k)[1]}" => { "${split("-", k)[0]}" = v }...
    } : merge(v0...)
  ]
}

output in_three_steps {
  value = local.final_map
}

output in_one_step {
  value = local.all_in_one_map
}

output list_representation {
  value = local.as_list
}

output:

in_one_step = {
  "0" = {
    "europe2" = "192.168.10.1"
    "us1" = "192.168.1.1"
  }
  "1" = {
    "europe2" = "10.0.0.1"
  }
}
in_three_steps = {
  "0" = {
    "europe2" = "192.168.10.1"
    "us1" = "192.168.1.1"
  }
  "1" = {
    "europe2" = "10.0.0.1"
  }
}
list_representation = [
  {
    "europe2" = "192.168.10.1"
    "us1" = "192.168.1.1"
  },
  {
    "europe2" = "10.0.0.1"
  },
]

答案2

得分: 0

我有一个更快的示例:

locals {
  original_map = {
    "us1" : {
      "0" : "192.168.1.1"
    },
    "europe2" : {
      "0" : "192.168.10.1",
      "1" : "10.0.0.1"
    }
  }
}

locals {
  original_maps_values = [for key, value in local.original_map : [for idx, sub_value in value : [key, sub_value, idx]]]
  transformed_map      = { for v in chunklist(flatten(local.original_maps_values), 3) : v[2] => { "${v[0]}" = v[1] }... }
}

output "transformed_map" {
  value = { for k, v in local.transformed_map : k => merge(v...) }
}

参考链接:
expanding-function-arguments

英文:

i have a much faster example:

locals {
  original_map = {
    "us1" : {
      "0" : "192.168.1.1"
    },
    "europe2" : {
      "0" : "192.168.10.1",
      "1" : "10.0.0.1"
    }
  }
}

locals {
  original_maps_values = [for key, value in local.original_map : [for idx, sub_value in value : [key, sub_value, idx]]]
  transformed_map      = { for v in chunklist(flatten(local.original_maps_values), 3) : v[2] => { "${v[0]}" = v[1] }... }
}

output "transformed_map" {
  value = { for k, v in local.transformed_map : k => merge(v...) }
}

references:
expanding-function-arguments

huangapple
  • 本文由 发表于 2023年2月6日 19:56:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/75360995.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定