Understanding the Risks of Terraform Code Refactoring

Refactoring - is the process of restructuring existing code without altering its external behavior or functionality. The goal is to improve the code's internal structure, readability, and maintainability.

Refactoring is an essential coding practice that should be done on regularly basis. It is true for general purpose programming languages. But when it comes to IaC like tools (Terraform), changing the internal structure of the code on the purpose of refactoring can be a risky operation. It can alter the external behavior and cause downtimes, crashes and many, many other scary things.

Let me show you how a common and simple refactoring technique such as renaming a resource name, can be a catastrophic in terms of Terraform.

Imagine that you have the following code that defines your EC2 instance:

resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
}

During refactoring process you come up with an idea to change the resource name to a more meaningful name such as web_server instead of web:

resource "aws_instance" "web_server" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
}

What will happen when you try to apply this change?

Terraform will recreate the resource. Terraform sees aws_instance.web_server as a new resource and aws_instance.web as no longer needed. First Terraform destroys the existing one and then creates a new resource with identifier web_server. During this process your web server will be in a downtime. That’s not what you wanted.

The proper way of renaming a resource in the example above will be by using a terraform state mv command:

terraform state mv aws_instance.web aws_instance.web_server

NOTE: Staring from Terraform v1.1 and above you can use explicit refactoring declarations with moved blocks instead of terraform state mv command.

💡
Keep in mind that Terraform is not like a general-purpose programming language and the core nature of it is operating with the state of the infrastructure. The default behavior of Terraform is: destroy old then create new.

Safeguards:

So, how to keep yourself safeguarded? The main rule is to use terraform plan and inspect it thoroughly. Verify that your changes are not destroying or creating something new.

The general list of rules are:

  • Plan Before Applying: Always run terraform plan to see the implications of your changes before applying them.

  • Update All References: Ensure that all usages of renamed variables or resources are updated.

  • Manage State Carefully: Use Terraform state commands to reflect changes in resource names.

  • Use Version Control: Keep your Terraform code in a version control system to track changes and facilitate rollbacks if necessary.

  • Test Changes: Apply refactoring changes in a non-production environment first to observe any unintended effects.

By following these rules you can avoid the pitfalls associated with refactoring and maintain a stable infrastructure with Terraform.

References: