Search code examples
lambdaterraformarchive-file

Is it possible to upload multiple directories storing lambda function to AWS lambda repeatedly by Loop in Terraform?


I have 3 to 4 folders containing lambda function and related files under the same directory: functions. Those folders are archived and uploaded to AWS lambda one by one with the use of Code-Block below.

### Set each Lambda function's name and its path
locals {
  # Lambda Functions
  lambda_id-1            = "L1"
  lambda_source_dir-1    = "./functions/L1/"

  lambda_id-2            = "L2"
  lambda_source_dir-2    = "./functions/L2/"

  lambda_id-3            = "L3"
  lambda_source_dir-3    = "./functions/L3/"
}

### Code-Block to Zip & Upload lambda function
#########################################################################
data "archive_file" "file-preparation-1" {
  type        = "zip"
  source_dir  = local.lambda_source_dir-1
  output_path = "${local.lambda_source_dir-1}.zip"

  # Ref. https://github.com/hashicorp/terraform-provider-archive/issues/39
  depends_on = [
    null_resource.dummy_trigger
  ]
}

resource "aws_lambda_function" "upload-lambda-1" {
  function_name = local.lambda_id-1
  filename      = data.archive_file.file-preparation-1.output_path

  role          = aws_iam_role.lambda_upload_role.arn
  handler       = "index.handler"
  runtime       = "nodejs12.x"

  tags        = var.extra_tags,
  )

  source_code_hash = data.archive_file.file-preparation-1.output_base64sha256
  depends_on = [
    data.archive_file.file-preparation-1
  ]
}
#########################################################################
# This code-block is repeated as many times as the number of lambdas
...

With the above method, every time we need to upload new lambda function, we have to add more code-blocks for it at the bottom in addition to inserting the name and path of new lambda function into locals.

As we plan to increase the number of Lambda functions, I would like to change the Code-Block to be repeatedly reusable for all lambda functions by using loop, so that I won't need to add Code-Block anymore. Please help to know how to do that, thank you.


Solution

  • At the very least, you can substantially reduce the amount of repetition that you need by using for_each functionality.

    For your case, the result would look something like

    ### Set each Lambda function's name and its path
    locals {
      # Lambda Functions
      functions = {
        "L1": "./functions/L1",
        "L2": "./functions/L2",
        "L3": "./functions/L3",
      }
    }
    
    data "archive_file" "lambda_source" {
      for_each = local.functions
    
      type        = "zip"
      source_dir  = each.value
      output_path = "${each.value}.zip"
    
      # Ref. https://github.com/hashicorp/terraform-provider-archive/issues/39
      depends_on = [
        null_resource.dummy_trigger
      ]
    }
    
    resource "aws_lambda_function" "function" {
      for_each = local.functions
    
      function_name = each.key
      filename      = data.archive_file.lambda_source[each.key].output_path
    
      role          = aws_iam_role.lambda_upload_role.arn
      handler       = "index.handler"
      runtime       = "nodejs12.x"
    
      tags        = var.extra_tags
    
      source_code_hash = data.archive_file.lambda_source[each.key].output_base64sha256
    }
    

    Now to add a new function you only need to add it to the functions map at the top; the other two blocks don't need to be repeated.

    I haven't looked at whether Terraform has functionality to build a map or array from a filesystem, so can't say whether this could be reduced further to not even need to list each function. I would personally want to see the list explicitly in the configuration anyway, but you can search further for that functionality if you want to.