top of page

Refactoring Terraform without causing havoc


💡 This post is quite opinionated, yet, these are lessons learned the hard way! So take what you will

 
“The Only Constant in Life Is Change.”- Heraclitus

The Only Constant in Life Is Change. A fact that also applies to our Software projects. Suppose you are a DevOps or Infrastructure engineer responsible for provisioning infrastructure. In that case, it is your role to ensure that your work is resilient, easy to change, and ultimately a work of art.


These qualities can only be accomplished if we proactively try to keep our system clean. Like anything in life, Software needs maintenance. Usually, that involves refactoring. So how do you refactor code that can take down your entire environment? Let me shed some light on that.


💡 I will be referring to Terraform resources, data sources, variable names and such as Terraform entities!


Renaming Terraform entities


Let's look at naming practices in Software that also apply to Terraform and reanalyze how to refactor names without breaking things.


  • Use names that reveal your intent: Name things to allow people to read your code much more straightforward and comprehend each entity's purpose (resource, data, or modules).

  • Don't use single letter names: This one is pretty obvious; look at the code below and tell me if you can guess what it does? This module could be doing anything, and it isn't clear what it does!


module "a" { 
    source = "../../modules/gcp/infrastructure"
    message = "this_is_obsecure_and_ugly!"
}

  • Avoid disinformation: These are names that are interpreted differently. Look at this piece of code below and assess if you think this means "a single VPC" or does the letter 'a' refers to a convention used to identify the zone! This is considered misinformation or open for interpretation, which causes unnecessary overhead and rot.

module "a_vpc" { 
    ...
}

  • Make useful distinctions: If something has another purpose, then the name MUST be different.

  • Avoid using noise words: Like (Data, info, List, etc...) "Distinguish names in such a way that the reader knows what the difference has to offer."

  • Use pronounceable names.

  • Choose clarity over clever names.

  • Pick one word per concept and stick to it: For example, if you have two modules that suppose to allow you to provide object storage, say across AWS S3 and Google Storage. This code below is confusing indeed. Because once time, you refer to the module as a "bucket" and another time as "object-storage." It is essential to use the same word for the same concept! In case you choose the term bucket, then possible names could be "google-bucket" and "aws-bucket."

module "bucket" { 
    name = "google_bucket"
}
// -------------  
module "object_storage" { 	
    name = "aws_s3" 
}
  • Shorter names are better as long as they are clear!

  • Only use lowercase letters and numbers.

  • Favour using underscores to separate words for Terraform entities.

This list is incomplete yet mighty! Keep these in mind while naming things in Terraform. Now, how do we refactor names without causing downtime?


Terraform allows you to list all the state files' entities using terraform state list. This command will show you all entities your state file currently knows about.


Now I noticed that I am using the k8s-cluster module!! As I mentioned earlier, it is a best practice to use underscores in names. Here is how we fix that!

  • Let's start by running terraform init

  • Then we fix the name to k8s_cluster

  • rename the module in the state file using terraform state move [old_module_name] [new_module_name]

> terraform state mv \ 	
    module.k8s-cluster.google_container_cluster.gke_cluster \
    module.k8s_cluster.google_container_cluster.gke_cluster  
 
> terraform state mv \ 
module.k8s-cluster.google_container_node_pool.gke_cluster_node_pool \ 		module.k8s_cluster.google_container_node_pool.gke_cluster_node_pool 

Now running terraform plan should result in No changes. Infrastructure is up-to-date.


Let's inspect the state file again using terraform state list. We can see that we successfully renamed the module to k8s_cluster to follow the new best practices we learned!



Here is the refactoring method!

  • You make the changes to the entity

  • you copy the old entity name from the result of the state list command

  • and then you update the path depending on what you have changed!


Here is another example of changing the node pool's name from gke_cluster_node_pool to gke_node_pool.


  • First, I would navigate to the gke_cluster module

  • Then I would update the resource name to gke_node_pool

  • Then I would run:

terraform state mv \
module.k8s_cluster.google_container_node_pool.gke_cluster_node_pool \ 
module.k8s_cluster.google_container_node_pool.gke_node_pool 
  • Then I would validate that I haven't broken anything using terraform plan.


Moving Terraform entities left and right!


How do you move a bunch of Terraform resources to a module without breaking anything?


The same workflow applies! You follow the above process for each resource you would like to move, and you prefix the resource with the module.[module_name].


Here is an example:

> terraform state list 
google_compute_network.vpc google_compute_subnetwork.subnet["primary subnet"]
  • Create a module and add the resources to it

  • Run the state commands like this terraform mv [resource][resource_name] module.[module_name].[resource].[resource_name] for each resource you moved

  • Use terraform plan to validate you haven't broken anything.

Voila!! You were able to refactor your terraform code without breaking anything! Now you can grab a drink and brag about how clean your Terraform code is!


In the next blog posts, we will look into how we can isolate entities from the state file. We will examine module structure best practices and much more!


If you want to learn more about Terraform at scale and how to keep your code clean, check out my conversation with Tylor and Mishra, where we talk about Terraform at Scale.



144 views0 comments

Recent Posts

See All

Comments


bottom of page