I am considering switching some of our infrastructure code over to Terraform, as we hit a bit of a wall with AWS CloudFormation.
Let me take an example of what I'm trying to achieve. I have an ECS cluster which can run around 10+ different task definitions. Each task definition contains almost the same configurations so to avoid code duplication I am building a reusable module.
From what I have gathered there are 3 primary ways to structure your terraform directories.
1:
project
├── modules
| ├─ ecs
| ├── main.tf
| ├── variables.tf
| ├── task
| ├── main.tf
| ├── variables.tf
|
|
└── env
| ├─── dev.tfvars
| ├─── prod.tfvars
| ├─── stage.tfvars
| ├─── 10+
|
|
|── main.tf
|── variable.tf
With this structure, I would have to get the variables from the env folder and pass it with -var-files="env/dev.tfvars"
and then in my main.tf I would have to pass the variable to the modules/ecs/task/main.tf which seems like a long way, and a lot of steps just to get a variable to the ecs/task/main.tf
2.
project
├── modules
| ├─ ecs
| ├── main.tf
| ├── variables.tf
| ├── task
| ├── main.tf
| ├── variables.tf
|
|
└── stage
| ├─── main.tf
| ├─── variable.tf
| ├─── stage.tfvars
|
└── dev
| ├─── main.tf
| ├─── variable.tf
| ├─── dev.tfvars
|
└── 10+
| ├─── main.tf
| ├─── variable.tf
| ├─── X.tfvars
If you wish to apply environment-based variables to the modules/ecs/task/main.tf
, you would have to start from the main.tf
in for example stage which calls the modules/ecs/main.tf
. and from there apply it through the /modules/ecs/main.tf
which then applies it to the /modules/ecs/task/main.tf
.
The problem with this approach is also whenever I add a new module, I would have to add it to all the different environments' main.tf
3.
project
├── modules
| ├── ecs
| ├── main.tf
| ├── variables.tf
| ├── task
| ├── main.tf
| ├── variables.tf
|
|
|
|
|── main.tf
|── variable.tf
Using terraform workspaces, I can use locals in the modules/ecs/task/variables.tf to determine what environment I am building. Like this:
modules/ecs/task.variables.tf
locals {
env="${terraform.workspace}"
masterAccountIDS = {
"default"="12121212"
"dev"="84848484"
}
masterAccountID="${lookup(local.masterAccountIDS, local.env)}"
}
But this would require that every time I add a new environment I go through all my variables.tf files, and add a new entry called for example "stage".
I can't figure out a way that would allow me not to copy paste code, or insert new things when adding new environments or keep it all located at one place, so I would maybe only have to edit one file.