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
chamber
or 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