module.db是一个对象列表,只有在apply之后才知道

Par*_*hoo 2 terraform terraform-provider-aws

rds.tf:-

module "db" {
  **count  = var.environment == "dev" || var.environment == "qa" ? 1 : 0**
  source = "../rds"
  identifier = var.db_name
  engine                     = var.rds_engine
  engine_version             = var.rds_engine_version

output.tf:

output "rds_instance_endpoint" {
  description = "The connection endpoint"
  value       = module.db.db_instance_endpoint
}

ERROR:-

Error: Unsupported attribute
   on outputs.tf line 28, in output "rds_instance_endpoint":
   28:   value       = module.db.db_instance_endpoint
   module.db is a list of object, known only after apply

Can't access attributes on a list of objects. Did you mean to access attribute "db_instance_endpoint" for a specific element of the list, or across all elements of the list?
Run Code Online (Sandbox Code Playgroud)

在 rds.tf 模块中声明 count 时出现上述错误。如果我删除计数,那么它工作正常,不确定这个错误是什么。

Mar*_*ins 13

本例中的错误消息是“无法访问对象列表上的属性”这句话,而不是“module.db是对象列表,只有在应用后才知道”这句话;后者只是附加上下文,可帮助您理解随后的错误消息。

换句话说,Terraform 告诉您这module.db是一个对象列表,并且在该列表上使用.db_instance_endpoint(“访问属性”)是无效的。

这里的根本问题是您有一个模块对象可能存在也可能不存在,因此您需要向 Terraform 解释您希望如何处理它不存在的情况。

一个答案是更改输出值以返回一组实例端点,这些端点在开发和 QA 环境以外的环境中将为空:

output "rds_instance_endpoints" {
  description = "The connection endpoints for any database instances in this environment."
  value       = toset(module.db[*].db_instance_endpoint)
}
Run Code Online (Sandbox Code Playgroud)

这里我使用“splat”运算符来获取module 的每个实例的db_instance_endpoint属性值,这目前意味着根据情况它将是单元素集或空集。这种方法最直接地对底层实现进行建模,并且如果您需要的话,您可以在将来自由添加该模块的其他实例,但您可能会认为这是一个多实例模块,这是一个实现细节,应该是封装在模块本身中。


另一个主要选项确实隐藏了作为列表的底层模块的实现细节,它是让您的输出值处于null没有模块实例的情况下,或者在有一个实例时成为单个字符串。为此,我们可以稍微修改上面的示例以使用functionone不是function toset

output "rds_instance_endpoints" {
  description = "The connection endpoint for the database instance in this environment, if any."
  value       = one(module.db[*].db_instance_endpoint)
}
Run Code Online (Sandbox Code Playgroud)

one函数具有三种可能的结果,具体取决于给定集合中的元素数量:

  • 如果集合没有元素,它将返回null
  • 如果集合中有一个元素,它将仅返回该元素的值。
  • 如果集合有多个元素,它将失败并显示一条错误消息。但请注意,这种结果在您的情况下是不可能的,因为count只能设置为零或一。

如果将此数据返回到调用模块以在其他地方使用,则处理空值可能会很烦人,但有时它是所描述的基础设施的最合理表示,因此值得增加额外的复杂性。特别是对于根模块输出值,Terraform 会将 null 值视为根本未设置输出值,并将其隐藏在来自 的消息中terraform apply,因此,在您的主要动机是的情况下,第二种策略通常是最佳选择在用户界面中返回此信息以供人们用于某些后续操作。