Journey to Terraform 0.12

Over the past couple of months I’ve been involved in upgrading my favourite automation tool; Terraform, to version 0.12.

I was late to the 0.12 party for a couple of reasons:

  • There were over 110 Terraform states to upgrade, across 3 clouds and 20+ Terraform providers
  • Many of the states shared the same custom modules
  • A couple of Terraform providers took a while to support 0.12
  • Some providers for 0.12 only supported the latest version of the platform it’s managing e.g. Kong API

This does not describe how to upgrade Terraform to 0.12 (the official guide is here: https://www.terraform.io/upgrade-guides/0-12.html), but shares some tips and tricks to speed up the process and minimise impact.

Backup your states

Once you run terraform apply with 0.12 on a state, it cannot go back to 0.11, so ensure you’ve backed up your states. You can save your remote state with:

It is also a good practice to have bucket versioning enabled on your storage bucket (I use at least 10 versions).

Upgrade custom modules

If you’re using many custom modules in your git repository, clone them all into another location i.e. 0.12/ subfolder, and upgrade each one independently.
Yes you can do a terraform init and plan on a module just to validate the syntax:

Specify min version for all providers

If you see the following error message:
Error: Failed to instantiate provider “github” to obtain schema: Incompatible API version with plugin. Plugin version: 4, Client versions: [5]

This indicates that your provider does not support Terraform 0.12.
Many people do not specify a min version for providers, especially the core Terraform providers such as template, http, random, null etc… Upgrade each one and specify a min version e.g.

Upgrade states

TLDR;

You may see some default values have changed or been added to the new provider, add them to your .tf files until you see no changes or they are minor changes and safe to apply.

The 0.12upgrade command creates a versions.tf file which is a quick way to see whether you’ve upgraded this state yet (including in modules).

Some gotchas

The 0.12upgrade does a great job but isn’t going to be 100% accurate. Some common changes are:

var.version reserved
Remove any var.version as it’s now reserved (I’ve had to remove it in lots of modules relying on a version of a helm chart for example)

Count for enabled
A quick fix for the count where it’s used for true/false is to convert it to 1 or 0:
count = var.enabled ? 1 : 0

Quotes
Some fields in resources need quotes as Terraform thinks it’s a variable or resource property, when it’s not and consequently removes the quotes. In this example credentials.json needs to be quoted

Lookups
If you get the error message “Blocks of type “default” are not expected here. Did you mean to define argument default?”.

Lists have changed with 0.12 and are much more powerful, a shortcut to keep it working is to just specify type = any.

Happy terraforming !