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

时间:2018-10-18 23:33:25

标签: terraform

我正在尝试设置Google Cloud Load Balancer,而第一步需要更新托管实例组上的命名端口,为此,我需要使用格式字符串来生成命令行调用。我觉得这应该是我可以使用terraform自动化的东西,但是我正在努力映射数据格式。

我有两组源数据。

从实例组资源中:

data "google_compute_instance_group" "all" {
  count = "${length(var.backend)}"
  self_link = "${element(var.backend, count.index)}"
}

我从data.google_compute_instance_group.all.*.named_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骇客来做到这一点,但我对更好的解决方案感兴趣:

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

1 个答案:

答案 0 :(得分:1)

我能够使用for表达式使用terraform 0.12.x重新排列地图列表的列表。打破这句话

merge({ for l in local.lolom[0] : l.name => l.port }, { monitor = local.monitor })
  1. 它将经过由for l in local.lolom[0]表示的地图的第一个列表
  2. 然后它将设置地图名称等于返回地图本身的端口值,因此现在我们有了{ https = 30443, http = 30080 }
  3. 然后,merge()将我们的地图与monitor地图结合起来,以提供预期的结果

    {
      "http"    = "30080"
      "https"   = "30443"
      "monitor" = "30012"
    }
    

在不使用jsonencode的情况下,我找不到将以上内容转换为参数的方法,但是以下内容似乎可以提供预期的结果。

locals {
  lolom = [
    [
      { name : "https", port : 30443 },
      { name : "http", port : 30080 }
    ],
    [
      { name : "https", port : 30443 },
      { port : 30080, name : "http" }
    ]
  ]

  monitor = 30012

  first  = merge({ for l in local.lolom[0] : l.name => l.port }, { monitor = local.monitor })
  second = merge({ for l in local.lolom[1] : l.name => l.port }, { monitor = local.monitor })

  first_args  = replace(jsonencode(local.first), "/[\\{\\}\"\\s]/", "")
  second_args = replace(jsonencode(local.second), "/[\\{\\}\"\\s]/", "")
}

output "first_args" {
  value = local.first_args
}

output "second_args" {
  value = local.second_args
}

应用

$ terraform apply

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

first_args = http:30080,https:30443,monitor:30012
second_args = http:30080,https:30443,monitor:30012