Upgrading to Terraform 0.12 a short summary for AWS

Giuseppe Borgese
6 min readJul 8, 2019

I have migrated 12 Terraform environments from v0.11.14 to the v0.12.2 and in this article, I share a summary about what I did to accomplish the task.

Additional Reading

Of course, you should read the official guide to upgrade your code, in this page I did a short summary of that guide plus I add my personal experience and my fixes.

Instead to start to use the new Terraform version read the guide with the new features of Terraform 0.12.

Migrate Prerequisites

  • Have your code to the latest Terraform 0.11 that it is v0.11.14. If you haven’t done yet the guide to migrate to 0.11 is this one. Also, if you want to migrate and you have this line in your code remove it or comment out as I did.
provider "aws" {
#version = "~> 1.10"
}

and run

terraform init --upgrade
terraform plan
  • In the guide it is suggested to don’t have any pending changes, I tried and this is NOT mandatory but it really helps. So try to have a terraform plan clean result. But if you are like me that you cannot apply some changes for a bug don’t worry you can update as well. Try to reduce these changes as less as possible.
  • Download the binary of Terraform 0.12 and make 2 alias because it will be helpful in the migration process, we refer to them in the article.
tf11 --version
Terraform v0.11.14
tf12 --version
Terraform v0.12.2
Immagine correlata

Perform the Upgrade to Terraform 0.12 in 4 commands

To migrate your repo you need to do only these 4 commands

tf11 0.12checklist
tf12 init --upgrade
tf12 0.12upgrade
tf12 plan

That’s it. Note the differences of the first command where we use Terraform 0.11 binary and the other 3 where we use the Terraform 0.12 instead.

The command tf12 0.12upgrade will change all your files syntax to adapt to the new one.

If you have as a result of the last command a clear terraform output the job is finished.

Of course, is very improbable that you don’t have any error message because the code needs some adaptation. So every command can report some adaptation that needs to be done before pass to the next command, I can show mines.

Change your Terraform 0.11 code to match the 0.12 syntax

I post here all my changes with the hope that I can save you a little bit of time.

  • tags: I have many of these
tags { 

has to be changed like this

tags = {

Or similarly this

 tags = [
{
“Name” = "${var.confluence_asg_name}"
},
]

has to be changed like this

 tags = {
“Name” = var.confluence_asg_name
}
  • aws_nat_gateway has a field allocation_id that is mandatory now
resource “aws_nat_gateway” “nat_gw” {
allocation_id =
  • file function is not allowed anymore in the lambda, so this code
resource "aws_lambda_function" "monitor" {
source_code_hash = "${base64sha256(file("${path.module}/${var.filename}.zip"))}"

has to be changed like this

resource "aws_lambda_function" "monitor" {
source_code_hash = "${filebase64sha256("${path.module}/${var.filename}.zip")}"
  • the count works a little bit different so I had an error like this
Error: Missing resource instance key
“aws_cloudwatch_log_group” “ssm”:
11: kms_key_id = “${aws_kms_key.ssm.arn}”
Because aws_kms_key.ssm has “count” set, its attributes must be accessed on
specific instances.
For example, to correlate with indices of a referring resource, use:
aws_kms_key.ssm[count.index]

the original resource

resource "aws_cloudwatch_log_group" "ssm" {
count = "${var.create_log_group}"
name = "/ssm-encrypted/"
retention_in_days = 14
kms_key_id = "${aws_kms_key.ssm.arn}"
}

has to be changed like this

resource "aws_cloudwatch_log_group" "ssm" {
count = "${var.create_log_group}"
name = "/ssm-encrypted/"
retention_in_days = 14
kms_key_id = "${aws_kms_key.ssm[count.index].arn}"
}
  • There are more checks that prevent you to make mistakes. In this case, I have deleted a variable from vars.tf but I forgot to remove it also in terraform.tfvars files. So the update command asks me to do it.
Warning: Values for undeclared variablesIn addition to the other similar warnings shown, 5 other variable(s) defined
without being declared.
Warning: Value for undeclared variableon terraform.tfvars line 46:
46: bastion_ami_id = “ami-cc821eb5”
The root module does not declare a variable named “bastion_ami_id”. To use
this value, add a “variable” block to the configuration.
Using a variables file to set an undeclared variable is deprecated and will
become an error in a future release. If you wish to provide certain “global”
settings to all configurations in your organization, use TF_VAR_…
environment variables to set these instead.
  • All the resources that start with a number must be changed adding a letter in front of it. This is the error
After analyzing this configuration and working directory, we have identified some necessary steps that we recommend you take before upgrading to Terraform v0.12:- [ ] `resource “null_resource” “1024”` has a name that is not a valid identifier.In Terraform 0.12, resource names must start with a letter. To fix this, rename the resource in the configuration and then use `terraform state mv` to mirror that name change in the state.

You need to change the code from

resource “null_resource” “1024”

To

resource “null_resource” “new_version_1024”

and run a terraform state mv command, this error will be shown at the first command when you are still using terraform 0.11 binary

tf11 state mv null_resource.1024 null_resource.new_version_1024
  • There are more checks in Terraform 0.12, for example, if you have defined, for an error, an attribute 2 times you need to remove it.
Error: Attribute redefinedon alb-balancer/main.tf line 11, in resource “aws_lb” “alb”:
11: idle_timeout = 300
The argument “idle_timeout” was already set at
alb-balancer/main.tf:9,3–15. Each argument may be set only
once.

remove the attribute that you have declared first because it was overridden from the second one and this is the one on the live infrastructure.

  • New lines count, this for me required a little bit of time to understand the issue.

Version on 0,11

resource “aws_wafregional_byte_match_set” “startrule” {
name = “rsso_admin”
....
byte_match_tuples
{
field_to_match {
type = “URI”
}

has to be changed with

resource “aws_wafregional_byte_match_set” “startrule” {
name = “rsso_admin”
byte_match_tuples {
field_to_match {
type = “URI”
  • This error was showed when I did a tf12 init command but it was automatically fixed after the tf12 0.12upgrade.
Error: Invalid single-argument block definition
on aurora-confluence.tf line 7, in variable “aurora_confluence_instance_name”:
7: variable “aurora_confluence_instance_name” { type = “list” default = [“”, “”] }
A single-line block definition must end with a closing brace immediately after
its single argument definition.
tf12 init — upgrade

Warning: Skipping backend initialization pending configuration upgrade
The root module configuration contains errors that may be fixed by running the
configuration upgrade tool, so Terraform is skipping backend initialization.
See below for more information.
Terraform has initialized, but configuration upgrades may be needed.Terraform found syntax errors in the configuration that prevented full
initialization. If you’ve recently upgraded to Terraform v0.12, this may be
because your configuration uses syntax constructs that are no longer valid,
and so must be updated before full initialization is possible.
Terraform has installed the required providers to support the configuration
upgrade process. To begin upgrading your configuration, run the following:
terraform 0.12upgrade
To see the full set of errors that led to this message, run:
terraform validate
  • The path of some files are changed and they aren’t tight to the running terraform username folder but to the source. This is much better because you don’t need to remove the username using some replace function but this kind of change is showed and it is necessary apply it.
# module.monitor_lambda.aws_lambda_function.monitor_iproxy will be updated in-place
~ resource “aws_lambda_function” “monitor_iproxy” {
~ filename = “.terraform/modules/25d4529ed1b8e691a0cda26d8ca11b8a/package.zip” -> “../../../terra/modules/monitor-iproxy/v0.12/package.zip” ~ last_modified = “2019–06–14T08:50:44.643+0000” -> (known after apply)~ qualified_arn = “arn:aws:lambda:eu-west-1:01234569:function:JC-TEST_monitor_iproxy:8” -> (known after apply) ~ version = “8” -> (known after apply)

Feedback

If you like this article, and you want to motivate me to continue to write, please:

--

--

Giuseppe Borgese

AWS DevOps Professional Certified — Book Author — Terraform Modules Contributor — AWS Tech Youtuber