July 14, 2015

Leveraging AWS API Gateway and Lambda to build a Slack bot

Leveraging AWS API Gateway & Lambda to Build a Slack Bot | Mixmax
Slack Message

The engineering team at Mixmax loves Slack integrations. Slack’s webhook API makes it super easy to integrate external data right into the heart of our internal communications. With just a few clicks we can configure integrations like GitHub pull requests or PagerDuty alerts.

One of our most wished for integrations was for our PaaS provider (Modulus.io) to send project state changes into Slack. Modulus has webhooks for each project upon state change, but the webhook needs some simple manipulation to get it into a working Slack format. It’s not a lot of code to do this manipulation, but setting up yet another project seemed like over kill. We could have added a single HTTP endpoint to an existing service to handle this simple webhook redirection, but that’s against our philosophy of microservices.

Once Amazon released API Gateway we knew instantly how we were going to build our Modulus-to-Slack bot.

Last Friday Amazon introduced API Gateway; an AWS service that allows you to build REST HTTP APIs that dispatch requests to other AWS services like EC2 or Lambda. This service is the key to building a quick Modulus-to-Slack webhook API.

Using AWS Lambda we can run some server-side JavaScript code in a hosted environment, without having to worry about server configurations or frameworks—just upload your JavaScript function and AWS Lambda will run it for you. By creating an HTTP endpoint in API Gateway that integrates with Lambda, we can create a simple microservice that accepts our Modulus webhook, transforms it into Slack format, then sends it to Slack’s webhook API.

First let’s look at the Lambda function. We need to transform the Modulus webhook into Slack’s incoming webhook format. Here is a simple transformation function:

var request = require('request');
var util = require('util');

var slackWebhookUrl = '<YOUR_SLACK_WEBHOOK_API_URL>';

exports.handler = function(event, context) {
  var data = convertModulusWebhook(event);
  var options = {
    method: 'post',
    body: data,
    json: true,
    url: slackWebhookUrl
  };
  request(options, context.done);
};

/* convert a Modulus webhook into a slack webhook */
var convertModulusWebhook = function(webhook) {
  var data = webhook;
  var text = util.format('%s - %s', data.type, data.project.name);
  var resp = {};
  resp.attachments = [];
  var info = {
      'fallback': text,
      'pretext': text,
      'color': getStatusColor(data.type),
      'fields': []
    };
  info.fields.push(buildCrashAttachment(data));
  resp.attachments.push(info);
  return resp;
};

var buildCrashAttachment = function(data) {
  if (data.type === 'crash' && data.servo) {
    return {
      'title': 'Modulus Alert',
      'text': data.servo.log,
      'short': false
    };
  } else {
    return {
      'title': 'Modulus Alert',
      'text': data.project.name,
      'short': false
    };
  }
};

/* returns a Slack color depending on the modulus event type. Crash should be red, deploy should be * green, and everything else will be orange. */
var getStatusColor = function(eventType) {
  if (eventType === 'crash') {
    return 'danger';
  } else if (eventType === 'deploy') {
    return 'good';
  } else {
    return 'warning';
  }
};

I’m not going to do a step-by-step of how to set up AWS Lambda (because ain’t no body got time for that), but it’s fairly straightforward to setup, relative to other AWS services.

Setting up an HTTP endpoint with API Gateway is a little confusing, but here is what your final HTTP endpoint should look like.

 

Setup 1

As you can see from the screenshot, I’ve created a resource under the root URL with the path /k12aorxwgz. This is the URL that Modulus’ webhook will POST to. This resource has a POST method configured to run the Lambda function that I created above. Once you have your API configured, you need to create a deployment stage in order to expose your API to the public. Once you have configured a stage for your API Gateway, you can get the endpoint URL and paste it into your Modulus project’s webhook notifications URL.

Setup 2
Modulus Setup

Once you have everything wired up you should get Slack messages like this:

Slack Message

API Gateway isn’t perfect. Harim Software Blog has a more in-depth post about some of the configuration annoyances and overall product shortcomings. It’s a great read and I recommend it if you are interested in learning more about using AWS API Gateway in a more full-fledged manner. For building simple one-off APIs, API Gateway and Lambda are a great alternative to spinning up another Modulus (or Heroku) project.

If you enjoyed reading this post consider Adding Mixmax to your Gmail and writing us with your opinions and comments. We’d love to hear from you. Reach out to us at careers@mixmax.com and follow us @Mixmax.

You deserve a spike in replies, meetings booked, and deals won.

Try Mixmax free