Debug Any Lambda Function Locally · Stackery Documentation

5 min read Original article ↗

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:

Installations

You will need to install the following software before continuing this guide:

CLI commands used

Invoking any function locally

To demonstrate the Stackery CLI invoke-by-arn functionality, we deployed a Serverless Framework project: node-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):

sls deploy screenshot

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.

cfn console

In a terminal window, inside the node-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:

initial function invoke

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.

function invoke logs

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:

function invoke envs

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.