Setting up a Managed Local Terraform Version

Rishi Goomar
Rocket Travel
Published in
3 min readMay 4, 2018

We use Terraform to provision and manage our infrastructure on AWS. We have some “legacy” terraform code that requires a much earlier version of terraform, but we also started newer projects and require one of the latest versions of terraform. There are some significant differences between the two versions and we wanted to make sure that everyone was using the correct version for the project. We built a way to make sure every terraform command is run with the correct binary for the project.

Background

Terraform is built on Go and is released as a single binary. You can download and use the Terraform binary directly by downloading from their releases page. Utilizing this knowledge, we decided to use that to keep a consistent version across computers.

The high level setup would look like this:

  1. Download Terraform binary from the releases page using a specified version
  2. Setup a reference to that location as the binary execution location
  3. Use that binary location to execute terraform commands

There are other terraform version managers like tfenv, but we didn’t want any engineer to have to install anything. An advantage of this method is that it just works right out of the box (on Mac and Linux) on our developer machines and can easily be run on a Linux server as well if need be without needing to install an extra dependency.

Makefile Setup

We use Makefile to setup easy commands with built-in defaults for various tasks that we run.

This assumes a that you have a terraform directory that has a qa or production directory within there as the environments. A simple setup.

TERRAFORM_VERSION := 0.11.7
TERRAFORM_LOCATION := .tf
TERRAFORM_BINARY := $(CURDIR)/.tf/terraform
PLATFORM := $(shell uname | tr '[:upper:]' '[:lower:]')
# Download the correct terraform version
get-terraform:
@curl -o tf_tmp.zip https://releases.hashicorp.com/terraform/$(TERRAFORM_VERSION)/terraform_$(TERRAFORM_VERSION)_$(PLATFORM)_amd64.zip
@unzip -o -d .tf tf_tmp.zip
@rm tf_tmp.zip
# Check if Terraform binary exists, otherwise download it
check-terraform-exists:
@[ ! -f $(TERRAFORM_BINARY) ] && make -s get-terraform || true
# Default to QA env
ENV := qa

# Check the terraform version and download if it isn't up to date
tf-version: | check-terraform-exists
ifneq ($(shell $(TERRAFORM_BINARY) version | head -n 1 | cut -d " " -f2 | tr -d v), $(TERRAFORM_VERSION))
@echo "Terraform version is out of date. Downloading correct version..."
@make -s get-terraform
@echo "Terraform binary updated"
else
@echo "Terraform version is up to date..."
endif
# Terraform init to a specific environment (make init ENV=qa)
init: | tf-version
@cd terraform/$(ENV) && $(TERRAFORM_BINARY) init
# Terraform plan to a specific environment (make plan ENV=qa)
plan: | tf-version
@cd terraform/$(ENV) && $(TERRAFORM_BINARY) plan

# Apply terraform to a specific environment (make apply ENV=qa)
apply: | tf-version
@cd terraform/$(ENV) && $(TERRAFORM_BINARY) apply

Now, this may look like a lot, but it allows the following:

  • Allows you to specify terraform version within the Makefile
  • Downloads the binary for the specified platform (tested on MacOS and Linux)
  • Utilizes that Terraform binary for commands using make init and make plan and make apply
  • Allows you to specify a environment to execute against
  • Checks if the terraform version you have downloaded locally is up-to-date, otherwise replace it with the version it should be using

Much of this setup can be ported over to other build tools and scripts, it’s just shell commands after all. :-)

If you want to see this in action or try it out, see this example repository.

--

--