mellifluous
mellifluous

Reputation: 2975

How do I pass resource output (EC2 Instance ID) as an environment variable to a Lambda function in Terraform?

I have four files ec2.tf, lambda.tf, variables.tf and outputs.tf. An EC2 instance gets created in ec2.tf, I want the instance id to be passed as an environment variable to Lambda creation resource. I want to pass the instance id through variables.tf.

# variables.tf

variable "runec2_lambda_env" {
  type = map(string)
  default = {
 # I want to pass the output as environment variable here 
    instanceid = "" 
    email      = "[email protected]"
  }
}

# master/lambda.tf

resource "aws_lambda_function" "runec2" {
  filename         = "runec2.zip"
  function_name    = "runec2"
  role             = aws_iam_role.runec2_exec_role.arn
  handler          = "runec2.lambda_handler"
  source_code_hash = filebase64sha256("runec2.zip")
  runtime          = "python3.7"

  environment {
    variables = var.runec2_lambda_env
  }
}


# master/outputs.tf

output "server_id" {
  value = "${join(", ", aws_instance.automation_server.*.id)}"
}

# outputs.tf

 output "public_instance_ids" {
  value = "${module.master.server_id}"
}

# master/ec2.tf

resource "aws_instance" "automation_server" {
  instance_type        = var.instance_type
  ami                  = var.image_id
  iam_instance_profile = aws_iam_instance_profile.ec2_profile.name

  tags = {
    Name = "Automation Server"
  }
  user_data = data.template_file.user-init.rendered
}

Upvotes: 1

Views: 980

Answers (1)

ydaetskcoR
ydaetskcoR

Reputation: 56877

Variables are things that you want the ability to set or override with tfvars files or, if it's a module, with module parameters. The other important part is that they don't support interpolation.

If you want to use interpolation then you need to use locals. You can also use locals to provide the equivalent of constants that you can refer to multiple times but cannot be overridden like variables.

So here you probably want to rework things so that your email variable is configurable but you automatically interpolate the EC2 instance ID into the environment variables of the Lambda function.

The simplest option would look like this:

variable "email" {
  default = "[email protected]"
}

resource "aws_lambda_function" "runec2" {
  filename         = "runec2.zip"
  function_name    = "runec2"
  role             = aws_iam_role.runec2_exec_role.arn
  handler          = "runec2.lambda_handler"
  source_code_hash = filebase64sha256("runec2.zip")
  runtime          = "python3.7"

  environment {
    variables = {
      email      = var.email
      instanceid = aws_instance.automation_server.arn
    }
  }
}

If you really wanted to define the environment variables as a block then you would use locals like this:

variable "email" {
  default = "[email protected]"
}

locals {
  runec2_lambda_env = {
    email      = var.email
    instanceid = aws_instance.automation_server.arn
  }
}

resource "aws_lambda_function" "runec2" {
  filename         = "runec2.zip"
  function_name    = "runec2"
  role             = aws_iam_role.runec2_exec_role.arn
  handler          = "runec2.lambda_handler"
  source_code_hash = filebase64sha256("runec2.zip")
  runtime          = "python3.7"

  environment {
    variables = local.runec2_lambda_env
  }
}

Upvotes: 3

Related Questions