terraform,

How to make local archive_file to be available when deploying Terraform aws_lambda_function

Sep 20, 2021 · 2 mins read · Post a comment
How to make local archive_file to be available when deploying Terraform aws_lambda_function

In today’s blog post, I really need to share with you all a quick tip regarding Terraform’s aws_lambda_function resource and how to make the latest local data archive_file to be present when planning/deploying Terraform infrastructure. So, let’s dive straight into it.

Prerequisites

  • Terraform

Scenario

Step 1. Take a look at the following Terraform code:

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"
    }
  ]
}
EOF
}

resource "local_file" "lambda_function" {
  content = templatefile("${path.module}/lambda/test.py.tpl", {
    region    = var.region
  })
  filename =  "${path.module}/lambda/test.py"

  file_permission      = 0644
  directory_permission = 0755
}

data "archive_file" "lambda_function" {
  type             = "zip"
  source_file      = "${path.module}/lambda/test.py"
  output_file_mode = "0644"
  output_path      = "${path.module}/files/lambda-test.zip"

  depends_on = [
    local_file.lambda_function
  ]
}

module "lambda_function" {
  source = "../modules/lambda"

  function_name = "lambda_function_name"
  role          = aws_iam_role.iam_for_lambda.arn

  filename         = data.archive_file.lambda_function.output_path
  handler          = "test.lambda_handler"
  source_code_hash = filebase64sha256(data.archive_file.lambda_function.output_path)
}

Step 2. Create an execution plan:

terraform plan 

Expected output:

Error: Error in function call
│ 
│   on main.tf line 94, in module "lambda_function":
│  94:   source_code_hash = filebase64sha256(data.archive_file.lambda_function.output_path)
│     ├────────────────
│     │ data.archive_file.lambda_function.output_path is "./files/lambda-test.zip"
│ 
│ Call to function "filebase64sha256" failed: open files/lambda-test.zip: no such file or directory.
╵

As you can see, the terraform plan command failed because it couldn’t find the lambda-test.zip file, since it’s not created yet. This is because the built-in functions are not part of the dependency handling even if we add a depends_on block.
In the example above, the filebase64sha256 function will check if the file is statically present in the configuration, not along the way, during the terraform plan execution.

Solution

Lucky for us, the archive_file data exports a output_base64sha256 attribute, which can be used as a source_code_hash value.

Step 1. Update the source_code_hash parameter line with the following one:

module "lambda_function" {
    ...
    source_code_hash = data.archive_file.lambda_function.output_base64sha256
    ...
}

Step 2. Create and deploy the Terraform execution plan:

terraform plan && terraform apply --auto-approve

Conclusion

Instead of deploying locally created archive files, uploading and pulling packages from a S3 bucket would be a more resilient, redundant and definitely a preferable approach. Or even better, you could always use container images instead of deployment packages.
Feel free to leave a comment below and if you find this tutorial useful, follow our official channel on telegram.