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

从Terraform数据块提取子网生成locals列表失败求助

问题排查:Terraform构建Web应用子网访问限制时的属性错误

问题场景

尝试创建带有VNet访问限制的Web应用,需传入子网名称、子网ID及优先级。先通过以下数据块获取子网列表:

data "azurerm_virtual_network" "vnet" {
  name                = var.np_vnet1
  resource_group_name = var.np_vnet_rg
}

data "azurerm_subnet" "np-vnet1-subnets" {
  for_each             = toset(data.azurerm_virtual_network.vnet.subnets)
  name                 = each.value
  virtual_network_name = data.azurerm_virtual_network.vnet.name
  resource_group_name  = data.azurerm_virtual_network.vnet.resource_group_name
}

接着在locals中构建格式,动态传入azurerm_windows_web_app资源:

locals {
subnet_restrictions = [
    for idx, subnet in [data.azurerm_subnet.np-vnet1-subnets] : {
      name                      = subnet.name
      virtual_network_subnet_id = subnet.id
      priority                  = idx + 100
    }
  ]
}

最终传入Web应用的ip_restrictions:

dynamic "ip_restriction" {
      for_each = local.subnet_restrictions
      content {
        name                      = ip_restriction.value["name"]
        virtual_network_subnet_id = ip_restriction.value["virtual_network_subnet_id"]
        priority                  = ip_restriction.value["priority"]
        action                    = "Allow"
      }
    }

但执行时持续报错,提示对象无name或id属性:

│ Error: Unsupported attribute
│
│   on locals.tf line 29, in locals:
│   29:       name                      = subnet.name
│
│ This object does not have an attribute named "name".
╵
╷
│ Error: Unsupported attribute
│
│   on locals.tf line 30, in locals:
│   30:       virtual_network_subnet_id = subnet.id
│
│ This object does not have an attribute named "id".

错误根源

[data.azurerm_subnet.np-vnet1-subnets]的写法是核心问题:你把整个map类型的数据源对象包装成了一个单元素列表,循环中的subnet变量指向的是整个map,而非单个子网资源实例,因此无法直接调用name和id属性。

使用for_each创建的数据源azurerm_subnet.np-vnet1-subnets本质是一个键值对map,键为子网名称,值为对应的子网资源对象。

修正方案

方案1:遍历子网数据源的values集合

直接遍历数据源的values集合,用索引计算优先级:

locals {
  subnet_restrictions = [
    for idx, subnet in values(data.azurerm_subnet.np-vnet1-subnets) : {
      name                      = subnet.name
      virtual_network_subnet_id = subnet.id
      priority                  = idx + 100
    }
  ]
}

方案2:保留键值对关联(可选)

如果需要保留子网名称与资源的关联,可将map转换为目标结构,后续动态块遍历map的values即可:

locals {
  subnet_restrictions = {
    for subnet_name, subnet in data.azurerm_subnet.np-vnet1-subnets : subnet_name => {
      name                      = subnet.name
      virtual_network_subnet_id = subnet.id
      priority                  = index(keys(data.azurerm_subnet.np-vnet1-subnets), subnet_name) + 100
    }
  }
}

# 动态块调整为遍历map的values
dynamic "ip_restriction" {
  for_each = local.subnet_restrictions
  content {
    name                      = ip_restriction.value.name
    virtual_network_subnet_id = ip_restriction.value.virtual_network_subnet_id
    priority                  = ip_restriction.value.priority
    action                    = "Allow"
  }
}

额外优化:避免索引顺序问题(可选)

若担心子网名称排序导致优先级变化,可通过哈希值生成更稳定的优先级:

priority = tonumber(substr(sha1(subnet.name), 0, 3)) + 100

内容的提问来源于stack exchange,提问作者NickP

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 04:47:15