Terraform 0.11.x to 0.12.3

At Relay42 we rely heavily on Terraform for both our infrastructure on AWS and our monitoring in Datadog.

Like the most of users of Terraform, we have been waiting long for the new release which brings a lot of changes:

Terraform 0.12 is a major update that includes dozens of improvements and features spanning the breadth and depth of Terraform’s functionality. Some highlights of this release include:

1. First-class expression syntax: express references and expressions directly rather than using string interpolation syntax.

2. Generalized type system: use lists and maps more freely, and use resources as object values.

3. Iteration constructs: transform and filter one collection into another collection, and generate nested configuration blocks from collections.

4. Structural rendering of plans: plan output now looks more like configuration making it easier to understand.

5. Context-rich error messages: error messages now include a highlighted snippet of configuration and often suggest exactly what needs to be changed to resolve them.

However, with so many changes under the hood, including a new template engine, there is an official upgrade path you have to follow to move from 0.11.x to 0.12.

So, following the guide, you might encounter the following error:

Error: module not found
The module address "<module>" could not be resolved.
If you intended this as a path relative to the current module, use "./<module>" instead. The "./" prefix indicates that the address is a relative filesystem path.
view raw error.tf hosted with ❤ by GitHub
Error: module not found

The reason for that is a change you might have missed which dictates that all modules in Terraform that reside on the filesystem have to be designated with either “./<module>” (relative to current directory) or “../<module>” (outside of current directory).

Therefore, if you have a module defined like that:

module "some-module" {
source = "some-module"
}
view raw main.tf hosted with ❤ by GitHub
where some-module is a module defined in a directory where your main.tf is located

You’d have to actually rewrite it to:

module "some-module" {
source = "./some-module"
}
view raw main.tf hosted with ❤ by GitHub
the ./ notation is mandatory in tf 0.12.x to signify a relative path

Now, if you are like us, and have 100s of modules, maybe this regex can help you to spot all modules which match:

# this should be changed to ./asd
source = "module"
# this shouldn't be matched as it's already correct
source = "./module"
# this also shouldn't be matched as it's also already correct
source = "../module"
view raw terraform.tf hosted with ❤ by GitHub
how do you match only the modules that need changing?

You can use this regex to match all modules and replace them:

^(\s*source\s*=\s*")((?:(?!\.\./|\./).)+)(")
view raw regex hosted with ❤ by GitHub
the regex of the year

In our two major projects, we got 100’s of matches:

After you are done with replacing, run a:

terraform fmt
view raw commandline hosted with ❤ by GitHub
to format your code properly

And then you are done with the compatibility changes and can run:

terraform 0.12upgrade
view raw terraform upgrade hosted with ❤ by GitHub
terraform 0.12upgrade

and follow the guide here: https://www.terraform.io/upgrade-guides/0-12.html

Happy coding!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.