在 terraform 中创建动态块
Posted
技术标签:
【中文标题】在 terraform 中创建动态块【英文标题】:Create dynamic block in terraform 【发布时间】:2021-12-31 07:35:15 【问题描述】:我想在 terraform 中创建 google_compute_health_check
,我正在考虑如何使它们成为最通用的。我的代码 atm 是这样的
application.hcl
inputs =
health_checks =
tcp-health-check =
name = "tcp-health-check"
desc = "Health check via tcp"
port = 80
timeout_sec = 4
check_interval_sec = 30
主terragrunt.hcl
include
path = find_in_parent_folders()
terraform source ...
locals
app_vars = read_terragrunt_config(find_in_parent_folders("application.hcl"))
inputs =
# and my idea was that every invocation of the module, picks it's own set
# of health checks that it wants to use
health_checks = [local.app_vars.inputs.health_checks.tcp-health-check]
现在模块 main.tf
看起来像这样
locals
checks = for check in var.health_checks: check.name => check
resource "google_compute_health_check" "main"
for_each = local.checks
name = each.value.name
timeout_sec = each.value.timeout_sec
check_interval_sec = each.value.check_interval_sec
dynamic tcp_health_check
#for_each = each.value.name == "tcp_health_check" ? each.value : []
#for_each = lookup(each.value, "tcp_health_check", [])
for_each = contains(keys(each.value), "tcp_health_check") != null ? each.value :
content
port = 80
# port = each.value.port
# port_name = each.value.name
我被困在动态块中 - 如何使它工作,以便它仅在我通过 tcp
health_check 时应用,当我通过时,ssh
它创建动态 ssh
块(我知道代码 atm 中没有 ssh 块,但将来我会通过我需要的任何健康检查来扩展模块)
我得到的错误如下contains
Error: List longer than MaxItems
on main.tf line 30, in resource "google_compute_health_check" "main":
30: resource "google_compute_health_check" "main"
Attribute supports 1 item maximum, config has 7 declared
ERRO[0011] 1 error occurred:
* exit status 1
lookup
Error: ExactlyOne
on main.tf line 30, in resource "google_compute_health_check" "main":
30: resource "google_compute_health_check" "main"
"ssl_health_check": one of
`grpc_health_check,http2_health_check,http_health_check,https_health_check,ssl_health_check,tcp_health_check`
must be specified
ERRO[0005] 1 error occurred:
* exit status 1
与==
比较
Error: Inconsistent conditional result types
on main.tf line 44, in resource "google_compute_health_check" "main":
44: for_each = each.value.name == "tcp_health_check" ? each.value : []
|----------------
| each.value is object with 7 attributes
| each.value.name is "tcp-health-check"
The true and false result expressions must have consistent types. The given
expressions are object and tuple, respectively.
ERRO[0005] 1 error occurred:
* exit status 1
好的,以另一种方式解决了它,但感谢 Marcin 的回答
terragrunt.hcl
inputs =
name = "nat-health-check"
used_for = "used for NATs"
check_interval_sec = 30
timeout_sec = 5
healthy_threshold = 1
unhealthy_threshold = 5
http_checks = local.app_vars.inputs.health_checks.nat-http
和模块main.tf
resource "google_compute_health_check" "main"
name = var.name
timeout_sec = var.timeout_sec
check_interval_sec = var.check_interval_sec
description = "$var.name - $var.used_for"
dynamic "http_health_check"
for_each = var.http_checks != null ? [1] : []
content
port = var.http_checks.port
request_path = var.http_checks.request_path
port_specification = var.http_checks.port_specification
【问题讨论】:
您当前的代码有什么问题?有什么错误吗? 我已经把它们放在帖子里了 【参考方案1】:以下
contains(keys(each.value), "tcp_health_check") != null ? each.value :
失败,因为当这是真的时,您的动态块 tcp_health_check
将被执行不止一次,因为您的 each.value
只是一个值映射。你不能有超过一个 tcp_health_check
块。
第二个
for_each = lookup(each.value, "tcp_health_check", [])
没有失败并且是正确的。但由于它导致false
,因此不会创建您的tcp_health_check
块。这失败了,因为您没有提供任何替代块 grpc_health_check,http2_health_check,http_health_check,https_health_check,ssl_health_check,tcp_health_check
。
最后一次尝试:
for_each = each.value.name == "tcp_health_check" ? each.value : []
失败,因为它应该是for_each = each.value.name == "tcp_health_check" ? each.value :
。但如果你解决了这个问题,each.value
将再次像以前一样失败。
总而言之,你总是注定要失败,因为当你像第二种情况一样消除你的块 tcp_health_check
时,你并没有提供任何替代方案。如果你的条件是true
,each.value
会尝试创建多个块。
关闭解决方案是(不考虑虚假情况,您需要提供替代方案):
dynamic tcp_health_check
for_each = each.value.name == "tcp_health_check" ? [1] : []
content
port = each.value.port
port_name = each.value.name
【讨论】:
它仍然不起作用,抛出错误说它需要一个主要块(ssl/https/http/tcp)看起来像 for_each 中的 if 语句是错误的 @CptDolphin 您需要提供替代方案。你不这样做,所以你总是会失败。 我的意思是,我知道如果我不创建 tcp,我将不得不提供替代方案,但我传递(似乎)正确的值,它应该创建它,但它仍然没有通过用它嗯;生病测试一些并输入 - 如果它适合你,它也应该适合我 @CptDolphin 您的所有条件都返回false
。因此,您必须提供替代方案。如果您想要 true
,请更改您的条件或输入变量,因为 each.value.name == "tcp_health_check"
与您的变量不匹配。
好的,以其他方式进行,不是最好的但有效,感谢您的回答!以上是关于在 terraform 中创建动态块的主要内容,如果未能解决你的问题,请参考以下文章
如何在 terraform 中创建允许/拒绝防火墙规则条件?
在同一个 TF 脚本中使用多个 Terraform 提供程序(GCP 和 Kubernetes)创建资源