Thursday, June 2, 2016

IBM OpenWhisk

I recently attended an IBM developerWorks Open Tech Talk on a new technology called IBM OpenWhisk.  At the time of this blog post, IBM OpenWhisk is experimental, and while trying it for the first time I ran into some issues you'd expect with any new technology. I'll address those issues in this post.

This technology is a great new open source cloud-based platform for letting developers easily build apps that are triggered by an event, and then automatically kick off a set of actions to respond. It fits perfectly in the trend of micro-service architectures what are emerging as the preferred way of building scalable cloud-based software using small, loosely coupled services distributed throughout the internet.

If you are familiar with IFTTT (https://ifttt.com/) which stands for "If This Then That", then you will be have an easy time understanding OpenWhisk. Basically, it's a simple way of using cloud services to connect the apps you use in a sequence to produce some desired result.

For example, I personally use IFTTT to connect Dropbox events (e.g. a picture is uploaded from my mobile phone) to Flickr actions (e.g. upload picture to Flickr). Once set up, this sequence of events happens automatically without my intervention.

So back to OpenWhisk.  Events trigger an action (or sequence of actions) to produce a result.  In OpenWhisk lingo, there are several main concepts:

  • Trigger: A class of events that can happen and are fired (activated) by using a dictionary of key-value pairs (the event).
  • Action: An event handler (or composition of event handlers) - stateless code that runs in response to an an event that uses a dictionary of key-value pairs for input, as well as for output where the key is a string, and the value is JSON.
  • Rule: An association between a trigger and an action.
  • Feed: A piece of code that configures an external event source to fire trigger events.
  • Package: A bundle of feeds and actions.

A source emits events (e.g. CRUD operations) as triggers, and a rule determines the association between that trigger and an action the developer provides that encapsulates some code to be executed.

Currently, OpenWhisk supports Actions that developers code in 2 languages, either NodeJS or Swift, and also has the ability to support other languages or native code through an Action that wrappers a Docker container.

There is a limited set of triggers today, but seeing as this is open source and growing, I'm sure that will grow quickly. As of today, the available triggers are Cloudant and GitHub, as well as scheduled actions (basically timed triggers). You can also directly invoke an action by using the OpenWhisk API, CLI or iOS SDK.

My point of this blog post was not to describe OpenWhisk in detail to you, but instead show you how to use OpenWhisk through an example and provide feedback as an early adopter. If you want to find out more, there is a lot of documentation on OpenWhisk at either IBM developerWorks (http://developer.ibm.com) or IBM Bluemix (http://bluemix.net) as soon as you are approved for your access to OpenWhisk Beta.

So for this post, I decided it would be fun to try and connect GitHub as a trigger (for notifications) to Slack as an action to post messages so that when a notification occurs on GitHub, it is posted as a message to a specific Slack channel.

Like I mentioned, at the time of writing this post, IBM OpenWhisk is still experimental, and so you need to register and sign up for early access and be approved first. You can do that by going to IBM Bluemix, creating an account if you have not already, and then going to the OpenWhisk page and requesting access: https://new-console.ng.bluemix.net/openwhisk/

In my case, I'm running on the Mac OS X operating system, so my experience will come from that perspective.  The first thing to do when getting started is to install the CLI (Command Line Interface). This is pretty simple, and they provide instructions, but it requires pip, or the package management system for installing and managing software written in Python. In my case, I did not have it installed on my machine already. But there is an easy fix to that, simply run the following command and use your password when prompted.

sudo easy_install pip

To get started with my experiment, I first needed to configure the provided GitHub package as a service to fire a trigger when there is activity in one of my Git repositories.  In order to do that, you need your GitHub username, repository and a personal access token from GitHub. In order to get a personal access token for this application, simply generate one from this link from your GitHub profile settings: https://github.com/settings/tokens


Select "repro" and "notifications" as shown above to get notifications for when source control changes (commits) happen.

Now create a package binding for GitHub with the following CLI command:

$ wsk package bind /whisk.system/github myGit --param username <username> --param repository <git_repository> --param accessToken <token_in_previous_step>

You should see the following result:

ok: created binding myGit

Now you need to create a trigger which will fire on a GitHub event and using your feed. You can choose from any of the Github webhooks (an HTTP POST callback) available here: https://developer.github.com/v3/activity/events/types/. For this example, I want to see when anything is pushed to a branch in the repository. So I will execute the following CLI command:

$ wsk trigger create myGitTrigger --feed myGit/webhook --param events push

With the following results:

ok: created trigger feed myGitTrigger

Also note, that it's easy to make mistakes and get erroneous triggers that you don't want.  In that case you can simply execute the following command to get the full list of triggers:

$ wsk trigger list

And then the following command to delete the ones you don't want:

$ wsk trigger delete <trigger_name>

Next, you have to set up Slack for accepting incoming webhooks to integrate with your action.  First, goto Slack and sign into your account.  Then select "Apps & Integrations" from the Profile dropdown menu.


Then type in "incoming" to the search filter.


In the search results, install WebHooks for your domain.


You will be prompted to select a channel.


And then you will be given the Webhooks URL, as well as a bunch of options on how to customize the incoming messages.


To test out this integration, you can use cURL to run a quick test by POSTing the message "Hello World" to your Slack channel: 

$ curl -X POST -H 'Content-type: application/json' --dat'{"text":"Hello World"}' https://hooks.slack.com/services/<your_url_details>

Once you verify you get the message in Slack, then you can take your test one step further by binding the OpenWhisk Slack package with your configuration.

$ wsk package bind /whisk.system/slack mySlack --param url 'https://hooks.slack.com/services/<your_url_details>' --param username '<username>' --param channel '#<channel_name>'

And then directly invoking the action.

$ wsk action invoke mySlack/post --blocking --result --param text 'Message from OpenWhisk'

Again, you should see the message posted to your Slack channel.

Now we want a trigger coming from GitHub to invoke the posting to Slack action. But this can't be a direct call through a rule, because we need to somehow pass through the commit message from GitHub to Slack. This needs to be done in an indirect way, which can be accomplished through a Javascript action. For example, save this simple Javascript to a file called "myGitToSlackAction.js"

function main(params) {

  var commits = param.commits;
  var parameters = {
    text : "The file '" + commits[0].modified + "' modified by '" + commits[0].author.name + "'."
  };

  whisk.invoke({
    name: "/<myNamespace>/mySlack/post",
    parameters: parameters,
    blocking: true,
    next: function(error, activation) {
      whisk.done(undefined, error);
    }
  });

  return whisk.async();
}


Note, that you need to explicitly provide your namespace in the Javascript file. This is currently a defect being addressed by the OpenWhisk team. Just go ahead and replace the <myNamespace> with your actual namespace which can be found using the following command.

$ wsk package list

This Javascript is very simple, but hopefully provides the baseline of how you can indirectly go through actions to call Slack passing your intended message (in this case the commit message created using the commits object). From this simple sample, you can do all sorts of interesting things to the message you post to Slack, like provide a more details of the Git commit, or change aspects of the message on Slack like change the icon or username doing the posting. And in this example, it only posts the first commit commits[0], and you could instead loop through and post them all.

Now you need to create an action from this Javascript file:

$ wsk action create myGitToSlackAction myGitToSlackAction.js

And lastly we need to tie together the trigger with these actions through a rule:

$ wsk rule create --enable myGitSlackRule myGitTrigger myGitToSlackAction

Now the pipeline of events should be complete. When you commit a change to Git, it will trigger an event as was defined by your myGitTrigger which in turn invokes the myGitToSlackAction action, and as part of that action, it calls from Javascript the mySlack package binding passing the commit message you created.

You can test this out pretty simply by making a change to a file and committing it to your Git repository, for example:

$ git add <somefile>
$ git commit -m "Testing the GitHub-to-Slack message event"
$ git push origin master

So far we've done everything related to OpenWhisk on the command line.  But you can also do a lot from the IBM Bluemix web site, including editing your Javascript or creating actions and rules.  It also has a very helpful dashboard which shows you the details regarding anything that happens so you can easily debug any issues you may have. In terms of this particular example, you can go to the Activity Log and expand the "myGitTrigger" entry to see specifically what parameters are passed from the Git commit message to further customize the message posted to Slack.  Here is a partial screen capture of some of those key/value pair parameters:


Hopefully that gets you moving in trying out your own IBM OpenWhisk application pipelines!

No comments:

Post a Comment