Building Python Serverless Slack Apps on OpenFaas

If you are not familiar with OpenFaas, it’s definitely time that you should have a look at it, plus, they are doing some pretty awesome work!

From OpenFaas’s Documentation:

OpenFaaS (Functions as a Service) is a framework for building serverless functions with Docker and Kubernetes which has first class support for metrics. Any process can be packaged as a function enabling you to consume a range of web events without repetitive boiler-plate coding.

Make sure to give them a visit at openfaas.com and while you are there, in the world of serverless, have a look at how Alex outlines architecture and patterns he applies in a real-world example, absolutely great read!

What are we doing today?

Today we will build a slack app using python which we will deploy as a function on OpenFaas!

Our slash command will make a request to our slack-request function, which will respond with a JSON string, which will then be parsed in a slack attachment message, then based on your button decision, it will then invoke our slack-interaction function, which will then respond with another message that will allow you to follow the embedded link.

The slack messages are really basic, but you can create an awesome workflow using slack apps. And the best of all, it's running on OpenFaas!

Deploying OpenFaas

Docker Swarm and Kubernetes are supported, but since I am using Docker Swarm at the moment of writing, this tutorial will show how to deploy OpenFaas to your cluster. Have a look at OpenFaas Documentation for more detailed information.

Installing OpenFaas CLI for Mac:

$ brew install faas-cli

Deploy the OpenFaas Stack:

$ git clone https://github.com/openfaas/faas $ cd faas $ ./deploy_stack.sh

Credentials: The default configuration will create credentials for you and returns instructions on how to authorize faas-cli, for demonstration it will look more or less like the following:

$ echo -n <some_hash_secret> | faas-cli login --username=admin --password-stdin

The UI will be available at: http://127.0.0.1:8080. For this demonstration, we will only use the cli.

Create the Functions

I will create 2 python functions:

  • The slack-request function, which will be associated to the slash command
  • The slack-interactive function, which will be used for interactivity

Create a home directory for your functions and create 2 functions:

$ mkdir -p ~/functions && cd ~/functions $ faas-cli new --lang python slack-request $ faas-cli new --lang python slack-interactive

Read the documentation if you’d like to learn more.

Configure the first function:

$ vim slack-request/handler.py

And our function code:

import json

def handle(req):
data = {
"text": "Serverless Message",
"attachments": [{
"title": "The Awesome world of Serverless introduces: OpenFaas!",
"fields": [{
"title": "Amazing Level",
"value": "10",
"short": True
},
{
"title": "Github Stars",
"value": "15k +",
"short": True
}],
"author_name": "OpenFaas",
"author_icon": "",
"image_url": "https://blog.alexellis.io/content/images/2017/08/small.png"
},
{
"title": "About OpenFaas",
"text": "OpenFaaS is a framework for packaging code, binaries or containers as Serverless functions on any platform."
},
{
"fallback": "Would you recommend OpenFaas to your friends?",
"title": "Would you recommend OpenFaas to your friends?",
"callback_id": "response123",
"color": "#3AA3E3",
"attachment_type": "default",
"actions": [
{
"name": "recommend",
"text": "Ofcourse!",
"type": "button",
"value": "recommend"
},
{
"name": "definitely",
"text": "Most Definitely!",
"type": "button",
"value": "definitely"
}
]
}]
}
return json.dumps(data)

Since our response needs to be parsed as json, we need to set the content type for our environment in our yaml configuration. Read more on it here. Edit the slack-request.yml :

provider:
name: faas
gateway: http://<your.gw.address>:8080
functions:
slack-request:
lang: python
handler: ./slack-request
image: <your-repo>/slack-request:latest
environment:
content_type: application/json

Now we need to build our image, push it to our repository like dockerhub, then deploy to openfaas:

$ faas-cli build -f ./slack-request.yml 
$ faas-cli push -f ./slack-request.yml
$ faas-cli deploy -f ./slack-request.yml
Deploying: slack-request.
Deployed. 202 Accepted.
URL: http://your.gw.address:8080/function/slack-interactive

Configure the slack-interactive function:

$ vim slack-interactive/handler.py

Note that whenever you interact with the first message, a post request will be made against the interactivity request URL, you will notice that I decoded the payload (but not doing anything with it), where you will find the callback_id, request_url etc.

But for simplicity, I am just using a static JSON message to respond. Our function code:

import json
import urllib
def handle(req):
urlstring = urllib.unquote(req).decode('utf8').strip('payload=')
response = json.loads(urlstring)
data = {
"attachments": [
{
"replace_original": True,
"response_type": "ephemeral",
"fallback": "Required plain-text summary of the attachment.",
"color": "#36a64f",
"pretext": "Ahh yeah! Great choice, OpenFaas is absolutely brilliant!",
"author_name": "",
"author_link": "https://github.com/openfaas/faas",
"author_icon": "http://flickr.com/icons/bobby.jpg",
"title": "OpenFaas",
"title_link": "https://github.com/openfaas/faas",
"text": "Head over to OpenFaas",
"image_url": "https://avatars2.githubusercontent.com/u/27013154?s=400&v=4",
"thumb_url": "https://github.com/openfaas/faas",
"footer": "Slack Apps built on OpenFaas",
"footer_icon": "https://a.slack-edge.com/45901/marketing/img/_rebrand/meta/slack_hash_256.png",
"ts": 123456789
}
]
}
return json.dumps(data)

We also need to set the content type to JSON:

provider:
name: faas
gateway: http://<your.gw.address>:8080
functions:
slack-interactive:
lang: python
handler: ./slack-interactive
image: <repo>/slack-interactive:latest
environment:
content_type: application/json

Build, deploy and ship:

$ faas-cli build -f ./slack-interactive.yml 
$ faas-cli push -f ./slack-interactive.yml
$ faas-cli deploy -f ./slack-interactive.yml
Deploying: slack-interactive.
Deployed. 202 Accepted.
URL: http://<your.gw.address>:8080/function/slack-interactive

When your functions are deployed, go ahead and create the slack app.

Create the Slack App

Once you are set, you should be able to see the slash command integration in your slack workspace, head over to slacks documentation if you run into any trouble.

Test your Slack App

Now that everything is good to go, its time to test your slack app running on OpenFaas!

Head over to slack and run your command /<your-slack-slash-command>. You should see this output:

When you select one of the buttons, you will get a new message:

This is a very basic example of slack apps, but slack apps are really powerful. You can for example create a slack app that deploys ephemeral environments on swarm, or create change management approval workflows etc.

I hope this was informative, I am really enjoying OpenFaas at the moment and if your have not tested it, I encourage you to try it out, its really, really amazing!

Thanks for reading, please have a look at my blog https://blog.ruanbekker.com/ for more posts

Originally published at blog.ruanbekker.com on February 21, 2019.

--

--

--

DevOps Engineer and Open Source Enthusiast

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Working effectively as a small team

Apache Camel 3 — camel-core vs camel-core-engine (smaller core)

AWS lambda now supports partial batch failures. But is it the best approach?

Did Google just got hacked?!

Video Streaming on Web: Learning the Jargon Part 1

Sep 22: Inside Cardstack This Week

5+ Years experienced Spring boot and microservices Interview questions

How to Evaluate and Pitch New Software to Your Team

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Ruan Bekker

Ruan Bekker

DevOps Engineer and Open Source Enthusiast

More from Medium

Deploying a Containerized Web Scraper with a CI/CD pipeline to AWS using Terraform, Boto3, and…

A Step-By-Step Guide to Predictive Analytics on AWS — Generating Sensor Data with a Raspberry Pi…

Terraform, AWS & Google Colab: Getting Started

Migrating to AWS Step Functions