One Makefile to rule them all

Some languages have environment or version managers such as RVM for Ruby, NVM for Node, or even Rackspace's DVM for Docker.

It's highly recommended to lock the Terraform version, so everyone in the team uses the same version, and updates can be painlessly handled. To do that, I suggest using a Terraform container, so we'll use here the one I use myself: sjourdan/terraform:<version> (from https://github.com/sjourdan/terraform-docker). But I understand replacing the simple terraform command by something such as docker run -it --rm -v `pwd`:/data sjourdan/terraform:0.7.3 can feel not so appealing. That's why we can use a common Makefile for each project using Terraform.

Using a common entry point for manipulating the infrastructure code helps a lot of sharing practices, enforcing policies, and integrating third-party services such as CI systems.

Getting ready

To step through this recipe, you will need the following:

  • A working Terraform installation
  • An AWS account with an SSH key configured in Terraform (refer to the Chapter 2, Provisioning IaaS with Terraform recipes)
  • An Internet connection

How to do it…

Let's begin by setting the Terraform version we want to use in a Makefile so it will be easy to manipulate for updates in the future:

TERRAFORM_VERSION = 0.7.3

Let's now create a TERRAFORM_BIN variable that will include the full Docker command, plus share our local folder:

TERRAFORM_BIN = docker run -it --rm -v "$(PWD)":/data sjourdan/terraform:$(TERRAFORM_VERSION)

I like auto-documenting my Makefile, and I propose a popular technique: make by default calls make help, which in turn parses the Makefile for comments, and displays them. That way, I can choose what to output by simply adding a comment. Here's how it works:

.DEFAULT_GOAL := help

help:
  @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "33[36m%-30s33[0m   %s
", $$1, $$2}'

Now simply use this feature to create an entry for the validation and formatting from the previous recipe:

validate: terraform-fmt terraform-validate  ## Validate syntax and format
terraform-fmt:
  $(TERRAFORM_BIN) fmt -list
terraform-validate:
  $(TERRAFORM_BIN) validate

If you simply type make, you'll get an automatic help:

$ make
validate                       Validate syntax and format

Now, a simple make validate will both validate the syntax and format the code.

It would be great to have the plan and apply commands as well, and if you followed the recipe on environment management with Terraform, that would be awesome if it worked right from the Makefile, we'd save a lot of time.

Start by creating the Makefile main "help" entries:

plan: terraform-validate terraform-plan ## Plan changes
apply: terraform-validate terraform-apply ## Apply Changes

Note

We added the validation step at each step, so we're always absolutely sure it passes full validation (and you can add your own validation steps).

Let's check for an environment variable named env, passed at make execution (such as make plan env=staging), and returns an error if not set:

ifndef env
getenv=$(error var:"env=" is not set)
else
getenv=$(env)
endif

Now we can write what terraform-plan and terraform-apply are exactly running, with isolated Terraform states and environments:

terraform-plan:
  $(TERRAFORM_BIN) plan -state=$(call getenv).tfstate -var environment=$(call getenv)

terraform-apply:
  $(TERRAFORM_BIN) apply -state=$(call getenv).tfstate -var environment=$(call getenv)

By the way, you can add support for environments to our previous terraform-validate example:

terraform-validate:
  $(TERRAFORM_BIN) validate -var environment=$(call getenv)

Add as many features as you want to your project's Makefile; you'll soon realize this simple tool helps so much.

For example, I always add a make destroy command, so I can easily destroy a test infrastructure (be careful though!):

destroy: terraform-destroy  ## Destroy (careful!)
terraform-destroy:
  $(TERRAFORM_BIN) destroy -state=$(call getenv).tfstate -var environment=$(call getenv)

Our Makefile now looks like this:

$ make
apply                          Apply Changes
destroy                        Destroy (careful!)
plan                           Plan changes
validate                       Validate syntax and format

Also, it can be used like this:

$ make plan env=staging
$ make apply env=staging

Note

Add absolutely anything that might make your lives easier, such as releases, tests, and so on.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.139.103.204