Search code examples
amazon-web-servicesterraformterraform-provider-aws

In Terraform how to reference resource created via loop over list of objects


I have a list of objects specified in variables.tf as follows:

variable lambda_attributes {
  description = "List of Lambda Objects"
  type = list(object({
    name        = string
    description = string
    runtime     = string
  }))
  default = [
    {
      name        = "device-update",
      description = "device update function",
      runtime     = "nodejs20.x"
    },
    {
      name        = "location-update ",
      description = "location update function",
      runtime     = "nodejs20.x"
    },
    {
      name        = "ticket-update",
      description = "ticket update Function",
      runtime     = "nodejs20.x"
    }
  ]
}

and I create IAM roles in a loop with this code:

resource "aws_iam_role" "role_for_lambda" {
  for_each = {for i, v in var.lambda_attributes:  i => v}
  name               = "iam_for_lambda_${each.value.name}"
  assume_role_policy = data.aws_iam_policy_document.assume_role.json
}

How do I reference the role when I create a Lambda functions in a loop as shown below?

resource "aws_lambda_function" "my_lambdas" {
  for_each = {for i, v in var.lambda_attributes:  i => v}
  function_name = "${each.value.name}"
  description   = "${each.value.description}"
  role          = ???

Thanks for your assistance.


Solution

  • aws_lambda_function is created with a for_each loop based on a map, so you can access its resources by its key:

    aws_iam_role.role_for_lambda[each.key].some_property
    

    Example (not tested):

    locals {
      # Use same map in both resources
      attributes_map = { 
        for attribute in var.lambda_attributes : 
        attribute.name => attribute 
      }
    }
    
    resource "aws_iam_role" "role_for_lambda" {
      for_each = locals.attributes_map
    
      name               = "iam_for_lambda_${each.value.name}"
      assume_role_policy = data.aws_iam_policy_document.assume_role.json
    }
    
    resource "aws_lambda_function" "my_lambdas" {
      for_each = local.attributes_map
    
      function_name = each.value.name
      description   = each.value.description
      role          = aws_iam_role.role_for_lambda[each.key].arn
    
      # ....
    }
    

    Please note that I've changed the code slightly in order to:

    • Reduce code duplication by reusing same map in both resources
    • Use the name property as the map key, as opposed to using the index as in your example. Using indexes can cause some issues so they should be avoided.