My Little Helper: Slack Bot

As a Site Reliability Engineer (SRE) I spend a significant amount of my time on the Linux console. Furthermore, I spend some time writing software and tooling. But I also spend a lot of time on Slack (substitute with your organizations preferred chat platform) communicating with humans.1

Bridging these domains often requires copying and pasting of information including sometimes reformatting. At one point, I was so annoyed by moving console output from a terminal window to Slack that I decided to find a better way.

My idea was to have a single, statically linked binary that I can scp to a system and that would run without further actions. The job of that binary helper would be to post to Slack on my behalf.

To honor the great inventor (and actress) Hedy Lamarr my little helper was named after her.

Great, we have a problem, a solution, and the name hedybot. But what are actual uses cases in a world (striving for) full automation? Actually, there are still a lot of manual tasks left, including:

  • Tasks that require human oversight to avoid disaster
  • One-time but often long-running tasks

Manual Deployment Notifications

One example of a task that requires human oversight at my workplace is the deployment of Domain Name System (DNS) changes. Since a mistake here can easily cost thousands of dollars and unmeasurable loss of customer trust, we tend to have an experienced engineer deploy the changes. For additional assurance, we always post the deployed changes to Slack for everyone to read. People double check and sometimes ask questions about the changes. That is a wonderful use case for hedybot! Here it is in action, using dns-tools:

$ rrpush --quiet --dry-run=false --delay=0 --no-color 2>&1 \
  | hedybot --channel=FOO2342 --title="Deployment on Production DNS"

In Slack it looks like this.

small

By the way, the color follows some loose internal convention and is hardcoded. It is a potential improvement to make the color configurable via command line flag.

Long-running Jobs

Another great use case for hedybot is a long-running job. Let’s assume there is a server that we need to wipe to comply with regulations. One could easily lose track of such a task once it is started. Daily business and occasional firefighting push less urgent matters aside and soon our brain has forgotten about them. This is where a little helper comes in handy by posting a quick message:

$ dd if=/dev/urandom of=/dev/sdx bs=4096; \
  echo "disk erase finished" | hedybot --title="Example Server"

The resulting message is clear and simple:

small

Thanks to the timely reminder, we can decommission the server right away and save some money here.

Hedybot Source Code

Here is the Golang code that I used. Grab it to craft your own little helper.

package main

import (
  "flag"
  "io/ioutil"
  "log"
  "os"

  "github.com/nlopes/slack"
)

const (
  // fetch API key from your slack workspace
  apiKey = "xxxx-xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxx"
)

func main() {
  channelID := flag.String("channel-id", "C85PT1ULR",
    "ID of the channel to post too")
  title := flag.String("title", "Message",
    "Title for the message to post")
  flag.Parse()

  bytes, err := ioutil.ReadAll(os.Stdin)
  if err != nil {
    log.Fatalf("read stdin: %v", err)
  }
  if len(bytes) < 1 {
    log.Fatalf("stdin is empty")
  }
  report := string(bytes)

  params := slack.PostMessageParameters{
    AsUser: true,
    Attachments: []slack.Attachment{
      {
        Color: "#FFA500",
        Fields: []slack.AttachmentField{
          {
            Title: *title,
            Value: report,
          },
        },
      },
    },
  }
  api := slack.New(apiKey)
  _, _, err = api.PostMessage(*channelID, "", params)
  if err != nil {
    log.Fatalf("post report: %v", err)
  }
}
  1. The tricky part my job is to figure out which activity is worth automating, which activity requires time boxing, and when going deep into the details is advised.