关于Terraform旧版本中split/join/list嵌套代码的逻辑解析、优化及空元素移除的技术问询
关于这段Terraform代码的分析与优化建议
Hey,我来帮你拆解这段有点绕的Terraform代码,结合你提到的背景(原作者是为了兼容老版本Terraform),咱们一步步来理清楚:
1. 原语句的逻辑到底是什么?
首先看你单独拎出来的join(",", concat(data.yyy_ids.public.ids, list(""))):
- 原作者首先用
concat把public.ids列表和一个只包含空字符串的列表拼在一起——这一步是为了确保拼接后的列表绝对不会是空的,哪怕public.ids里啥都没有,拼接后至少还有个""元素。 - 接着用
join把这个拼接后的列表转成字符串:如果public.ids是["subnet-123", "subnet-456"],结果就是"subnet-123,subnet-456,";如果public.ids是空的,结果就是","。 - 再结合外层的
split(",", ...),把字符串又拆回列表:上面第一个例子会变成["subnet-123", "subnet-456", ""],第二个例子会变成["", ""]。 - 为啥要这么折腾?因为Terraform 0.12之前的条件表达式不支持直接返回列表类型,只能通过
join把列表转成字符串,再用split转回去,而原作者担心如果public.ids是空的,直接join会得到空字符串,split后就成了空列表,可能触发资源的参数校验错误,所以才加了这个空字符串兜底。
2. 有没有更清爽的写法?
当然有!关键看你们现在用的Terraform版本:
如果已经升级到Terraform 0.12+(强烈建议)
直接抛弃这种字符串来回转的骚操作,用原生的列表条件表达式就行:
- 如果你需要确保
subnet_ids永远是非空列表(比如LB资源要求必须指定子网),可以给空列表加个默认子网:
subnet_ids = var.xxx_lb ? data.yyy_ids.private.ids : (length(data.yyy_ids.public.ids) > 0 ? data.yyy_ids.public.ids : ["your-default-subnet-id"])
- 如果你的资源允许
subnet_ids是空列表,那写法更简单:
subnet_ids = var.xxx_lb ? data.yyy_ids.private.ids : data.yyy_ids.public.ids
直接返回列表就行,完全不需要join/split这些多余操作。
如果还在坚守Terraform 0.12以下版本
也可以优化掉拼接空字符串的操作,用coalesce函数兜底:
subnet_ids = split(",", var.xxx_lb ? join(",", data.yyy_ids.private.ids) : coalesce(join(",", data.yyy_ids.public.ids), "your-default-subnet-id"))
这样如果public.ids是空的,会用你指定的默认子网ID,而不是空字符串,更符合实际需求。
3. 要是必须保留原逻辑,怎么去掉空元素?
如果因为某些原因没法改整体逻辑,要过滤掉结果里的空字符串,分两种情况:
- Terraform 0.12+:直接用
compact函数,它会自动过滤列表里的所有空字符串:
subnet_ids = compact(split(",", var.xxx_lb ? join(",", data.yyy_ids.private.ids) : join(",", concat(data.yyy_ids.public.ids, list("")))))
- Terraform 0.12以下:这个版本没有
compact也没有列表推导式,只能用count和element手动构建过滤后的列表,非常繁琐,举个例子:
locals { subnet_str = var.xxx_lb ? join(",", data.yyy_ids.private.ids) : join(",", concat(data.yyy_ids.public.ids, list(""))) subnet_list = split(",", local.subnet_str) valid_count = "${length(regexall("[^,]+", local.subnet_str))}" } resource "aws_lb" "example" { subnet_ids = ["${element(split(",", local.subnet_str), count.index)}"] count = "${local.valid_count}" }
说实话,这种写法太折磨人了,真的建议赶紧升级到0.12+版本。
内容的提问来源于stack exchange,提问作者GaTechThomas
相关产品推荐
相关产品推荐

