From a99e727b5e088a0a46450570897a9336ea8cc9f2 Mon Sep 17 00:00:00 2001 From: Nate McCurdy Date: Tue, 10 Oct 2023 11:12:18 -0700 Subject: [PATCH] fix: Allow for custom_iam_policy_arns that don't exist yet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PROBLEM: Prior to this, specifying `custom_iam_policy_arns` for IAM Policies that do not exist yet and would be created in the same Terraform run that creates the Lambda Execution Role would cause the following error: ``` │ Error: Invalid for_each argument │ │ on .terraform/modules/foo.test_lambda/iam-role.tf line 81, in resource "aws_iam_role_policy_attachment" "custom": │ 81: for_each = local.enabled && length(var.custom_iam_policy_arns) > 0 ? var.custom_iam_policy_arns : toset([]) │ ├──────────────── │ │ local.enabled is true │ │ var.custom_iam_policy_arns is set of string with 3 elements │ │ The "for_each" set includes values derived from resource attributes that cannot be determined until apply, and so Terraform cannot determine the full set of keys that will identify the instances of this resource. │ │ When working with unknown values in for_each, it's better to use a map value where the keys are defined statically in your configuration and where only the values contain apply-time results. │ │ Alternatively, you could use the -target planning option to first apply only the resources that the for_each value depends on, and then apply a second time to fully converge. ``` This is due to the ARN's of those policies not being known and the usage of sets in `for_each` for the `aws_iam_role_policy_attachment` resource. As the set's values are unknown at apply time, Terraform can't create a dependency graph. SOLUTION: * Don't use `toset()` for the `for_each` in the `aws_iam_role_policy_attachment` resource. * Build a map of ARNs to attach to the Lambda execution role. Use this map as the value of `for_each`. OUTCOME: * Terraform doesn't error when using `aws_iam_role_policy_attachment` for policies that don't exist yet but will exist after the apply. --- iam-role.tf | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/iam-role.tf b/iam-role.tf index 1fd1d84..397ab7d 100644 --- a/iam-role.tf +++ b/iam-role.tf @@ -1,3 +1,7 @@ +locals { + custom_iam_policy_arns_map = length(var.custom_iam_policy_arns) > 0 ? { for i, arn in var.custom_iam_policy_arns : i => arn } : {} +} + resource "aws_iam_role" "this" { count = local.enabled ? 1 : 0 @@ -82,8 +86,8 @@ resource "aws_iam_role_policy_attachment" "ssm" { } resource "aws_iam_role_policy_attachment" "custom" { - for_each = local.enabled && length(var.custom_iam_policy_arns) > 0 ? var.custom_iam_policy_arns : toset([]) + for_each = local.enabled ? local.custom_iam_policy_arns_map : {} role = aws_iam_role.this[0].name - policy_arn = each.key + policy_arn = each.value }