Atlantis + Terragrunt = ?
TLDR; Does Atlantis work with Terragrunt? The short answer — pretty much, yes (updated 18.9.2018).
UPD (7.5.2019): Published new repository Terragrunt Reference Architecture where the very real code is published. Check it out if you want to see Terragrunt in action.
UPD (18.9.2018): Updated blog post, added a link to Terragrunt use-case in Atlantis documentation.
UPD (25.5.2018): I have just published Terraform module for running Atlantis on AWS Fargate — https://github.com/terraform-aws-modules/terraform-aws-atlantis
When I wrote this blog post in February 2018, Atlantis didn’t have proper integration with Terragrunt and a lot of things have changed since that time. Please check Terragrunt use-case in Atlantis documentation because some of the following may be outdated.
I go through my experience of integrating these two tools:
- Terragrunt — Thin wrapper for Terraform that provides extra tools for working with multiple Terraform modules.
- Atlantis — A unified workflow for collaborating on Terraform through GitHub and GitLab.
Both of these projects are open-source and have decent community (1000 stars and 39 contributors — Terragrunt; 600 stars and 13 contributors — Atlantis).
I use Terragrunt because I like the way my Terraform code is structured and I’d like to keep it DRY. I use Terraform AWS modules and promote reusability whenever possible (internally — with private infrastructure modules shared between teams; externally — with resource modules published in terraform-aws-modules).
Most of experienced users I know tend to not mix Terraform configurations (*.tf) with the actual values (*.tfvars) when working on medium/large setups. I like to hide Terraform code from users by just giving them access to values they should control (of course, they contribute to Terraform configurations, but it happens not in the same place they play with values). Terragrunt helps with this quite a lot.
Once code is pushed, developer opens a pull-request and pull-request reviewers can see Terraform plan before merge. This is the simplest functionality I wanted to achieve with Atlantis.
Now, let me explain a project structure and see whether Atlantis can help.
- Different projects are located in directories like project-env/region/layer. For example: user-stage/eu-west-1/vpc — has code for VPC layer deployed in eu-west-1 region used by user project in staging environment.
- Each project has its own set of AWS IAM roles which should be assumed to be able to change infrastructure (readonly role — to do terragrunt plan, power-user role — to do terragrunt apply)
Let’s get it working together…
Following setup instructions described on Atlantis project page was pretty easy to get a Terraform project of supported structure to work. My project structure was not supported out of the box, and in order to make Atlantis to work with my structure I used to come up with some hacks.
Which binary to run?
It is possible to specify version of Terraform using terraform_version parameter in configuration file (atlantis.yaml), but not complete path to a binary or shell wrapper, for my case.
Solution #1— make terraform an alias to terragrunt wrapper script and tell wrapper script where correct terraform actually is:alias terraform=/usr/local/bin/terragrunt.sh
Solution #2 — change PATH environment variable to resolve a terragrunt shell wrapper instead of the correct terraform binary and rename shell wrapper to terraform.mv /usr/local/bin/terragrunt.sh /usr/local/my-bin/terraform
I leave to you to decide which solution is less ugly :)
Ideally, there should be a good way to specify path to a binary through configuration.
Workspaces? No, please!
I don’t use Terraform workspaces and don’t want any tool to decide this for me. This should be controllable and should be disabled by default on my opinion. In Atlantis it is not possible to disable this.
Arguments are appended
Similar to workspaces, Atlantis assumes I use terraform and appends some arguments to commands it run (eg, -no-color). In some cases it works well, but it expects a single string as an output of terraform version so I used to make another hack in my shell wrapper to make Atlantis happy:# terraform version should return single string, but terragrunt outputs a bit more
if [[ "$1" == "version" ]]; then
echo "Terraform v0.11.3"
This is the main show stopper. Atlantis expects atlantis.yaml to be placed in a project root. In a single repository we have dozens of projects at the same time, so there should be at least the same amount of configuration files, which is simply not acceptable for us. 100% of my projects could be served with the same atlantis.yaml file. Remember, Terragrunt helps to make infrastructure configurations DRY.
It would be good to support some inheritance of configuration file, or have an environment variable, or command line argument to specify the configuration file to use.
Atlantis supports project structures described here. I have opened an issue 523 which describes desired project structure and will be glad to elaborate as time allows.
I think Atlantis should have a list of whitelisted and blacklisted directories where Atlantis has to check for changes and run commands.
Wouldn’t it be great to be able to write atlantis apply user-stage/eu-west-1 it a pull-request comment and it understands what is a project and make things happen. I think it is an awesome goal.
More points and ideas for another time:
- Expose terraform execution via API to be able to trigger same commands using other webhooks (eg, in Slack messages — /atlantis apply user-stage/eu-west-1 or /atlantis output user-stage/eu-west-1)
- Assume role support is tightly connected to Terraform at the moment and does not work like this with Terragrunt which support CLI argument and environment variables.
- Assume role with MFA is impossible at the moment. Add integration with Slack or Twilio to send request to a person who has requested atlantis apply.
- Reformat output of terraform plan which is pasted as a comment into collapsable list (using “<details><summary>Summary</summary>Details…</details>” tags)
I want to say that Atlantis is a great young project which is very much needed in the Terraform community. Let’s contribute our time to it (by trying it at least) and make it even better— https://github.com/runatlantis/atlantis.
Stay in touch: https://twitter.com/antonbabenkoat