Topics: 6 min readtime

Tableau Server Webhooks, REST API and Slack: a learning experience

Written by Timothy
Wednesday 14 October, 2020

Introduction

In an effort to learn about a few concepts relevant to Tableau Server and automation, we're going to build the following: a Python script that uses Tableau Server's REST APIwebhooks and a library called HTTPServer, to post to Slack. The resulting application is based on the premise of posting a notification to Slack when a new workbook is published to Tableau Server. The notification message should contain a link to the workbook, as well as its thumbnail. Like this:

Tableau_Server_To_Slack_Message

The project is as good as completed. There are improvements to work on, but the concepts and functionality are all there and available on GitHub. We'll refer to that repository from time to time.

Preparation

There are a few aspects of this project that do require some preparation. The bulk of that is related to the authentication to the two platforms we're working with: Tableau Server and Slack.

For Tableau Server, we'll be using Personal Access Tokens, which are currently the preferred way of authenticating to the Tableau Server REST API, and are easy to set up.

As for Slack, we've set up an app that uses a bot token to authenticate. Slack app authentication is slightly more complicated, so if these concepts are new to you, it's a good idea to read up and then set up the app and grab the token.

Aside from authentication, it's worth checking the usage section of the documentation to set up the Python virtual environment and the further pre-requisites.

Architecture and Flow

Enough about introductions and preparations; on to the actual substance. Our Python script will be the glue between the different components mentioned in the introduction. Remember, a webhook is a mechanism we can use to call a service or function when a specific event occurs on Tableau Server. It works by sending an HTTP request with information about the event at hand, to a certain URL.

Our script will set up and connect the webhook(s) using the REST API, and ensure the webhook can talk back to us. To do all this, we'll use the following Python modules:

  • Tableau Server Client (TSC) is going to communicate with the Tableau Server REST API to set up (and later remove) the webhook. It's also going to fetch metadata and a preview image of the workbook at hand.

  • HTTPServer is going to be the lightweight web server that listens to the events from the webhook. It's going to be wrapped in an ssl socket according to these instructions.

  • python-slackclient: some Slack library we used before. Really easy interface to the Slack API which we'll use to post messages.

These components are spun together as follows:

tableau-server-webhooks-to-slack-Architecture

  • Log in to Tableau Server REST API with PAT (diagram, step 1).

  • Create a webhook with name, event, and target URL as provided (diagram, step 2).

  • Spin up the "listener web server" that listens to said webhook target URL, forever (diagram, HTTPServer component).

    • This HTTP Server has a request handler function to receive and process requests from Tableau Server's webhook (diagram, step 3).

    • It then also takes care of fetching additional metadata for the workbook (diagram, step 4), and ...

    • ... of posting to Slack when we have everything (diagram, step 5).

  • When the script is terminated (with a KeyboardInterrupt), delete the webhook we created previously.

A Few Highlights In The Code

We're not going to cover the full script in this blog post, but a few sections are worth a closer look.

Configuration

#### Parse config file
config = configparser.ConfigParser()
config.read("config.ini")

The above makes use of a convenient module called configparser, which provides easy access to a configuration file's contents. Point to the file, and this will ensure you can readily access the configuration values in a Python list.

Webhook definition

#### Create webhook
webhook_model = TSC.WebhookItem()
webhook_model.name = config["Webhook Configuration"]["webhook_name"]
webhook_model.url = config["Webhook Configuration"]["webhook_url"]
webhook_model.event = config["Webhook Configuration"]["webhook_event_name"]
webhook = tableau_server.webhooks.create(webhook_model)
print("Webhook created: \"" + webhook.name + "\" with id " + webhook._id)

It's not yet thoroughly documented, but the Tableau Server Client already supports actions for managing webhooks on Tableau Server! It's really quite simple to pass the three required parameters we need, and have it set up.

Other Comments About The Code

If you're interested, it's worth skimming through the code to see what it does. The most interesting remaining part may be the definition and setup of the do_POST(self) function as part of the SimpleHTTPRequestHandler class. Basically: what do we do when we receive a message from the Tableau Server webhook! The HTTPServer will just keep listening forever when launched, and will execute this code when "spoken to".

The code is slightly too extensive to include in the blog post, but it comes down to:

  • Parsing that message to find out what we're dealing with. Note that the current code only processes events for workbooks being created, but it could be extended to handle all events.

  • Using TSC (again) to get the URL and thumbnail of the newly published workbook.

  • Posting this information to Slack, using Slack Web Client library.

Conclusion

The timing of this post and the work in it, is rather interestingly timed. Indeed, at their global virtual Tableau Conference, Tableau did just announce they would soon start supporting... Slack notifications from Tableau Server. What a coincidence.

So, was this all in vain? Most certainly not! Here are a few reasons why:

  • This was, first and foremost, an opportunity to learn about the architecture of a solution combining all these components.

  • Gaining this understanding would allow us to build similar solutions with the likes of automation platforms like tray.io, n8n.io, etc.

  • Even though this type of functionality will be built into the product later, this custom approach allows for greater flexibility when it comes to the message posted, its attachments such as the preview, and so on. We could even consider other target platforms such as Microsoft Teams, and we'd have a totally different solution on our hands, that's not yet supported out of the box.

In conclusion, we're very happy with what we've learned from building this educational script. If you're working on similar projects or if you can use some help with a similar initiative, don't hesitate to be inspired by this example, or to reach out. #DataDevs, here to support each other!