You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 04:18:26