Debug Any Lambda Function Locally
Overview
The Stackery CLI allows you to invoke any Lambda function by Amazon Resource Name (ARN), regardless of the framework or toolkit used to deploy them. This includes Lambda functions built using Serverless Framework, AWS CDK, or the AWS Console.
This guide will cover stackery local invoke
and demonstrate how to iterate on your functions locally against cloudside services.
Setup
Project Repository
The following repository is referenced throughout this guide:
- Serverless Framework Function + SQS (
invoke-any
branch)
Installations
You will need to install the following software before continuing this guide:
- The Stackery CLI
- The AWS SAM CLI
- Docker Desktop (Community Edition) (Free Docker account required for download)
- Serverless Framework (not required, but used in the example below)
CLI commands used
Invoking any function locally
To demonstrate the Stackery CLI invoke-by-arn functionality, we deployed a Serverless Framework project: node8-serverless
. It includes a Lambda function configured with the environment variables it'll need to interact with an AWS SQS queue.
Here's the function we defined in serverless.yaml
, its environment variables, and the SQS queue resource:
...
functions:
Function:
handler: index.handler
...
environment:
QUEUE_NAME:
Fn::GetAtt:
- Queue
- QueueName
QUEUE_ARN:
Fn::GetAtt:
- Queue
- Arn
QUEUE_URL:
Ref: Queue
resources:
Resources:
Queue:
Type: AWS::SQS::Queue
Properties:
QueueName:
Fn::Sub: '#{AWS::StackName}-Queue'
Below is the output from running serverless deploy --verbose
(after installing the required plugins):
With our project deployed, we'll need to obtain its ARN to iterate and invoke locally. In the screenshot above, the serverless deploy --verbose
command outputs the ARN, but it can also be found in the AWS console.
Navigate to the deployed Cloudformation stack and select Outputs to locate the ARN.
In a terminal window, inside the node8-serverless
directory, run the following command to invoke the function locally.
$ stackery local invoke --function-arn {ARN} --source-dir ./src
For the --source-dir
argument, we pass ./src
since it's the folder which contains the function code.
├── src
| └── index.js
├── package.json
└── serverless.yaml
We'll be prompted to select the AWS profile the Stackery CLI uses to invoke the function. In this case, it'll be the same AWS profile used to deploy our project.
You can also use the
--aws-profile
flag to specify AWS profile
We haven't added anything to index.js
yet, and we aren't passing any Stackery Event Inputs, so we should see the following:
We'll add some console logs to get a better sense of the output, and also add the --watch
flag to our CLI command to invoke the function after
save changes to our index.js
file.
As we mentioned earlier, the stackery local invoke
command not only invokes the function, but also adopts any cloudside configurations that were deployed. When we configured this function in our serverless.yaml
file, we added three environment variables related to our SQS queue, which can now be referenced locally.
The following code prints out our cloudside environment variables, and uses the sendMessage
SDK call to send a message to our SQS queue:
// Load AWS SDK and create a new SQS object
const AWS = require("aws-sdk");
const sqs = new AWS.SQS();
const queueUrl = process.env.QUEUE_URL; // supplied by Function service-discovery wire
const queueName = process.env.QUEUE_NAME;
const queueArn = process.env.QUEUE_ARN;
exports.handler = async message => {
console.log("Queue Name: ", queueName);
console.log("Queue ARN ", queueArn);
console.log("Queue URL", queueUrl);
// Construct parameters for the sendMessage call
const params = {
MessageBody: 'New Job',
QueueUrl: queueUrl
};
await sqs.sendMessage(params).promise();
return 'Job sent to queue: ' + queueName;
}
After saving index.js
our function is automatically invoked, and we get the following output:
Now that the function is successfully sending messages to our queue, we can run serverless deploy --verbose
once more and deploy our Serverless Framework project with confidence.
Additional arguments
--build
Adding the --build
flag will build the function before invoking it. Common for runtimes that require compiling (C#, Java, etc).
--watch
Adding the --watch
flag is Stackery's version of 'hot reloading' for your function file. If you run the stackery local invoke
command with the --watch
flag attached, your function will continue to be invoked every time you save a change to your function code file.
--use-container
Adding the --use-container
flag runs the sam-build
inside a Lambda-like Docker container. Use this flag to build functions that depend on packages with natively compiled dependencies.
SAM build currently does not support the use of this flag for the .NET runtime
Local invoke options
Event input
See our documentation on running locally with an event input.
Dependencies
If your function requires dependencies or libraries, you can use them just as you would in a traditional local development environment. Before invoking your function locally, add your dependencies to a package.json
or equivalent file, then run npm install
, pip install -r requirements.txt -t .
, etc. in your function directory. When you invoke your function locally, the dependencies will be available to your function.