Speed Up Terraform Debugging Using Terraform Console

Utilize Terraform Console for rapid feedback and resolving data structure problems.

Want to debug terraform issues with quicker feedback and instant access to terraform state? Try ✨Terraform Console ✨ - the equivalent of the python shell, but for Terraform.

Background

What am I doing?

This week I've been working on setting up canary analysis with Argo Rollouts for a service I'll refer to as: my-service. We do this by using Terraform and the way we do it requires having a local variable named local.my-service_pools containing a map of environments and their pools.


The Problem

  1. The pools (zones) that my-service runs in for each environment (production, staging and meta) are read from multiple yaml files and stored in a variable named local.my-service_pools

  2. local.my-service_pools is used by other terraform tooling and therefore must be correct as soon as it's created.

  3. Due to the way that our infrastructure is set up, the variable requires that any pool named us-central1-f be named default, and therefore any mention of us-central1-f would need to be swapped for default in this map.

To tackle this problem, I decided to first read the contents of the file into a temporary variable named local.my-service_zonal_pools_from_yaml which I thought simply looked like this:

The Goal

To create a new variable named local.my-service_pools which uses a for loop to iterate through my temporary local.my-service.zonal_pools_from_yaml and while doing so: replace any mention of us-central1-f with default.

A Failed Fix

I used a for loop to make a "copy" of the variable (Terraform doesn't support copying variables) by iterating through each environment, and then through each pool to replace us-central1-f with default

I referred to this as my "transformation" variable.

Which seemed good but... was actually wrong ❌, because the downstream references to that variable kept on yelling at me:

Frustration

  1. The error message doesn't tell me much. Yes, it's a list of strings, but that's what I wanted isn't it?

  2. The Feedback loop is too long. Because this is the Terraform for our entire environment's infrastructure and because our Terraform runner (Spacelift) is constantly running plans from PR's across the organization - I have to wait a long time to see the results of my changes via terraform plan

    1. On Spacelift, I'm competing with private workers to become available to run my plan; and

    2. On my laptop - it takes 10+ minutes to build because I don't have the state cached (or, more specifically, that the cache keeps on changing with every run on Spacelift.

Research

I realized I was getting bitten on syntax / data massaging here - and first I'd need a better, faster, cheaper way to play with the Terraform for quick iteration and results.

And so off to Google I went.

Enter: terraform console

What does Terraform Console do? The terraform console command will read the Terraform configuration in the current working directory and the Terraform state file from the configured backend so that interpolations can be tested against both the values in the configuration and the state file.

With terraform console

  1. I could see the warning I was running into as soon as it started up. (It's my "early-warning" that the code was still incorrect)

  1. I could inspect and see what local.my-service_zonal_pools_from_yaml actually looked like right now!

  2. And then I could compare it against local.my-service_pools to see what my transformation variable instantiation was actually putting out!

‼️ The actual problem was that: my-service_pools_from_yaml has each environments zones in a toset() whereas my-service_pools has those zones in a tolist()

Solution

✨Surround the for loop with a toset()

Now when I run terraform console there are no errors, which is my first-sign that my code is correct.

And, when I compare the two variables in the console, I see that they are both toset()'s ✅:

Caution

While you're in the console, you acquire a state lock 🔒 that could prevent other people from using Terraform.

Releasing state lock. This may take a few moments...

The console holds a lock on the state, and you will not be able to use the console while performing other actions that modify state.

Conclusion

In conclusion, terraform console is a powerful tool for debugging and fine-tuning Terraform code, providing quick feedback and reducing the time spent waiting for terraform plan results. It is especially useful for working with loops, experimenting with new syntax, and resolving structural issues. However, be cautious when using the console as it acquires a state lock, which may prevent others from modifying the state.