Skip to content

Bug: for_each keys derived from dynamic role values cause runtime error in gcp-permission module #44

@jmorgenstern-b24

Description

@jmorgenstern-b24

Summary

The IAM member resources in the terraform/modules/gcp-permission module build their for_each map keys from a dynamically computed value (the role name). Because these role values are only known at apply time, Terraform cannot determine the for_each keys during planning and fails with an "Invalid for_each argument" error.

Affected files

  • terraform/modules/gcp-permission/folder.tfgoogle_folder_iam_member.folder_level_permissions
  • terraform/modules/gcp-permission/project.tfgoogle_project_iam_member.project_level_permissions

Details

The roles originate from the module output module.pantheon_gcp_roles.necessary_gcp_roles, which is passed into the module via var.pantheon_gcp_roles (see pantheon_one_o/main.tf). This output is a computed value that is not known at plan time.

The for_each key is constructed from this dynamic value:

for_each = local.is_project_level ? { for entry in local.project_roles : "${entry.role}.${entry.projectId}" => entry } : {}

Since entry.role is unknown until apply, the resulting map keys are also unknown, producing:

Error: Invalid for_each argument
The "for_each" map includes keys 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.

Expected behavior

The module should plan and apply successfully regardless of whether the role list is statically defined or computed from another module output.

Proposed fix

Use the static list index of the flattened local.*_roles list as the for_each map key instead of a key derived from the dynamic role value. The indices are known at plan time independently of the (dynamic) element values:

# project.tf
for_each = local.is_project_level ? { for idx, entry in local.project_roles : idx => entry } : {}

The same fix has already been applied to folder.tf:

# folder.tf
for_each = local.is_folder_level ? { for idx, entry in local.folder_roles : idx => entry } : {}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions