将地图列表更改为terraform中的格式化字符串

将地图列表更改为terraform中的格式化字符串,terraform,Terraform,我正在尝试设置Google云负载平衡器,其中一个步骤需要更新托管实例组上的命名端口,我需要一个格式化字符串来生成命令行调用。我觉得这应该是我可以用terraform自动化的东西,但我正在努力映射数据格式 我有两组源数据 从实例组资源: data "google_compute_instance_group" "all" { count = "${length(var.backend)}" self_link = "${element(var.backend, count.index)}"

我正在尝试设置Google云负载平衡器,其中一个步骤需要更新托管实例组上的命名端口,我需要一个格式化字符串来生成命令行调用。我觉得这应该是我可以用terraform自动化的东西,但我正在努力映射数据格式

我有两组源数据

从实例组资源:

data "google_compute_instance_group" "all" {
  count = "${length(var.backend)}"
  self_link = "${element(var.backend, count.index)}"
}
我从
data.google\u compute\u instance\u group.all.*.named\u port
中获取现有的命名端口,格式如下:

[
    [
        map[name:https port:30443],
        map[name:http port:30080]
    ],
    [
        map[name:https port:30443],
        map[port:30080 name:http]
    ]
]
我还希望确保在我自己的映射中定义端口:

variable "node_ports" {
  type    = "map"
  default = {
    "https"   = "30443"
    "monitor" = "30012"
  }
}
两者之间可能存在重叠;我想选择变量中定义的值。(所有实例组的命名端口都相同。)

首先,我想将两个映射合并成一个映射,以确保每个名称都有一个端口。如何将第一个地图列表转换为单个地图,以便获得此结果

{
  "http"    = "30080"
  "https"   = "30443"
  "monitor" = "30012"
}
其次,我想将所有这些转换为命令行所需的格式:

gcloud --project ${var.project} compute instance-groups set-named-ports ${basename(var.backend[count.index])} --named-ports=https:443,http:30080,monitor:30012
我想我可以通过
jsonencode
hack做到这一点,但我对更好的解决方案感兴趣:

"${replace(jsonencode(named_ports), "/[\\{\\}\"\\s]/", "")}"

我能够使用for表达式使用terraform 0.12.x重新排列地图列表。打破这种说法

merge({for l in local.loloom[0]:l.name=>l.port},{monitor=local.monitor})
  • 它将遍历local.lolom[0]l的第一个映射列表
  • 然后它会将映射的名称设置为端口返回映射本身的值,因此现在我们有了
    {https=30443,http=30080}
  • 然后,
    merge()
    将把我们的地图与
    监视器
    地图结合起来,给出我们想要的结果

    {
      "http"    = "30080"
      "https"   = "30443"
      "monitor" = "30012"
    }
    
  • 如果不使用
    jsonencode
    ,我无法找到将上述内容转换为参数的方法,但下面似乎提供了预期的结果

    本地人{
    lolom=[
    [
    {name:“https”,端口:30443},
    {name:“http”,端口:30080}
    ],
    [
    {name:“https”,端口:30443},
    {端口:30080,名称:“http”}
    ]
    ]
    监视器=30012
    first=merge({for l in local.lolom[0]:l.name=>l.port},{monitor=local.monitor})
    second=merge({for l in local.loloom[1]:l.name=>l.port},{monitor=local.monitor})
    first\u args=replace(jsonecode(local.first),“/[\\{\\\\\\”\\s]/”,“”)
    second\u args=replace(jsonecode(local.second),“/[\\{\\\\\\\”\\s]/”,“”)
    }
    输出“第一个参数”{
    value=local.first\u参数
    }
    输出“第二个参数”{
    value=local.second_参数
    }
    
    申请

    $terraform应用
    申请完成!资源:添加0个,更改0个,销毁0个。
    产出:
    第一个参数=http:30080,https:30443,监视器:30012
    second_args=http:30080,https:30443,monitor:30012