9
votes

I used to use multiple .sh files that ran different "terraform remote config" commands to switch between state files in buckets in different Google Cloud projects for different environments (dev, test and prod).

With version 0.9.0, I understand that this now goes into a a .tf file:

terraform {
  backend "gcs" {
    bucket = "terraform-state-test"
    path   = "terraform.tfstate"
    project = "cloud-test"
  }
}

In version 0.9.0 there is now also the State Environment ("terraform env"):

resource "google_container_cluster" "container_cluster" {
  initial_node_count = "${terraform.env == "prod" ? 5 : 1}"
}

But how should I now manage multiple environments in the same directory structure with the new backend configuration?

1

1 Answers

1
votes

At the time of this writing, not all of the remote backends in Terraform have been updated to support state environments. For those that have, each backend has its own conventions for how to represent the now-multiple states in the data store.

As of version 0.9.2, the "consul", "s3" and "local" backends have been updated. The "gcs" backend has not yet, but once it has the procedure described here will apply to that too.

There's initially a "default" environment, but if you never run terraform apply with this environment selected then you can ignore it and name your environments whatever you want.

To create a new environment called "production" and switch to it:

terraform env new production

This will establish an entirely separate state on the backend, so terraform plan should show that all of the resources need to be created fresh.

You can switch between already-existing environments like this:

terraform env select production

Before 0.9, many teams (including yours, it sounds like) wrote wrapper scripts to simulate this behavior. It's likely that these scripts didn't follow exactly the same naming conventions in the storage backends, so some manual work will be required to migrate.

One way to do that migration is to start off using the "local" backend, which stores state in a local directory called terraform.state.d. While working locally you can create the environments you want and then carefully overwrite the empty state files in the local directory with the existing state files from your previous scripted solution. Once all of the local environments have appropriate states in place you can then change the backend block in the config to the appropriate remote backend and run terraform init to trigger a migration of all of the local environments into the new backend.

After this, the terraform env select command will begin switching between the remote environments rather than the local ones.

If your chosen remote backend doesn't yet support environments, it's best to continue with a scripted solution for the time being. This means replacing terraform remote config in your existing wrapper script with a use of the partial configuration pattern to pass environment-specific configuration into terraform init.