Okay! I think I understand this now. Thanks for working through this with me.
From your earlier examples it seems like your lambda functions are defined by local.restapi.options.restapi.lambdas
. For the sake of focusing only on the task at hand here I’m going to shorten that just to local.lambdas
here but still keep your shown structure where each element of lambdas
has an attribute function
giving the function name and an attribute signing
indicating whether it should have a signing object.
So for my simplified example, we’ll say there’s a data structure like this:
locals {
lambdas = [
{
function = "auth"
signing = true
},
{
function = "get"
signing = false
},
]
}
This data structure seems to meet the first requirement for a for_each
expression: it has one element per lambda function instance we want to declare, and each one has a unique key in the form of the function
attribute value. Threfore we should be able to use this in the for_each
of the lambda function with just one more projection to make it be a map instead of a list, as for_each
requires:
resource "aws_lambda_function" "example" {
for_each = { for l in local.lambdas : l.function => l }
name = each.value.function
# ...
}
Your other requirement was to declare one aws_lambda_code_signing_config
per function, but only if its corresponding definition has signing
set. You can achieve that by copying the for
expression from the previous resource and adding an if
clause to it:
resource "aws_lambda_code_signing_config" "example" {
for_each = {
for l in local.lambdas : l.function => l
if l.signing
}
# ...
}
Writing for l in local.lambdas
means that inside the body of the for
expression there is a temporary symbol l
that refers to each of the element values of local.lambdas
in turn. In the original example we used that to access l.function
to get the function name, and in this second resource I’ve also added if l.signing
, which accesses the signing
attribute of the current object. The result then will be a filtered version of the collection which keeps only the elements where l.signing
is true.
In a sense we could say that l
inside this expression serves a similar function as each.value
in the rest of the resource configuration. That follows here because the for
expression projects to l.function => l
and so the values of the resulting map exactly match the values of the input list. But we can’t use each.value
directly inside the for
expression, because as I was noting previously it’s this expression that decides what values each.value
would take, and so we don’t yet know what value that should return.
Likewise it wouldn’t be valid to use l
in the expression that comes directly after in
, because that expression is deciding which values l
will take. We have to identify a specific single collection here, which the for
expression will then take values from.
I hope that makes sense! I tried to cut down the example here so we could focus only on the for
expressions and the for_each
arguments and not on all of the other seeminly-unrelated parts generating the big local.restapi
data structure, although if you have success with my examples here but aren’t sure how to adapt them to work with your existing configuration then I’d be happy to help with that if you can again explain what the goal of each part is, so that I can then suggest a solution that will meet the goal.