Terraform列表对象迭代下Grafana联系点资源适配配置问题
解决Grafana联系点适配列表类型变量的方案
核心问题是:原来基于map类型变量的for_each迭代逻辑,改成list类型后,需要先把列表中每个对象的多渠道字段扁平化,生成带唯一标识的集合,才能适配Terraform资源的for_each要求。
1. 扁平化渠道列表(定义局部值)
先通过局部值把var.channel_list里每个对象的one-name和another-name提取出来,生成以「去掉#的渠道名」为键、完整渠道字符串(带#)为值的map——这样键既唯一,又和联系点名称直接对应:
locals { flattened_channels = merge([ for _, channel_pair in var.channel_list : { "${trim(channel_pair["one-name"], "#")}" = channel_pair["one-name"] "${trim(channel_pair["another-name"], "#")}" = channel_pair["another-name"] } ]...) }
这里的merge(...)是把每个列表元素生成的小map合并成一个大集合,...是Terraform的展开运算符。
2. 调整grafana_contact_point资源的迭代逻辑
把原来的for_each换成上面的局部值,同时简化字段配置(和原来的业务逻辑完全对齐):
resource "grafana_contact_point" "contact_point" { for_each = local.flattened_channels name = each.key # 直接用去#后的渠道名作为联系点名称 slack { ... # 保留你原有的slack其他配置 recipient = each.value # 传入带#的完整渠道字符串 username = "xy" } }
3. 修正通知策略的动态块逻辑
原来的lookup写法有误,直接提取字段并去掉#,就能匹配联系点的名称:
dynamic "policy" { for_each = var.channel_list content { matcher { label = "x" match = "=~" value = ".*" } # 关联one-name对应的联系点,用去#后的名称匹配 contact_point = trim(policy.value["one-name"], "#") group_by = ["..."] } }
如果需要给每个列表元素同时生成两个策略(分别对应one-name和another-name),可以把dynamic块的for_each换成local.flattened_channels,再在内容里对应调整即可。
额外提示
用渠道名作为for_each的键比用列表索引更稳定:即使列表元素顺序变化,也不会触发资源重建,只有渠道名修改时才会更新,更符合基础设施即代码的最佳实践。
内容的提问来源于stack exchange,提问作者DisplayName
相关产品推荐
相关产品推荐

