amazon-web-servicesaws-lambdaterraformterragrunt

How to deploy AWS Lambda function via Terragrunt without a source package?


I'm trying to deploy an AWS Lambda function using Terragrunt without attaching a zip package. The goal is to create the function with basic configurations and manage it directly through Terragrunt.

I've attempted setting create_package: false but Terragrunt throws an error Could not locate source_path "null". I tried using a dummy package with local_existing_package: "./dummy.zip" and ignore_source_code_hash: true, but the error persists.

Here’s what my configuration looks like:

1st Try:

- function_name: test-function
  create_package: false
  description: "test-function"
  handler: "lambda_handler"

2nd Try:

- function_name: test-function
  create_package: false
  local_existing_package: "./dummy.zip"
  ignore_source_code_hash: true
  description: "test-function"
  handler: "lambda_handler"

Solution

  • I believe this configuration should work:

    - function_name: test-function
      create_package: false
      local_existing_package: "./dummy.zip"
      ignore_source_code_hash: true
      description: "test-function"
      handler: "lambda_handler"
      runtime: "python3.9"
      memory_size: 128
    

    but there's one thing that concerns me, the local_existing_package should be the absolute path not the relative path.

    variable "local_existing_package" {
      description = "The absolute path to an existing zip-file to use"
      type        = string
      default     = null
    }
    

    so try to use local_existing_package = "${abspath("./dummy.zip")}" instead and clear the terragrunt cache before applying again :

    rm -rf .terragrunt-cache
    

    Solution


    The issue was in the lambdas = try({}) block. Initially, only the function_name and options were being passed, while everything else was ignored.

    After encountering the error (source_path "null"), I decided to debug the actual inputs being sent to the Lambda module. To do this, I added the following line:

    debug_input_items = run_cmd("echo", "DEBUG: Items passed to module -> ${jsonencode(local.lambdas)}")
    

    To my surprise, the debug revealed that only the function_name was being passed to the module. This explained why source_path was still null even when I explicitly set it to “something.”

    To fix this, I updated the block to include all the necessary fields like runtime, handler, memory_size, and others. Additionally, because .hcl files don’t support $ for interpolation, I ensured that local_existing_package was handled dynamically by constructing its path based on the Lambda function name. Since you’ll typically use the same name for the ZIP file as the Lambda function, this approach simplifies the setup.

    Here’s the updated block:

    lambdas = try({
      for lambda in local.all_lambdas:
        "${include.root.locals.convention-naming}-${lambda.function_name}" => merge(
          {
            function_name           = "${include.root.locals.convention-naming}-${lambda.function_name}"
            create_package          = lambda.create_package
            local_existing_package  = abspath("${get_terragrunt_dir()}/${lambda.function_name}.zip")
            ignore_source_code_hash = lambda.ignore_source_code_hash
            description             = lambda.description
            handler                 = lambda.handler
            runtime                 = lambda.runtime
            memory_size             = lambda.memory_size
          },
          try(lambda.options, {})  # Include optional configurations
        )
    }, {})
    
    debug_input_items = run_cmd("echo", "DEBUG: Items passed to module -> ${jsonencode(local.lambdas)}")
    

    I tested everything at my end and it's working. enter image description here Do not forget to add a non empty .py file within the zip file. just python file with print('Hello World!') will be enough

    Thank you for uploading out the code and sorry for being a little bit late.