Use Lambda Layers To Post To Slack

I have tried a few different ways of reporting Lambda errors to Slack, but haven’t found a reusable solution that gave all of the information I desired. I decided to solve that problem by creating my own Lambda layer. This solution doesn’t highlight the use of error logging, but is dynamic enough that you can just pass an error message into the layer.

For this to be useful to you, make sure you are familiar with the following:
1. AWS Lambda
2. Node JS
3. NPM
4. Slack

Create The Slack App

The first thing you will need to do is create a Slack application that will leverage Incoming Webhooks. Visit: https://api.slack.com and click the ‘Start Building’ button.

Slack API Homepage

You will be prompted to enter an App Name and to map the Application to an existing workspace:

Creating A New Slack App

Click ‘Create App’ and on the next screen, select ‘Incoming Webhooks’.

Select Incoming Webhooks

On the next screen, toggle the ‘Activate Incoming Webhooks’ to ‘On’ then scroll down and click ‘Add New Webhook to Workspace’. Once you do that, you will have to map the webhook to a channel and then you will receive a URL for your webhook.

Activating A New Webhook

Great, now we need to create our Lambda Layer that can POST to this webhook. Copy your webhook and paste it somewhere safe, we will need it later.

Create the Lambda Layer

The file structure of your Lambda Layer is going to be the most important part of this process. When you’re done, the file structure should look like this:

slack-lambda-layer
|
|__nodejs
|
|__node_modules
|
|__posttoslack
|
|-index.js
|-package.json

Lets begin in a clean workspace, navigate to your terminal and execute the following:

$ mkdir slack-lambda-layer
$ cd slack-lambda-layer
$ mkdir nodejs
$ cd nodejs
$ mkdir node_modules
$ cd node_modules

The above file structure is very important, if you do not create the nodejs directory, your Lambda will not be able to find the module. Once you are in the node_modules folder you can create a new directory. This directory will be the name of the package you import.

$ mkdir posttoslack
$ cd posttoslack
$ touch index.js
$ npm init

You can just hit enter through the npm init prompts, note the entry point is index.js. Open index.js with a text editor and paste the following:

Typically, I would use Request Promise for making HTTP calls, but knowing AWS provides the https package in the lambda runtime, I wanted to keep it simple. You could easily build on this to include the request-promise package in your Lambda layer if desired.

Double check that your directory structure looks something like this:

slack-lambda-layer
|
|__nodejs
|
|__node_modules
|
|__posttoslack
|
|-index.js
|-package.json

Now you will need to zip the nodejs directory and upload it to AWS. Once zipped, navigate to your Lambda console in AWS and click ‘Layers’ then ‘Create Layer’.

Create A New Lambda Layer

Here you can name the layer whatever you want. The only important fields on this screen are the source code and runtime. If you needed to create a lambda layer for a different runtime, use Amazon’s documentation to see if your file structure would need to change.

Now you should have a new Lambda Layer.

Your New Lambda Layer

The last step is for us to create a Lambda function that will use this layer.

Create The Lambda Function

Let’s navigate back to the Lambda console and create a new function. Remember, the runtime needs to be 8.10 for our layer to work correctly.

Create Your Lambda Function

You now have the ability to add layers to your Lambda. Click on the ‘layers’ button under your function name, and then click on ‘Add a layer’.

Add A Layer To Your Lambda

Pick your newly created layer and click ‘Add’.

Select The Lambda Layer

Make sure to save your Lambda and switch to the code view. You should see there is a layer associated with your lambda now.

Update the source code of the lambda to require the new layer and leverage it. You will need the Slack Webhook URL from earlier to use as parameters for the function.

const pts = require('posttoslack');
exports.handler = async(event, context) => {
return pts.posttoslack("hooks.slack.com", "/services/XXXXXXXXX/YYYYYYYYY/XXXXXXXXXXXXXXXXXXXXXXXX", 'hello from lambda');
};

If all went well, when you test your lambda you should get a new Slack message:

Let me know your thoughts, how to make it better, or any questions you may have!