In module us-region-1, I define a aws_lambda_layer_version
Layers in module resource:
resource aws_lambda_layer_version "abc"{
for_each = ".xxxx."
layer_name = each.key
}
And in global main terraform, I define an lamba layers to reference to that aws_lambda_layer_version
, so I have to define an data resource to get reference and depend on module resource
Data layers
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 function
resource "aws_lambda_function" "test-lambda-layers" {
for_each = ".xxxx."
layers = [data.aws_lambda_layer_version.abc[each.key].arn]
}
Dependencies in Terraform are between resources as a whole, and not between individual instances of resources. This is because the count
and for_each
arguments can themselves create dependencies, and so Terraform can decide the instances for a resource only after it's begun walking the dependency graph.
With that said, it's not clear to me from your question why it's important to depend on specific instances in your case. Dependencies only affect the order of operations and not which operations Terraform will perform, and so a dependency on all of the instances of aws_lambda_layer_version.abc
should be an acceptable substitute for a dependency on an individual instance: it'll still provide the same guarantee that the dependent will be processed only after the thing it depends on, it'll just also wait until some other unrelated objects were complete first.
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
}
With that said, this updated configuration still exhibits a Terraform anti-pattern: a particular Terraform configuration should typically either manage a particular object or read that object from the remote API, never both at the same time. From the rest of your question it seems like you need to use the ARN of the AWS Lambda Layer Version object, in which case you can access the equivalent attribute from the managed resource type directly, rather than asking Terraform to read back the same object it's already managing:
resource "aws_lambda_function" "example" {
for_each = aws_lambda_layer_version.abc
layers = [each.value.arn]
}
If your motivation for this was to spread these declarations between modules, the better way to do that would be to pass the data directly between the modules, rather than using a data resource as an indirection. In your module that declared aws_lambda_layer_version.abc
you can write an output value like this:
output "lambda_layer_versions" {
value = tomap({
for k, lv in aws_lambda_layer_version.abc : k => {
id = lv.id
arn = lv.arn
}
})
}
This will construct a map of objects which has the same keys as your for_each
instance keys, where each object has id
and arn
attributes.
Your root module can then access the ARNs from this object:
module "layers" {
source = "./module/lambda-layers"
# ...
}
resource "aws_lambda_function" "test-lambda-layers" {
for_each = module.layers.lambda_layer_versions
layers = [each.value.arn]
}