如何在Terraform中提取CSV列唯一值解决NSG创建重复报错
问题描述
基于存储网络安全规则的CSV文件创建NSG(网络安全组)时,因列表内存在重复值导致资源创建失败,需在Terraform中提取CSV列的去重唯一值完成资源部署。
原有问题配置
locals { csv_data = <<-CSV id,nsgname,rgname,rule,priority 1,nsg-one,rg-test,rule1,100 2,nsg-one,rg-test,rule2,110 3,nsg-one,rg-test,rule3,120 4,nsg-one,rg-test,rule4,130 5,nsg-one,rg-test,rule5,100 6,nsg-one,rg-test,rule6,110 7,nsg-one,rg-test,rule7,120 8,nsg-one,rg-test,rule8,130 9,nsg-two,rg-test,rule9,2300 10,nsg-two,rg-test,rule10,2300 11,nsg-two,rg-test,rule11,2140 12,nsg-two,rg-test,rule12,2140 13,nsg-three,rg-test,rule13,2100 14,nsg-three,rg-test,rule14,2110 15,nsg-three,rg-test,rule15,2120 16,nsg-three,rg-test,rule16,2130 17,nsg-three,rg-test,rule17,2100 18,nsg-three,rg-test,rule18,2130 19,nsg-three,rg-test,rule19,2140 20,nsg-three,rg-test,rule20,2140 21,nsg-four,rg-test,rule21,2300 22,nsg-four,rg-test,rule22,2140 23,nsg-four,rg-test,rule23,2140 CSV nsgss = csvdecode(local.csv_data) } resource "azurerm_network_security_group" "tf_network_security_groups" { for_each = { for nsg in local.nsgss : nsg.id => nsg } name = format("nsg-%s", each.value.nsgname) location = "uksouth" resource_group_name = "rg-test" }
注:本示例默认资源组rg-test已存在,测试配置时可手动创建该资源组,或使用以下配置完成创建:
resource "azurerm_resource_group" "tf_resource_group" { name = "rg-test" location = "uksouth" }
问题根因
原配置直接使用CSV每行的自增id作为for_each的唯一键,会为每一行规则记录都尝试生成同名NSG资源。Azure规定同一资源组下NSG名称必须唯一,重复创建同名资源会直接触发部署失败。
修复方案
先对CSV数据按NSG标识维度做去重,生成键唯一的NSG映射集,再传入for_each完成资源创建。
1. 新增locals去重逻辑
在原有locals块中增加去重处理,使用Terraform内置distinct函数提取唯一NSG条目,再转换为for_each支持的映射结构:
locals { # 原有csv_data、nsgss配置保持不变 # 提取去重后的NSG基础属性列表 unique_nsgs = distinct([ for nsg in local.nsgss : { nsgname = nsg.nsgname rgname = nsg.rgname } ]) # 转换为以NSG名称为键的映射,确保键全局唯一 nsg_map = { for nsg in local.unique_nsgs : nsg.nsgname => nsg } }
2. 修改NSG资源的for_each配置
将NSG资源的for_each数据源替换为去重后的nsg_map:
resource "azurerm_network_security_group" "tf_network_security_groups" { for_each = local.nsg_map name = each.key location = "uksouth" resource_group_name = each.value.rgname }
关键逻辑说明
distinct函数会自动对比传入集合内的结构体,返回完全去重后的列表,自动过滤CSV中同个NSG关联多条规则产生的重复条目- 最终生成的
nsg_map以NSG名称作为唯一键,完全满足Terraform for_each对键唯一性的要求,不会触发重复创建错误 - 后续如需为每个NSG批量绑定安全规则,可使用
groupby函数按nsgname对原始nsgss列表做分组,再通过azurerm_network_security_rule资源遍历创建即可。
内容的提问来源于stack exchange,提问作者Display name
相关产品推荐
相关产品推荐

