Terraform创建EC2时ebs_block_device动态块调用EBS快照报element空列表错误
错误根因
- 大小写匹配冲突:快照的mount标签值为大写
/X01//X02,但传入的ebs_block_device参数里mount为小写/x01//x02,Terraform字符串匹配严格区分大小写,直接导致筛选结果为空 - 无空列表兼容逻辑:直接用
element(,0)取列表第一个元素,当筛选不到符合条件的快照时,空列表触发报错 - 命名规则兼容问题:当前ResourceName标签拆分逻辑仅适配
{前缀}-Node-{序号}-SNAP格式的命名,若Edge节点快照命名规则不同,也会触发空列表错误
修复方案
1. 修复匹配逻辑,添加空值兜底
将snapshot_id取值逻辑替换为以下代码,统一大小写匹配规则,匹配不到时可返回null(允许无快照创新盘)或主动抛出错误强制校验快照存在:
snapshot_id = try( element( [ for val in data.aws_ebs_snapshot.ebs_volume : val.id # 统一转小写匹配,消除大小写差异 if lower(val.tags["mount"]) == lower(tostring(lookup(ebs_block_device.value, "mount", ""))) && tostring(element(split("-", val.tags["ResourceName"]), length(split("-", val.tags["ResourceName"])) - 2)) == tostring(count.index + 1) ], 0 ), # 若要求必须匹配到快照,把null替换为abort("未找到匹配的EBS快照,请检查快照标签和传入参数") null )
2. 可选优化:提前构造快照映射表
在local块中提前完成快照索引映射,避免动态块内重复遍历,提升执行效率:
locals { # 构造 节点序号-小写mount路径 => 快照ID 的映射表 snapshot_mapping = { for snap in data.aws_ebs_snapshot.ebs_volume : "${element(split("-", snap.tags["ResourceName"]), length(split("-", snap.tags["ResourceName"])) - 2)}-${lower(snap.tags["mount"])}" => snap.id } }
动态块内直接从映射表取值即可:
snapshot_id = lookup(local.snapshot_mapping, "${count.index + 1}-${lower(tostring(lookup(ebs_block_device.value, "mount", "")))}", null)
3. 额外代码bug修复
当前kms_key_id取值逻辑存在类型匹配问题,encrypted标签为布尔值时和字符串"true"比对会返回false,建议修改为:
kms_key_id = lookup(ebs_block_device.value, "encrypted", false) ? var.kms_key_id : null
内容的提问来源于stack exchange,提问作者SLS
相关产品推荐
相关产品推荐

