Terraform 012 should I bother to update my code

HashiCorp released Terraform 0.12, one of the leading Infrastructure as Code solutions on 22nd May 2019 and the current stable release is version 0.12.20. For what on paper appears a minor release there was a large amount of enhancements, but unfortunately for those that have been with Terraform for a number of years, a complete rewrite of many of the syntax coding formats that caused a number of incompatibilities in code written for earlier versions of the software. Also some of the changes also meant that the then current generation of 3rd party providers would not work with the new version. So, should I stay or should I go, or to be more precise; is it time to migrate, or should I wait?

If you have been following our series of posts on using Terraform to deploy infrastructure into AWS, you may have noticed that we have been using the latest and greatest version of the product.

Terraform

What benefits will I get with the new Terraform?

Benefits

The full set of enhanced and improved features is large but here are a few highlights:

  • First-class expressions: versions prior to 0.12 has to use expressions as a string interpolation, this meant ${var.thing}, now they have been integrated into the language and can be directly used myvar = var.thing.
  • “For” expressions; This is a big thing for Terraform, now you can easily transform elements in a list to another output element. This is a much needed function, as the method previously utilized to achieve the same result was cludgy and often buggy.
  • Dynamic configuration blocks: it is now possible to generate a number of block of code based on a list or map, using the new “dynamic” block construct. This is a much better solution than the previous method of treating a block type name as if it was an attribute that expected a list of map elements.
  • Generalised “Splat” operator: You can now use the “Splat” within expressions that are applied to any list value rather only as a part of the “count” set
  • Nullable argument Values: it is now possible to use a conditional expression to conditionally leave an argument value unset. Previously you had to provide a default value. Setting an argument to “null” effectively leaves the argument out of consideration.
  • Rich types in Module inputs: support for returning flat lists and maps of strings was introduced in version 0.7, Hashicorp enhanced this in 0.12. Rich Types Module inputs are now generalized to the allow return of arbitrary nested data structures with mixed types. Module authors can if they wish specify an expected type constraint for each input variable to allow early type checking of arguments.
  • Resource and Module Object Values: An entire resource or module can now be treated as an object value within expressions, including passing them through input variables and output values to other modules, using an attribute-less reference syntax, like “aws_instance.myvar”.
  • Extended template syntax: The simple interpolation syntax from prior versions is extended to become a simple template language, with support for conditional interpolations and repeated interpolations through iteration. For more information, see the String Templates documentation
  • Interpolation functions: Due to the richer type system in the new configuration language implementation, Terraform now offers functions for decoding serialization formats. jsondecode is the opposite of jsonencode, while csvdecode provides a way to load in lists of maps from a compact tabular representation.
  • Revamped error messages: Error messages relating to configuration now always include information about where in the configuration the problem was found, along with other contextual information. We have also revisited many of the most common error messages to reword them for clarity, consistency, and action advice.
  • Structural plan output: When Terraform renders the set of changes it plans to make, it will now use formatting designed to be similar to the input configuration language, including nested rendering of individual changes within multi-line strings, JSON strings, and nested collections. This makes for a much more logical view of what is happening in your infrastructure

For the full List of enhancements read the Change log on Hashicorp’s GitHub found here. What this has started to do is elevate Terraform from an adolescent language to a mature fully formed language. These changes to HCL allow for a much more fully formed conversation between the intent and the result.

As a result, you can see there are many compelling reasons to start using the latest Terraform release. However if you have a heavy investment in an earlier version there are a number of hurdles to jump to move to Terraform 0.12. Let’s look at what you need to do to move your code to 0.12.

What will I need to change in my Terraform Code?

changes

As we said earlier there are a number of syntax changes to the way that your code is written this makes upgrading a little more complex than a minor version update but it is not too onerous.

The format of tags for example has changed in Terraform 0.12 it used to be

tags {

But now it is:

tags = {

But fortunately we do not really need to worry too much about this.

How easy is the change?

Change is Easy

Your upgrade path will depend on the version of Terraform that you are currently running. If you are still running code that uses a version lower than 0.9 you will first need to review the upgrade path to 0.9 page on HashiCorp’s side and then the upgrade path to 0.11 before attempting to upgrade your code to 0.12. if your code is using 0.10 or 0.11 you will just need to review upgrade path to version 0.11.

As this post is about the upgrading of your environment to 0.12 we will only concentrate on the process once your code is at 0.11.14 (the last version of that code base).

Your first pain point will be your providers. That said, Terraform 0.12 has been out for almost a year now and all the commonly-used providers are now 0.12-compatible having released second generation provider versions.

If you have not done so already in your legacy code add the following stanza to constrain your providers to a version that is compatible with your code.

terraform {
  required_providers {
    aws = "~> 1.0
  }
}

In your 0.12 code add the following

terraform {
  required_providers {
    aws = "~> 2.0"
  }
}

Obviously substitute your provider name with the relevant one against which you are running your code. That will mean that your new code will work with the newer providers. And your legacy code will run against the old providers.

This may seem like a lot of hard work, that’s OK HashiCorp have managed a lot of the heavy lifting for you. The process to upgrade your code is simply running four commands against your repo, but first to first a couple of potential gotchas.

Firstly before you upgrade a repo – comment out any version constraints. Obviously download and install the binary of Terraform 0.12, then make tan alias, to the version 11 binary – this will make the upgrade process more logical and prevent any issues being caused by the incorrect version being used.

Linux

From the working directory of the binary

alias terraform11=terraform

To verify run the commands

Terraform11 –version and terraform –version you should receive a response similar to the below

terraform11 –version
Terraform v-0.11.14

And

terraform --version
Terraform v0.12.20

Windows10

The process is a little more complicated in a windows environment and may not be worth the effort.

Completing the Terraform upgrade

Upgrading

To actually complete the upgrade you need to issue these four commands

terrafrom11 0.12checklist

Please note that this command is using the version 11 binary. The next three command use the new version 12 binary

terraform init --upgrade
terraform 0.12upgrade
terraform plan.

If you are lucky you will not receive any error on your code and you now have a version 0.12 repo.

Some things will need a manual intervention. Fortunately the upgrade process will point out where the errors are and give an explanation. For example the way count works has changed. Also the handling of variables is stricter with version 12, and it will catch any undeclared values and any resource that starts with a number will have to be prefaced with a letter.

Summary

Terraform Summary

The upgrade path from 0.11 to Terraform 0.12 is well mapped out and now that the code base is stable we have had 20 minor releases on version 0.12 since it’s release in May of 2019 there is really no excuse for not migrating your code.

The process is not that onerous and is actually straightforward if you follow some common-sense strategies. There is no real reason to keep using your legacy code base outside of a provider that has as yet not be updated to use HCL2. If you are in that position, we suggest that you start pushing back at the relevant owners of the provider and scythe them for their tardiness 🙂