Skip to content

Instantly share code, notes, and snippets.

@osterman
Last active January 14, 2019 19:56
Show Gist options
  • Save osterman/1541fd6b60626cef4a3b322baf8d7e3d to your computer and use it in GitHub Desktop.
Save osterman/1541fd6b60626cef4a3b322baf8d7e3d to your computer and use it in GitHub Desktop.
Using Terraform without Wrappers

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.

  1. Manage the enviroment the way we want to. e.g. using chamber or some other tool like direnv, or both!
source <(chamber exec $(basename `pwd`) -- bash -c 'export -p')
  1. We can use the task runner of our choice (e.g. make, robo, variant).

  2. ...and we can use vanilla terraform without wrappers.

Curious? We do this and WAAAAAAY more in cloudposse/geodesic

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment