Terraform workspaces are useful for storing different configurations per
environment within the same backend. In order to make changes to the configuration based on the current workspace the
workspace name can be referenced in terraform using terraform.workspace
variable.
The immediate approach to have different settings per environment would be to use the ternary operator on the workspace name per setting, I.e.
resource "aws_instance" "vm-1" {
ami = (terraform.workspace == "staging"
? "ami-0b6d8a6db0c665fb7" # 18.04 LTS
: "ami-05c26ae4789875080" # 20.04 LTS
)
instance_type = (terraform.workspace == "production"
? "m5.large"
: "t3.large"
)
}
This method not only reduces readability with more environments, but also makes it harder to infer the configuration of a specific environment as well as default values.
In contrast input variables can be used alter the configuration without
changing the source code. The values for these variables can be provided through a custom variable file (.tfvars
)
using the command line flag -var-file
, which allows the user to have environment specific settings in a single
location. This means that users aren’t only required to switch workspaces but also need to specify a different variable
file for each environment.
An open feature requests exists that tries to resolve this issue by
automatically loading variables from a variable file based on the current workspace. The comment section of this issue
mentions various workarounds by users. One workaround
is the use of a local which contains a nested map where the keys of the outer map match the terraform.workspace
name, I.e.
locals {
env = merge(local.vars["defaults"], local.vars[terraform.workspace])
vars = {
defaults = {
instance_type = "t3.large"
}
staging = {
ami = "ami-05c26ae4789875080" # 20.04 LTS
}
production = {
ami = "ami-0b6d8a6db0c665fb7" # 18.04 LTS
instance_type = "m5.large"
}
}
}
resource "aws_instance" "vm-1" {
ami = local.env["ami"]
instance_type = local.env["instance_type"]
}
Another option is to use compute the variable filename
based on the output of terraform workspace show
, I.e.
terraform plan -var-file "$(terraform workspace show).tfvars"