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

如何在Terraform中将YAML资源权限参数传入模块?

问题

我有一个本地YAML文件,内容如下:

- owner: "terraform-service-account"
    principal: "sa-1234"
    resources:
      - resource_name: "be_serivicing"
        resource_type: "TOPIC"
        operation: "WRITE"
      - resource_name: "cjiscool"
        resource_type: "TOPIC"
        operation: "READ"
  - owner: "terraform-service-account-write"
    principal: "sa-948534"
    resources:
      - resource_name: "cjiscoolgroup"
        resource_type: "GROUP"
        operation: "READ"

我希望将其中的resource_name、resource_type、principal和operation值传入Terraform模块。

我的代码中有如下输出:

output "principals_resources" {
  value = {for acl in local.acls : acl.owner => acl.resources}
}

输出结果为:

Changes to Outputs:
  + principals_resources = {
      + terraform-service-account       = [
          + {
              + operation     = "WRITE"
              + resource_name = "be_serivicing"
              + resource_type = "TOPIC"
            },
          + {
              + operation     = "READ"
              + resource_name = "cjiscool"
              + resource_type = "TOPIC"
            },
        ]
      + terraform-service-account-write = [
          + {
              + operation     = "READ"
              + resource_name = "cjiscoolgroup"
              + resource_type = "GROUP"
            },
        ]
    }

当我在模块中添加for_each时出现错误,当前模块代码如下:

module "acls" {
  source = "../acls"

  for_each = {for acl in local.acls : acl.owner => acl.resources}

  resource_type = each.value.resource_type
  resource_name = each.value.resource_name
  principal     = each.value.principal
  operation     = each.value.operation
}

报错信息:

│   on main.tf line 12, in module "acls":
│   12:   resource_type = each.value.resource_type
│     ├────────────────
│     │ each.value is tuple with 2 elements
│ 
│ This value does not have any attributes.

该模块用于创建Confluent Kafka ACL,模块代码如下:

resource "confluent_kafka_acl" "topic_write" {
  count = var.resource_type == "TOPIC" && var.operation == "WRITE" ? 1 : 0

  resource_type = "TOPIC"
  resource_name = var.resource_name
  pattern_type  = "LITERAL"
  principal     = "User:${var.principal}"
  host          = "*"
  operation     = "WRITE"
  permission    = "ALLOW"
}

我是Terraform新手,想了解如何正确将上述参数传入模块?

解决方案

核心问题

你当前的for_each把每个owner映射成一个资源数组,each.value是数组而非单个资源对象,自然无法直接读取resource_type这类属性。每个Kafka ACL是独立资源,需要为每个资源条目创建模块实例,而非每个owner创建一个。

步骤1:扁平化ACL条目

先把local.acls的嵌套结构展开,生成包含所有独立ACL条目的列表,每个条目带上对应的principal:

locals {
  flattened_acls = flatten([
    for acl in local.acls : [
      for res in acl.resources : merge(res, { principal = acl.principal })
    ]
  ])
}

这个操作会把每个owner下的资源条目拆成独立项,每个项都包含resource_name、resource_type、operation和对应的principal。

步骤2:遍历扁平条目创建模块实例

用for_each遍历扁平化后的列表,给每个实例生成唯一标识(用principal+resource_name+operation的组合):

module "acls" {
  source = "../acls"

  for_each = {
    for idx, acl in local.flattened_acls : 
    "${acl.principal}-${acl.resource_name}-${acl.operation}" => acl
  }

  resource_type = each.value.resource_type
  resource_name = each.value.resource_name
  principal     = each.value.principal
  operation     = each.value.operation
}

步骤3:优化模块内的资源定义

当前模块只处理TOPIC+WRITE的情况,建议改成通用写法适配所有ACL类型:

resource "confluent_kafka_acl" "main" {
  resource_type = var.resource_type
  resource_name = var.resource_name
  pattern_type  = "LITERAL"
  principal     = "User:${var.principal}"
  host          = "*"
  operation     = var.operation
  permission    = "ALLOW"
}

如果需要针对特定类型做特殊逻辑,再添加条件判断即可。

验证结果

可以添加输出查看扁平化后的条目,确认所有属性都正确:

output "flattened_acls" {
  value = local.flattened_acls
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 23:17:14