Category:

Introduction

During my co-op term, I got the opportunity to work with the creators of Atlantis to contribute a Slack integration feature, providing value to both Hootsuite and the open source community. I learned significantly and enjoyed developing the feature all the way from design to implementation and testing.

Background

At Hootsuite, we write our infrastructure-as-code using Terraform. To effectively collaborate on Terraform, we created and open sourced Atlantis. Here’s a brief introduction for those unfamiliar with Terraform or Atlantis.

What is Terraform?

Terraform is a tool for writing infrastructure-as-code, controlled via a Command Line Interface (CLI). This allows users to review, version, reproduce and automate changes in infrastructure.

Using Terraform, we describe infrastructure resources such as compute instances, storage, security groups, DNS entries and more, using HashiCorp Configuration Language (HCL).

For example, we can describe an AWS security group with:

Then run terraform plan to create a plan for modifying infrastructure – creating a security group in this example. Finally run terraform apply to apply the plan.

What is Atlantis?

Atlantis is a tool for teams to effectively collaborate on Terraform. It enables Terraform plans and applies to happen directly on Version Control System (VCS) platforms such as Github via pull request comments. As a result, both operations engineers and developers can collaborate, discuss and review Terraform outputs right on the pull requests. Other cool features include a unified location for credentials so no need to worry about distributing credentials and locking workspaces to prevent concurrent modification.

Atlantis and Terraform in action

We’ll create a pull request on Github describing a security group:

Then comment atlantis plan to make a Terraform plan for creating the resource:

Finally comment atlantis apply to actually create it. After doing so, we can see the newly created security group on AWS:

Working in the Dark is Bad

It’s awesome that our workflow for modifying infrastructure happens directly on pull requests, but changes such as modifying security group rules, database rules, and DNS entries inherently come with the risk of causing outages. Ideally, all recent infrastructure changes should be highly visible and easily trackable, so we can minimize the time spent searching for potential breaking changes when a problem arises.

To address this issue, I first asked “where do we currently look for information about recent production deployments?” – Slack! Leveraging this, it makes sense for all infrastructure changes to be available there too. This will increase visibility on recent changes in infrastructure and reduce the time spent tracking them down.

Atlantis + Slack Integration to the Rescue

An Honourable Attempt

My first approach was to configure a Slack Incoming Webhook which provides an URL endpoint to send a message to a Slack channel. Then use Atlantis’ project specific configurations that allows a shell command to be run after an apply executes for a specific Terraform project. With these two functionality, I can configure a Terraform project to curl the Slack URL to send a message after an apply is executed. This was an appropriate proof of concept but this only works for a single project so the project specific configurations would need to be duplicated for all 100+ Terraform projects at Hootsuite to catch all infrastructure changes. Following the Don’t Repeat Yourself (DRY) software engineering principle, I knew this was unacceptable.

Second Time’s the Charm

For my next approach, I reached out to Luke and Mishra, the maintainers of Atlantis, about adding Slack integration to Atlantis natively. Luckily, they indicated this was a requested feature by users of Atlantis and endorsed the idea!

With the new approach, we can:

  1. configure the Slack webhooks for an Atlantis server rather than for each Terraform project
  2. support sending messages to different channels based on the workspace (dev, staging, production, etc)
  3. contribute to the open source community and provide an easy way for Atlantis users to set up slack notifications
To enable sending Slack messages from Atlantis at a server level, I implemented the logic to execute any webhooks and a Slack webhook that sends a request to Slack’s chat.postMessage API to post a message to a Slack channel. Finally, I exposed a configuration that allows the Slack webhook to be triggered by apply events.

After implementing this feature, it’s simple to configure Atlantis to use it. First, we create a Slack Workspace Token for accessing Slack APIs, then specify to use a Slack webhook in Atlantis’s configuration. It’ll look like:

Now we’re ready to go! Whenever Atlantis executes an apply, it’ll trigger the Slack webhook and send a beautiful message to the channel specified:

With this in place, all infrastructure changes done through Atlantis will now be visible in a Slack channel – success!

For bonus points, we can configure certain webhooks to trigger based on workspaces by specifying a workspace-regex in an event. This is useful for teams with multiple workspace environments.

Conclusion

Developing this feature and contributing it for the open source community was super fun. Big thanks to Luke Kysow for walking me through the codebase, reviewing all my code and helping me throughout the whole process from design to implementation and testing!

About the Author

Nicholas Wu is a Software Developer Co-op on the Production Operations and Delivery team. He is currently studying Computer Engineering at the University of British Columbia. Connect with him on Linkedin or find him on Github, Instagram, YouTube.