One of the biggest pains with terraform is that it's not totally 12-factor compliant (III. Config). That is, terraform doesn't consume environment variables for all settings & parameters. As a result, many of us use wrappers like terragrunt to invoke terraform.
Have you ever wanted to set the backend config using strictly environment variables?
Well, as it turns out this is possible - just in an extremely roundabout way. For example, if we want to set the backend-config bucket using an environment variable, we can do the following:
export TF_CLI_ARGS_init="-backend-config=bucket=my-bucket"(Read more here)
Then anytime I call terraform init, it will automatically pass the backend setting as a parameter. This works for all other settings as well.
The Problem
The problem with TF_CLI_ARGS_* is that it is difficult to toggle individual parameters without reconstructing the entire env.
Instead, what I want to do is set TF_CLI_INIT_BACKEND_CONFIG_BUCKET=my-bucket and not mess with constructing terraform parameters. Similarly, then I can set TF_CLI_PLAN_REFRESH=true to automatically add -refresh=true when calling terraform plan
The Solution
It's for this reason, we've added support for setting TF_CLI_* environment settings to cloudposse/tfenv (#golang), which will then map them to the TF_CLI_ARGS_*.
Download the precompiled binary here for your OS.
Now, we can do the following (e.g. by adding it to our .envrc and using direnv):
source <(tfenv)
Then I can use vanilla terraform without any wrappers and just run terraform init, terraform plan, terraform apply, etc... and they "just work". No wrappers needed (e.g. terragrunt).
But wait, there's more!!!
We can automatically initialize any terraform-root-module.
For example, if I add this to my .envrc:
export TF_CLI_INIT_FROM_MODULE="git::https://github.com/cloudposse/terraform-root-modules.git//aws/vpc-peering?ref=tags/0.29.0"
source <(tfenv)
Now, when I run terraform init, it will download the remote module and initialize it all in one fell swoop.
What I like about this is we can now manage our environment how we want to.
- Manage the enviroment the way we want to. e.g. using
chamberor some other tool likedirenv, or both!
source <(chamber exec $(basename `pwd`) -- bash -c 'export -p')
-
We can use the task runner of our choice (e.g.
make,robo,variant). -
...and we can use vanilla terraform without wrappers.
Curious? We do this and WAAAAAAY more in cloudposse/geodesic