我们正在尝试将动态名称应用于防火墙规则,以便使用基于实例组 URL 列表的 terraform 在 GCP 中打开 8089 和 8843。它没有获取结果并给我们 url 中的最后一项,而是给我们 https:
tf:
#This is to resolve an error when deploying to nginx
resource "google_compute_firewall" "ingress" {
for_each = toset(google_container_cluster.standard-cluster.instance_group_urls)
description = "Allow traffic on ports 8843, 8089 for nginx ingress"
direction = "INGRESS"
name = element(split("/", each.key), length(each.key))
network = "https://www.googleapis.com/compute/v1/projects/${local.ws_vars["project-id"]}/global/networks/${local.ws_vars["environment"]}"
priority = 1000
source_ranges = google_container_cluster.standard-cluster.private_cluster_config.*.master_ipv4_cidr_block
target_tags = [
element(split("/", each.key), length(each.key))
]
allow {
ports = [
"8089",
]
protocol = "tcp"
}
allow {
ports = [
"8443",
]
protocol = "tcp"
}
}
结果:
Error: "name" ("https:") doesn't match regexp "^(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?)$"
on main.tf line 133, in resource "google_compute_firewall" "ingress":
133: name = element(split("/", each.key), length(each.key))
这里的解决方案是什么?为什么它不给出数组中的最后一项?有更好的办法吗?
与许多语言一样,Terraform/HCL 使用基于零的索引,因此如果您想要数组中的最后一个元素,则需要从长度中减一,如下所示:
locals {
list = ["foo", "bar", "baz"]
}
output "last_element" {
value = element(local.list, length(local.list) - 1)
}
element
函数导致了这种混乱,因为当您尝试访问超出它所环绕的列表的长度时,而不是出现越界/范围错误,因此您得到的是第一个元素:
该索引是从零开始的。如果与以下函数一起使用,此函数会产生错误 一个空列表。索引必须是非负整数。
大多数情况下使用内置索引语法list[index]。用这个 功能仅适用于特殊的附加“环绕”行为 如下所述。
要从列表中获取最后一个元素,请使用 length 来查找其大小 列表(负 1,因为列表是从零开始的),然后选择最后一个 元素:
> element(["a", "b", "c"], length(["a", "b", "c"])-1) c
不幸的是,在撰写本文时,Terraform 目前不支持内置索引语法中的负索引:
locals {
list = ["foo", "bar", "baz"]
}
output "last_element" {
value = local.list[-1]
}
抛出以下错误:
Error: Invalid index
on main.tf line 6, in output "last_element":
6: value = local.list[-1]
|----------------
| local.list is tuple with 3 elements
The given key does not identify an element in this collection value.
正如 comments 中所建议的,这里更好的方法是首先反转列表,然后使用
reverse
函数从反转列表中取出第一个元素:
output "last_element" {
value = reverse(local.list)[0]
}
如果你的字符串只被分割一次,你可以忽略元素函数:
message1 = split("/", "text1/text2")[0] # get text1
message2 = split("/", "text1/text2")[1] # get text2