- UPDATED 20th May, 2017: If you are more comfortable with Python, you can this post on Errbot and PowerShell.
- UPDATED 8th July, 2016: Created a installation video for Hubot using PowerShell DSC here.
- UPDATED 1st July, 2016: Created a PowerShell DSC Resource to install Hubot which makes the process much easier. Can be found on GitHub here or found in the PowerShell Gallery here.
ChatOps is a term used to describe bringing development or operations work that is already happening in the background into a common chat room. It involves having everyone in the team in a single chat room, then bringing tools into the room so everyone can automate, collaborate and see how automation is used to solve problems. In doing so, you are unifying the communication about what work gets done and have a history of it happening.
ChatOps can be supplemented with the use of tools or scripts exposed using a chat bot. Users in the chat room can talk to the bot and have it take actions on their behalf, some examples of this may be:
- Checking the status of a Windows Service
- Finding out who is on call via the PagerDuty API
- Querying a server to see how much disk space is available
Bots can also be a great way to expose functionality to low-privledged users such as help desk staff, without having to create web interfaces or forms.
If you want more details on the concept of ChatOps, I recommend watching ChatOps, a Beginners Guide presented by Jason Hand.
A popular toolset for ChatOps is Slack as the chat client, and Hubot as the bot. In this post we will use Slack and Hubot together with a PowerShell module I’ve written called PoshHubot. The module will handle installation and basic administration of Hubot. From there, we will integrate Hubot with PowerShell so we can perform some ChatOps in the Microsoft ecosystem.
- Basic Hubot Concepts
- Requirements
- Create a Slack Integration for Hubot
- Installing Hubot
- Starting Hubot
- Integrating Hubot with PowerShell
- Wrapping Up
Basic Hubot Concepts
There are a few basic Hubot concepts I want to introduce to you before we continue.
Node.js and CoffeeScript
Hubot is built in CoffeeScript, which is a programming language that complies into JavaScript. Hubot is built on Node.js. This means the server running the bot will need to have Node.js and CoffeeScript installed. The PoshHubot module will handle this.
When writing scripts for your bot, you will have to get your hands a little dirty with CoffeeScript. We will be calling PowerShell from inside CoffeeScript, so we only need to know a tiny bit to get by.
Environment Variables
Hubot scripts make heavy use of environment variables to set certain options for the bot.
One example of this is to allow the Hubot to access sites with invalid SSL certificates, you would set an environment variable of NODE_TLS_REJECT_UNAUTHORIZED
.
There are 3 possible ways to do this:
- You can set these environment variables as a system wide setting in an Administrative PowerShell prompt using:
- You can set them in the current PowerShell instance before you start the bot using:
- You can store the environment variable in the
config.json
file that we generate during the Hubot installation, which thePoshHubot
module will load before starting the bot.
Bot Brain
Hubot has a brain, which is simply a place to store persist data. For example, you could write a script to have Hubot store URL’s for certain services, which you could append to via chat commands. You want these URL’s to persist after Hubot reboots, so it needs to save them to its brain.
There are many brain adapters for Hubot, for example MySQL, Redis and Azure Blob Storage. For this blog we install a file brain - which will just store the brain as a .json file on the disk.
Requirements
You will need to a have a few things ready to get a Hubot setup with Slack:
- A Windows Machine with PowerShell 4.0+. For this tutorial I will be using a Windows 2012 R2 Standard machine with GUI. Once you get comfortable with Hubot you may decide to switch to using Server Core, which is a great choose for running Hubot
- Administrative access in your Slack group to create a Hubot integration
Create a Slack Integration for Hubot
To have Hubot communicating with Slack, we need to configure an integration. From Slack:
- Choose Apps & Custom Integrations
- Search for Hubot and choose Install
- Provide a Hubot username - this will be the name of your bot. For this blog the bot will be called bender
- Click Add Hubot Integration
After the integration has been added, you will be provided an API Token, something like xoxb-XXXXX-XXXXXX
. We will need this later so note it down.
Additionally, you can customize your bots icon and add channels at this screen.
Installing Hubot
Install the PoshHubot
module in one of two ways:
- Install it using PowerShell get with
Install-Module -Name PoshHubot
- Manually download the latest PoshHubot release and extract the module your PowerShell Module directory.
Once installed, we are going to create a configuration file that PoshHubot
will use.
Next, we need to install all the required components for Hubot, which will be handled by the Install-Hubot
command.
This will install the following:
- Chocolatey
- Node.js
- Git
- CoffeeScript
- Hubot Generator
- Forever which will run Hubot as a background process
Removing Hubot Scripts
Hubot comes installed with some default scripts which are not required when running on Windows. We can use the Remove-HubotScript
command to remove them.
Installing Hubot Scripts
There are many third party scripts available for Hubot to extend its functionality. You can search for them on the Node.js package manager site or on GitHub. We will use the Install-HubotScript
function to install some useful scripts.
Starting Hubot
Before we can start our bot and connect it to Slack, we have to configure the environment variables required by the scripts we are using. A good way to find out what environment variables a script is using is to look it up on GitHub. For example,
the jubot-brain-file script requires FILE_BRAIN_PATH
to be set.
Additionally, the Slack adapter for Hubot requires an environment variable to be set for the Slack API token called HUBOT_SLACK_TOKEN
.
We will store both of these in the config.json
file we created earlier.
Open the C:\PoshHubot\config.json
file and in the EnvironmentVariables
section, add the new environment variables.
The completed config.json
file should look something like this:
With all the configuration in place, we can start Hubot.
Open up Slack and see your bot online! If for some reason your bot doesn’t connect, you can find the logs in the LogPath
defined earlier in the config.json
file.
Hubot comes with some built in commands, so you can directly message your bot with help
and see if you get a response back.
If you want your bot to join certain channels, you can enter /invite @bender
in Slack to bring him into the channel. To have Hubot perform commands, you need to address him in the channel. Try a @bender pug bomb me
.
Integrating Hubot with PowerShell
We have our Hubot joined to Slack and we have triggered a few pug bombs, but it is time to do something useful - create our own script.
The Hubot documentation covers scripting in detail and I recommend giving it a read before continuing on.
We are going to write a basic script to find the status of a Windows service on the machine hosting the Hubot. The plan is:
- Send the bot a message saying
@bender: get service dhcp
- wheredhcp
could be the name of any service. - The Hubot script will use a regex capture group to select out the name of the service (in this case
DCHP
) - The Hubot script will pass this captured service name into a PowerShell script to find the status of the service.
- If the service exists, it will return the service status.
- If the service does not exist, it will say so.
- The PowerShell script will return the results in a json format. This will make it far easier to work with in CoffeeScript
Install Edge.js and Edge-PS
Edge.js and Edge-PS are Node.js packages which allow calling .NET and PowerShell (among other things) from Node.js.
To use them inside Hubot, we need to add them to the package.json
file which is generated when we install Hubot for the first time. You can find package.json
in the BotPath
specified above, in our case it is C:\myhubot\packages.json
. We will also add a version constraint. The latest version of each package can be found by searching the npm package manager.
After you have added them your package.json
should look similar to this:
Usually, after you update the package.json
, you would need to run npm install
to download the packages that have been added. This is handled behind the scenes for you by the Start-Hubot
command.
Create the PowerShell script
We need to design a PowerShell script that can be called from CoffeeScript, the Hubot scripting language. I recommend using the following methods when creating PowerShell scripts that will be called from Hubot:.
- Create PowerShell functions with paramaters - It makes it nice and easy to call PowerShell from CoffeeScript when they have well defined parameters
- Use error handling in your script - Use try-catch blocks inside your PowerShell functions so you can return a message to the bot if the command has failed
- Output results in json - This is a great way to pass data back to CoffeeScript. You can use PowerShell objects to send data back and have CoffeeScript pick out the parts you want
Keeping these methods in mind, I created a Get-ServiceHubot
function to find the service status:
I am applying some Slack formatting in my output, including the use of asterisks around words for bold and back ticks for code blocks. You will notice there are double backticks in the code so PowerShell does not interpret them.
Here is some example output from the PowerShell when the function is run against a service that exists:
Here is some example output from the PowerShell when the function is run against a service that doesn’t exist on the machine:
Save the PowerShell function into the scripts
folder in the Hubot directory. In my case I will be saving it to C:\myhubot\scripts\Get-ServiceHubot.ps1
Create the Hubot script
Now that our PowerShell function is completed, we need to wire it up to Hubot using CoffeeScript.
The goal for the CoffeeScript portion is to take a users message to the bot, work out the service name, pass it into the PowerShell script and return the result to the user.
This is the script I designed to call the PowerShell function. Be sure to read the comments so you understand how it works.
Save the CoffeeScript into the Hubot scripts directory as well, in my case this will be C:\myhubot\scripts\get-servicehubot.coffee
.
Testing the script
To load the script into Hubot, you need to restart the bot:
You will notice that npm
installs the Edge.js dependencies we added in the package.json
.
Check the logs in LogPath
defined earlier in the config.json
file to make sure that Hubot started successfully and loaded your script. You should see a line in the log file like this:
When your bot joins the channel, ask it for help again. You will notice that the get service
command has been added to the help. This is done automatically when you fill out the header part of the CoffeeScript script.
Now you can try some get service <service>
commands and see the results:
Wrapping Up
Hubot with PowerShell is a fantastic way to bring automation to your environment. With a tiny amount of CoffeeScript you can take your pre-existing PowerShell functions and make them available in a chat channel for anyone in your team to access. This is especially useful for allowing people in your company to access information on-demand from places Operations teams may only have access to.
I’d love to hear about the cool scripts you come up with when leveraging Hubot and PowerShell! Tweet me @matthodge.