Mike
Mike

Reputation: 11

Terraform loop in resource to merge map

I'm trying to dynamically set the contents of a dictionary within a resource. In my case I want to set per Lambda specific environment variables. I really don't want to modify the local.lambda structure in any way, but I can't quite work out the syntax to iterate over the local.lambda dictionary, lookup the extra vars and then their values dynamically. Any ideas on how I can achieve this?

Here's my locals data

locals {
  lambdas = {
    func1 = "myfunc-${local.env}"
    func2 = "myfunc-${local.env}"
    func3 = "myfunc-${local.env}"
  }


  envvars = {
    myenv1 = "apple"
    myenv2 = "pear"
    myenv3 = "orange"
  }

  extra_envvars = {
    myenv4 = "lettuce"
    myenv5 = "carrot"
    myenv6 = "turnip"
  }

  assign_extra_vars = {
    func1 = [ myenv4, myenv5 ]
    func3 = [ myenv6 ]
  }
}

Here's my Terraform resource with a little block of pseudo code which hopefully explain what I'm trying to achieve better than my broken Terraform.

resource "aws_lambda_function" "task" {
  for_each      = local.lambdas

  environment" {
    // Pseudo code
    my_extra = map {}
    for env_var in local.assign_extra_vars[each.key] : {
      my_extra[env_var] = lookup(local.extra_envvars, env_var, "")
    }
    // end pseudo code

    variables = merge(envvars, my_extra)
 
  }
}

Thanks in advance for any reply.

Upvotes: 0

Views: 2348

Answers (1)

yvesonline
yvesonline

Reputation: 4837

With a tiny bit of restructuring of your locals this can be achieved:

locals {
  env = "dev"

  lambdas = {
    func1 = "myfunc1-${local.env}"
    func2 = "myfunc2-${local.env}"
    func3 = "myfunc3-${local.env}"
  }

  envvars = {
    myenv1 = "apple"
    myenv2 = "pear"
    myenv3 = "orange"
  }

  extra_envvars = {
    func1 = {
      myenv4 = "lettuce"
      myenv5 = "carrot"
    }
    func3 = {
      myenv6 = "turnip"
    }
  }
}

So extra_envvars is now a lookup map by function.

Now your Lambda function becomes this:

resource "aws_lambda_function" "task" {
  for_each = local.lambdas

  function_name = each.value
  role          = aws_iam_role.iam_for_lambda.arn
  handler       = "test.test"
  runtime       = "nodejs12.x"

  environment {
    variables = merge(local.envvars, lookup(local.extra_envvars, each.key, {}))
  }
}

I've filled handler and runtime with dummy content, and for the sake of completeness this is how aws_iam_role.iam_for_lambda looks like:

resource "aws_iam_role" "iam_for_lambda" {
  name = "iam_for_lambda"

  assume_role_policy = <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Effect": "Allow",
      "Sid": ""
    }
  ]
}
EOF
}

Upvotes: 0

Related Questions