如何在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
相关产品推荐
相关产品推荐

