Skip to main content
The 2024 Developer Survey results are live! See the results
1030

Local development, testing, and debugging of serverless applications defined in Terraform using AWS SAM CLI

Created
Active
Last edited
Viewed 1k times
3 min read
Part of AWS Collective
6

One question we hear from developers using Terraform and AWS Lambda functions is how to locally test the Lambda function. Here’s a great example — I have a simple terraform file with a Lambda function. I don’t want to deploy this terraform stack to AWS for testing my changes. How do I locally test and debug serverless applications defined in Terraform?

module "publish_book_review" {
  source        = "terraform-aws-modules/lambda/aws"
  version       = "4.6.0"
  create_role   = false 
  timeout       = 30
  source_path   = local.lambda_src_path
  function_name = "publish-book-review"
  handler       = "index.lambda_handler"
  runtime       = "python3.8"
}

If this sounds like something you’ve run into before, let’s look at local testing and Terraform.

The Setup

AWS Serverless Application Model (SAM) is a framework for building serverless applications on AWS. SAM CLI is a powerful tool that allows developers to build, test, and deploy serverless applications on AWS. Recently, SAM CLI added support for Terraform local testing. This feature allows developers to write Terraform code and test it locally before deploying it to AWS. In this article, we will explore how SAM CLI supports Terraform local testing and how it can help you streamline your serverless development process.

Here are some ways to set up the environment to locally test a Lambda defined in Terraform module with SAM CLI.

Option 1: Instrument the Terraform resources to aid SAM CLI local testing and debugging.

You can add the following segment to your Terraform file.

resource "null_resource" "sam_metadata_aws_lambda_function_publish_book_review" {
    triggers = {
        resource_name = "aws_lambda_function.publish_book_review"
        resource_type = "ZIP_LAMBDA_FUNCTION"
        original_source_code = "${local.lambda_src_path}"
        built_output_path = "${local.building_path}/${local.lambda_code_filename}"
    }
}

null_resource: When the AWS SAM CLI build command runs, AWS SAM reviews Terraform code for any null_resource starting with sam_metadata_ and uses the information contained within this resource block to gather the location of the Lambda function source code and .zip package. This information allows the AWS SAM CLI to start the local execution of the Lambda function. This special resource should contain the following attributes:

* resource_name: The Lambda function address as defined in the current module (aws_lambda_function.publish_book_review)
* resource_type: Packaging type of the Lambda function (ZIP_LAMBDA_FUNCTION)
* original_source_code: Location of Lambda function code
* built_output_path: Location of .zip deployment package

Option 2: Lambda Terraform module

A community-supported Terraform module for Lambda (terraform-aws-lambda) has added support for SAM metadata null_resource. When using the latest version of this module, AWS SAM CLI will automatically support local invocation of the Lambda function, without additional resource blocks required.

Local testing

Once the setup is complete, you can do the local test using the following SAM CLI commands.

Run the sam build to reflect the local sam testing environment with changes after each code update.

  1. Local Build: To create a local build of the Lambda function for testing, use the sam build command:
sam build --hook-name terraform --beta-features
  1. Local invoke: The first test is to invoke the Lambda function with a mocked event payload from the API Gateway. These events are in the events directory. Run this command, passing in a mocked event:
sam local invoke aws_lambda_function.publish_book_review -e event_file.json —beta-features
  1. Local invoke from AWS CLI: Another test is to run a local emulation of the Lambda service using “sam local start-lambda” and invoke the function directly using AWS SDK or the AWS CLI. Start the local emulator with the following command:
sam local start-lambda

AWS SAM starts the emulator and exposes a local endpoint for the AWS CLI or a software development kit (SDK) to call. With the start-lambda command still running, run the following command to invoke this function locally with the AWS CLI:

aws lambda invoke --function-name aws_lambda_function.publish_book_review --endpoint-url http://127.0.0.1:3001/ response.json --cli-binary-format raw-in-base64-out --payload file://events/new-review.json

The AWS CLI invokes the local function and returns a status report of the service to the screen. The response from the function itself is in the response.json file. The window shows the following messages:

Debugging the Lambda function

Developers can use AWS SAM with a variety of AWS toolkits and debuggers to test and debug serverless applications locally. For example, developers can perform local step-through debugging of Lambda functions by setting breakpoints, inspecting variables, and running function code one line at a time.

The AWS Toolkit Integrated Development Environment (IDE) plugin provides the ability to perform many common debugging tasks, like setting breakpoints, inspecting variables, and running function code one line at a time. AWS Toolkits make it easier to develop, debug, and deploy serverless applications defined using AWS SAM. They provide an experience for building, testing, debugging, deploying, and invoking Lambda functions integrated into IDE. Refer to this link that lists common IDE/runtime combinations that support step-through debugging of AWS SAM applications.

Visual Studio Code keeps debugging configuration information in a launch.json file in a workspace .vscode folder. Here is a sample launch configuration file to debug Lambda code locally using AWS SAM and Visual Studio Code.

{
    "version": "0.2.0",
    "configurations": [
          {
            "name": "Attach to SAM CLI",
            "type": "python",
            "request": "attach",
            "address": "localhost",
            "port": 9999,
            "localRoot": "${workspaceRoot}/sam-terraform/book-reviews",
            "remoteRoot": "/var/task",
            "protocol": "inspector",
            "stopOnEntry": false
          }
    ]
}

JSON After adding the launch configuration, start a debug session in the Visual Studio Code.

Step 1: Instrument your code with following lines

import ptvsd

ptvsd.enable_attach(address=('0.0.0.0', 9999), redirect_output=True)
ptvsd.wait_for_attach()

Make sure to have the ptvsd python packages installed in your python environment.

Step 2: Run the Lambda function in the debug mode and wait for the Visual Studio Code to attach to this debugging session:

sam local invoke aws_lambda_function.publish_book_review -e event_file.json -d 9999

Step 3: Select the Run and Debug icon in the Activity Bar on the side of VS Code. In the Run and Debug view, select “Attach to SAM CLI” and choose Run. For this example, set a breakpoint at the first line of lambda_handler. This breakpoint allows viewing the input data coming into the Lambda function. Also, it helps in debugging code issues before deploying to the AWS Cloud.

enter image description here

Conclusion:

SAM CLI's support for Terraform for local testing is a powerful feature that allows developers to write and test Terraform code locally before deploying it to AWS. Following the steps outlined in this article, you can quickly start using SAM CLI and Terraform for local testing. A detailed step-by-step instruction along with a sample repo is located here

0