我已经搜索了很多,但我认为我没有找到我真正需要的答案。我正在尝试循环一个嵌套块,如果所有属性都在同一个根对象上,我就成功地做到了。如果我想在整个属性集上循环,这非常好。然而,这种情况有点不同。我需要循环整个属性集和一个子集。
在这个Terragrunt示例中,您可以看到所需的输入,因为我们希望完全循环升级策略以及循环规则及其目标,这样我们就可以创建许多包含许多规则/目标的升级策略。
/// PagerDuty Escalation Policies
create_escalation_policy = true
escalation_policies = [
{
name = "TEST Engineering Escalation 1"
description = "My TEST engineering escalation policy 1"
teams = ["111N1CV"]
num_loops = 2
rule = [
{
escalation_delay_in_minutes = 15
target = {
type = "user_reference"
id = "ABCB8F3"
}
},
{
escalation_delay_in_minutes = 15
target = {
type = "user_reference"
id = "NBCB1A1"
}
}
}
]
然而,经过一番尝试和错误之后,我能够循环整个升级策略,但如果我们在rule = {
中有值,则不能循环。CCD_1返回一个一般错误,Terraform在我确认为根对象而不是嵌套对象的对象中找不到这些属性。这是通过简单地将这些属性移到对象输入块的根来验证的。
│ Error: Unsupported attribute
│
│ on main.tf line 121, in resource "pagerduty_escalation_policy" "this":
│ 121: id = rule.value.id
│ ├────────────────
│ │ rule.value is object with 5 attributes
│
│ This object does not have an attribute named "id".
作为参考,这里是var.escalation_policies 的变量
variable "escalation_policies" {
description = "A list of escalation policies and rules for a given PagerDuty service."
type = any
}
以及资源
resource "pagerduty_escalation_policy" "this" {
for_each = {
for key in var.escalation_policies : key.name => {
name = key.name
description = key.description
num_loops = key.num_loops
teams = key.teams
}
if var.create_escalation_policy == true
}
name = each.value.name
description = each.value.description
num_loops = each.value.num_loops
teams = each.value.teams
dynamic "rule" {
for_each = {
for k, v in var.escalation_policies : k => v }
content {
escalation_delay_in_minutes = rule.value.escalation_delay_in_minutes
target {
type = rule.value.type
id = rule.value.id
}
}
}
}
在您当前的示例中,dynamic "rule"
块有一个for
表达式,它实际上没有做任何有用的事情:
{ for k, v in var.escalation_policies : k => v }
这个表达在两个方面很奇怪:
- 单独使用表达式,将
k, v
直接投影到k => v
是不寻常的,因为这不会真正改变键或值的任何内容。由于源var.escalation_policies
是一个列表而不是映射,因此是更改结果的数据类型,并使Terraform将整数索引转换为字符串,但除此之外,元素与var.escalation_policies
相同 - 考虑到上下文,这也是不寻常的,因为它重复了基于与包含资源相同集合的嵌套块:每个
var.escalation_policy
元素将有一个pagerduty_escalation_policy.this
实例,然后每个实例将为每个升级策略有一个嵌套的rule
块
为了获得有用的结果,dynamic
块中的for_each
应该使用不同的集合作为其重复的基础。我认为在您的情况下,您打算在每个策略的rule
属性中使用嵌套列表,但最外层的for_each
表达式不包括规则,因此您首先需要更新:
resource "pagerduty_escalation_policy" "this" {
for_each = {
for policy in var.escalation_policies : policy.name => {
name = policy.name
description = policy.description
num_loops = policy.num_loops
teams = policy.teams
rules = policy.rule
}
if var.create_escalation_policy == true
}
# ...
}
这意味着CCD_ 15现在将包括附加属性CCD_。
然后,您可以在dynamic
块中引用rules
属性:
dynamic "rule" {
for_each = each.value.rules
content {
escalation_delay_in_minutes = rule.value.escalation_delay_in_minutes
target {
type = rule.value.target.type
id = rule.value.target.id
}
}
}
这个命令告诉Terraform为each.value.rules
的每个元素生成一个动态rule
块,这是当前策略的rules
属性。
在content
块中,rule.value
是当前的rule
对象,因此可以引用该对象中的escalation_delay_in_minutes
和target
等属性。
id
是target
对象中的键,而不是rule
:中的键
id = rule.value.target.id
还要注意的是,for
表达式在映射中遍历键值对并输出完全相同的结构,这是无关的,为了提高效率和可读性,可以删除:
dynamic "rule" {
for_each = var.escalation_policies
...
}