Hero image

Invoking serverless-offline Lambdas


Recently I have been tasked with working on a lambda that is triggered through a Kinesis event. The issue with these is that you generally do not have an exposed API to trigger one. Luckily serverless-offline provides a little trick by exposing lambdas to their own endpoints.

If you run sls offline you will see something similar to the following message.

TXT

So we know it has given us something to help us invoke these, but what are the specifics?

Looking at the AWS SDK you can find the aws invoke lambda command which has a few options we will need to know in order to achieve this.

AWS Lambda Options

Output - We are not interested in the output at the moment so lets throw it away to /dev/null.

URL - In the logs mentioned above, there is a URL provided which gives a clue. Looking at the CLI an option is --endpoint-url allows us to input the URL. So lets set it as --endpoint-url http://localhost:4003.

Function to Call - The next thing the logs provide is a function name that we can use to call the lambda. In this case we are looking at handleKinesisEvent which we pass into --function-name which leaves us with --function-name handleKinesisEvent.

Payload - The last thing we need to do is pass through a valid payload to the lambda, which can be done through the --payload option. This is a bit more complex due to things being base64 encoded. You need to have the kinesis data, as well as the event itself encoded. To do this the easiest way is to split the payload into two parts - one a file of the data, and the other a script that will encode the data.

Lets start with the data file. In my case I just created a JSON file and put it in the root folder I am working in. In this case it is named event.json.

{
  "example": "data"
}

Next I created a shell script in the same location which wraps the data with the required JSON properties, and encodes the data. I have named it genpayload.sh.

#!/bin/bash
printf '{"Records":[ { "kinesis": { "data" : "'
cat ./event.json| base64 | tr -d '\n'
printf '" } } ] }'

Now all we need to do is call this script within the payload and the base64 encode it, leaving us with --payload $( ( bash ~/Desktop/genpayload.sh) | base64 ) - note you may need the -w0 option for base64 to get this working on linux.

Bringing it all together

Bringing all this together we are left with the following command that will run our local kinesis event:

aws lambda invoke /dev/null --endpoint-url http://localhost:4003  --function-name handleKinesisEvent --payload $( ( bash ./genpayload.sh) | base64 )

And that is it! The lambda is running when this command executes.

What Next

As always there are some things we can do to clean this up a little. The base64 command could be wrapped again, or the output could be put somewhere other than /dev/null, but for me this is all I needed to get the job done.



What to read more? Check out more posts below!