While we want to provision most of the things through Infrastructure as Code and use Terraform with our Oracle Cloud Infrastructure we also had to make sure each change will be properly tested before moving to production.

So what is a convenient way of deploying your infrastructure with different variables to different environments?

If you search around you see there are a lot of opinions how to do this. You might want to separate your environments on different folders so they have different variables and call your modules from there or you might want to have different tfvars files for different environments and call these when you run terraform plan/apply.

There is also the option we are looking now which is to use terraform workspaces. Workspace is sort of separate environment when you run terraform plan/apply and it will use separate state for each workspace. Sounds good? Yes!

What we did with workspaces

We have three different branches and environments:

  • default (basically dev)
  • pprd (pre-production)
  • prod

When we use workspaces then the default one is active when you start. If you want to use different one you need to create it first on the folder you are running terraform with:

terraform workspace new pprd

This will also change to the workspace you created. Later on if you want to switch between workspaces you can use:

terraform workspace select prod

From development perspective if I develop my change in default workspace, execute it and see all is ok it will get moved to next branch. When it’s there we will use another workspace and there will be a new state file for that environment/branch.

So what is the point of all this?

The point is that we can easily use different variables defined in the same variables.tf we always use. What you need to do is define variables as a map like this:

variable "bucket_name" {

type="map"

default=

{"default" = "dev-admin-bucket-tf"

"pprd"="pprd-admin-bucket-tf"

"prod"="prod-admin-bucket-tf"

}

}
In this case I have a different bucket_name variable depending on which workspace is being used.
And when creating the resource I have it like this:
bucket_name = "${lookup(var.bucket_name, terraform.workspace)}"
From the map I pick the value which matches with current terraform.workspace. Simple!

Conclusion

Using workspaces is an option you could consider if you have multiple environments.

One problem I noticed is that if you would like to have a list in your variable which would be inside map this isn’t so easy to do. That way you could pass list of variables lot easier to your module (if you use modules).

While we gather more experience on using these I will probably have more refined option later on but for now it seems like a feasible option with your infrastructure.

Leave a Reply

Your email address will not be published.