如何 select terraform 中 for_each 对象的特定实例
How to select specific instance of an for_each object in terraform
在模块us-region-1中,我定义了一个aws_lambda_layer_version
模块资源中的图层:
resource aws_lambda_layer_version "abc"{
for_each = ".xxxx."
layer_name = each.key
}
并且在全局主地形中,我定义了一个 lamba 层来引用它 aws_lambda_layer_version
,所以我必须定义一个数据资源来获取引用并依赖于模块资源
数据层
data aws_lambda_layer_version "abc"{
for_each = "..."
layer_name = each.key
depends_on = [??????]
# `aws_lambda_layer_version.abc` not work because it's not choose specific instance of aws_lambda_layer_version.abc.
}
Lambda 函数
resource "aws_lambda_function" "test-lambda-layers" {
for_each = ".xxxx."
layers = [data.aws_lambda_layer_version.abc[each.key].arn]
}
Terraform 中的依赖关系存在于整个资源之间,而不存在于各个资源实例之间。这是因为 count
和 for_each
参数本身可以创建依赖关系,因此 Terraform 只有在开始遍历依赖关系图后才能决定资源的实例。
话虽如此,我并不清楚你的问题为什么依赖于你的案例中的特定实例很重要。依赖关系只影响操作的顺序,而不影响 Terraform 将执行的操作,因此对 aws_lambda_layer_version.abc
的所有实例的依赖应该是对单个实例的依赖的可接受替代品:它仍然会提供相同的保证仅在它所依赖的事物之后才处理依赖,它只会也等到其他一些不相关的对象首先完成。
resource "aws_lambda_layer_version" "abc" {
for_each = ...
layer_name = each.key
}
data "aws_lambda_layer_version" "abc" {
for_each = aws_lambda_layer_version.abc
layer_name = each.value.layer_name
}
话虽如此,这个更新的配置仍然表现出 Terraform 反模式:特定的 Terraform 配置通常应该管理特定的对象 或 从远程读取该对象 API,永远不会同时出现。从你的问题的其余部分来看,你似乎需要使用 AWS Lambda Layer Version 对象的 ARN,在这种情况下你可以直接访问 the equivalent attribute from the managed resource type,而不是要求 Terraform 读回它已经管理的同一个对象:
resource "aws_lambda_function" "example" {
for_each = aws_lambda_layer_version.abc
layers = [each.value.arn]
}
如果您这样做的动机是在模块之间传播这些声明,那么更好的方法是直接在模块之间传递数据,而不是使用数据资源作为间接方式。在声明 aws_lambda_layer_version.abc
的模块中,您可以编写如下输出值:
output "lambda_layer_versions" {
value = tomap({
for k, lv in aws_lambda_layer_version.abc : k => {
id = lv.id
arn = lv.arn
}
})
}
这将构建一个对象映射,其键与您的 for_each
实例键相同,其中每个对象具有 id
和 arn
属性。
然后您的根模块可以从此对象访问 ARN:
module "layers" {
source = "./module/lambda-layers"
# ...
}
resource "aws_lambda_function" "test-lambda-layers" {
for_each = module.layers.lambda_layer_versions
layers = [each.value.arn]
}
在模块us-region-1中,我定义了一个aws_lambda_layer_version
模块资源中的图层:
resource aws_lambda_layer_version "abc"{
for_each = ".xxxx."
layer_name = each.key
}
并且在全局主地形中,我定义了一个 lamba 层来引用它 aws_lambda_layer_version
,所以我必须定义一个数据资源来获取引用并依赖于模块资源
数据层
data aws_lambda_layer_version "abc"{
for_each = "..."
layer_name = each.key
depends_on = [??????]
# `aws_lambda_layer_version.abc` not work because it's not choose specific instance of aws_lambda_layer_version.abc.
}
Lambda 函数
resource "aws_lambda_function" "test-lambda-layers" {
for_each = ".xxxx."
layers = [data.aws_lambda_layer_version.abc[each.key].arn]
}
Terraform 中的依赖关系存在于整个资源之间,而不存在于各个资源实例之间。这是因为 count
和 for_each
参数本身可以创建依赖关系,因此 Terraform 只有在开始遍历依赖关系图后才能决定资源的实例。
话虽如此,我并不清楚你的问题为什么依赖于你的案例中的特定实例很重要。依赖关系只影响操作的顺序,而不影响 Terraform 将执行的操作,因此对 aws_lambda_layer_version.abc
的所有实例的依赖应该是对单个实例的依赖的可接受替代品:它仍然会提供相同的保证仅在它所依赖的事物之后才处理依赖,它只会也等到其他一些不相关的对象首先完成。
resource "aws_lambda_layer_version" "abc" {
for_each = ...
layer_name = each.key
}
data "aws_lambda_layer_version" "abc" {
for_each = aws_lambda_layer_version.abc
layer_name = each.value.layer_name
}
话虽如此,这个更新的配置仍然表现出 Terraform 反模式:特定的 Terraform 配置通常应该管理特定的对象 或 从远程读取该对象 API,永远不会同时出现。从你的问题的其余部分来看,你似乎需要使用 AWS Lambda Layer Version 对象的 ARN,在这种情况下你可以直接访问 the equivalent attribute from the managed resource type,而不是要求 Terraform 读回它已经管理的同一个对象:
resource "aws_lambda_function" "example" {
for_each = aws_lambda_layer_version.abc
layers = [each.value.arn]
}
如果您这样做的动机是在模块之间传播这些声明,那么更好的方法是直接在模块之间传递数据,而不是使用数据资源作为间接方式。在声明 aws_lambda_layer_version.abc
的模块中,您可以编写如下输出值:
output "lambda_layer_versions" {
value = tomap({
for k, lv in aws_lambda_layer_version.abc : k => {
id = lv.id
arn = lv.arn
}
})
}
这将构建一个对象映射,其键与您的 for_each
实例键相同,其中每个对象具有 id
和 arn
属性。
然后您的根模块可以从此对象访问 ARN:
module "layers" {
source = "./module/lambda-layers"
# ...
}
resource "aws_lambda_function" "test-lambda-layers" {
for_each = module.layers.lambda_layer_versions
layers = [each.value.arn]
}