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

Terraform模块调用数据/资源时,变量的正确使用及报错解决

Terraform动态引用AWS IAM策略文档数据源问题解决

问题代码与报错

main.tf

module "SCP-L2-RegionRestriction" {
  source        = "github.com/awsmodulecode/scps.git"
  scp_name      = "SCP-L2-RegionRestriction"
} 

模块代码(main.tf)

resource "aws_organizations_policy" "SCP-L2-RegionRestriction" {
  name    = var.scp_name
  content = data.aws_iam_policy_document."${var.scp.name}".json
}

模块变量(variables.tf)

variable "scp_name" {
  description = "Policy name."
}

报错信息

╷
│ Error: Invalid attribute name
│ 
│ On .terraform/modules/SCP-L2-RegionRestriction/main.tf line 4: An attribute name is required after a dot.
╵

已定义的数据源

data "aws_iam_policy_document" "scp_fulladmin_deny" {
    statement {
            actions = ["*"]
            resources = ["*"]
            effect = "Deny"
            }
}
data "aws_iam_policy_document" "scp_fulladmin_allow" {
    statement {
            actions = ["*"]
            resources = ["*"]
            effect = "Allow"
            }
}

问题分析

你尝试用"${var.scp.name}"动态拼接数据源名称的方式在Terraform里是不支持的——Terraform的资源/数据源引用是静态的,不能通过变量拼接名称实现动态调用。另外你的模块变量仅定义了scp_name,不存在var.scp.name这个变量,这也是触发报错的直接原因。

解决方案

要实现根据变量选择不同策略文档的需求,推荐两种常用方法:

方法1:模块内通过变量映射匹配数据源

  1. 修改模块的variables.tf,新增变量指定策略类型:
variable "scp_name" {
  description = "Policy name."
}

variable "scp_policy_type" {
  description = "指定要使用的策略文档类型,可选值:scp_fulladmin_deny、scp_fulladmin_allow"
  type        = string
  validation {
    condition     = contains(["scp_fulladmin_deny", "scp_fulladmin_allow"], var.scp_policy_type)
    error_message = "必须指定有效的策略类型:scp_fulladmin_deny 或 scp_fulladmin_allow。"
  }
}
  1. 修改模块的main.tf,用映射表匹配对应数据源:
locals {
  policy_documents = {
    scp_fulladmin_deny = data.aws_iam_policy_document.scp_fulladmin_deny.json
    scp_fulladmin_allow = data.aws_iam_policy_document.scp_fulladmin_allow.json
  }
}

resource "aws_organizations_policy" "SCP-L2-RegionRestriction" {
  name    = var.scp_name
  content = lookup(local.policy_documents, var.scp_policy_type, null)
}
  1. 根模块调用时指定策略类型:
module "SCP-L2-RegionRestriction" {
  source           = "github.com/awsmodulecode/scps.git"
  scp_name         = "SCP-L2-RegionRestriction"
  scp_policy_type  = "scp_fulladmin_deny" # 按需切换类型
} 

方法2:直接传入策略文档内容(低耦合更通用)

如果模块不需要依赖内部数据源,直接将策略内容作为变量传入,通用性更强:

  1. 修改模块的variables.tf:
variable "scp_name" {
  description = "Policy name."
}

variable "scp_content" {
  description = "SCP策略文档的JSON内容"
  type        = string
}
  1. 修改模块的main.tf:
resource "aws_organizations_policy" "SCP-L2-RegionRestriction" {
  name    = var.scp_name
  content = var.scp_content
}
  1. 根模块调用时传入数据源内容:
module "SCP-L2-RegionRestriction" {
  source        = "github.com/awsmodulecode/scps.git"
  scp_name      = "SCP-L2-RegionRestriction"
  scp_content   = data.aws_iam_policy_document.scp_fulladmin_deny.json
} 

注意事项

  • Terraform不支持动态拼接资源/数据源名称,所有资源引用必须是静态定义的。
  • 方法2的模块耦合度更低,无需关心具体策略文档定义,更适合跨场景复用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 09:35:21