Speed Up Terraform Debugging Using Terraform Console
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
The pools (zones) that
my-service
runs in for each environment (production
,staging
andmeta
) are read from multiple yaml files and stored in a variable namedlocal.my-service_pools
local.my-service_pools
is used by other terraform tooling and therefore must be correct as soon as it's created.Due to the way that our infrastructure is set up, the variable requires that any pool named
us-central1-f
be nameddefault
, and therefore any mention ofus-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
The error message doesn't tell me much. Yes, it's a list of strings, but that's what I wanted isn't it?
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
On Spacelift, I'm competing with private workers to become available to run my plan; and
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
- 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)
I could inspect and see what
local.my-service_zonal_pools_from_yaml
actually looked like right now!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.
Subscribe to my newsletter
Read articles from Thilina Ratnayake directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Thilina Ratnayake
Thilina Ratnayake
I'm a developer from Vancouver, BC who's had an interesting journey in tech starting from support, through cloud infrastructure and project management. Currently I work as an SRE at lightstep helping build and "operationalize" things that helps to guide others towards better o11y :)