Terraform中如何在for_each循环内排除指定子网?
Terraform 0.14 使用 regexall 过滤 for_each 子网对象的解决方案
问题场景
我用hashicorp/subnets/cidr模块生成了一批子网对象列表,需要通过for_each遍历这些子网创建google_compute_global_address资源,但得排除名称以not-in-use开头的子网。
一开始我写了这样的代码:
for_each = {for subnet in module.regions.networks: subnet.name => subnet if regexall("^in-use", subnet.name)}
结果直接报错:
Error: Invalid 'for' condition The 'if' clause value is invalid: bool required.
哪怕把regexall()套在length()里也没解决问题。
注:虽然startswith()是处理前缀匹配更合适的函数,但我用的是Terraform 0.14版本,这个函数还没推出,只能继续用regexall(),最后加个>0就搞定了。
错误原因
Terraform的for表达式里,if子句必须返回布尔值(true/false),但regexall()的返回值是匹配结果的列表,不是布尔值,直接用它当条件就会触发类型不匹配的错误。之前用length()没生效,大概率是写法不对——得明确判断列表长度是否大于0,把列表结果转成布尔值才行。
解决方法
调整for_each的表达式,通过length(regexall(...)) > 0把正则匹配结果转换成布尔条件,就能符合if子句的要求了。
匹配以in-use开头的子网(保留这类子网)
for_each = { for subnet in module.regions.networks : subnet.name => subnet if length(regexall("^in-use", subnet.name)) > 0 }
排除以not-in-use开头的子网(符合最初需求)
如果你的目标是排除前缀为not-in-use的子网,对应的正则和条件要改成这样:
for_each = { for subnet in module.regions.networks : subnet.name => subnet if length(regexall("^not-in-use", subnet.name)) == 0 }
另一种简洁写法
Terraform会把非空列表隐式转为true,空列表转为false,所以也可以这么写(不过显式判断长度的写法可读性更强):
for_each = { for subnet in module.regions.networks : subnet.name => subnet if regexall("^in-use", subnet.name) != [] }
内容的提问来源于stack exchange,提问作者red888
相关产品推荐
相关产品推荐

