Hey there.
We have an issue with dynamic providers inside modules and I am searching for a better of our implementation. Solution works, but the problem happens when we want to delete a module.
Related topics:
- Defining provider aliases with string interpolation not working in Terraform 0.12
- https://github.com/hashicorp/terraform/issues/16826
What we are doing?
With described Terraform solution, we are able to define a new Serverless project, for which we then setup resources in multiple AWS accounts.
How does it look like?
Because we need to setup resources in multiple AWS accounts for each project, our project structure looks like this.
- root
- project_aws module
- stage module
- project_aws module
Before you continue, please keep in mind that code below has been completely simplified.
In root, we define a list of projects in a projects.tf
file, and one of the blocks/modules looks like this:
module "example-project" {
name = "example-project"
source = "./project_aws"
stages = {
"dev" = "account-dev",
"prod" = "account-prod",
}
}
Then, in project_aws
we separate this into two new modules, one for dev
and one for prod
, which basically looks like below. Here you can see that account_role_arn_dev
and account_role_arn_prod
are dynamically assigned and sent to stage
module.
locals {
account_role_arns = {
"account-dev" = "role_arn"
"account-prod" = "role_arn"
"account-temp" = "role_arn"
}
account_role_arn_dev = contains(keys(var.stages), "dev") ? local.account_role_arns[var.stages["dev"]] : ""
account_role_arn_prod = contains(keys(var.stages), "prod") ? local.account_role_arns[var.stages["prod"]] : ""
}
module "prod" {
source = "./stage"
name = var.name
stage = "prod"
enabled = contains(keys(var.stages), "prod") ? true : false
account_role_arn = local.account_role_arn_prod
}
module "dev" {
source = "./stage"
name = var.name
stage = "dev"
enabled = contains(keys(var.stages), "dev") ? true : false
account_role_arn = local.account_role_arn_dev
}
In stage
module, we dynamically initiate provider (based on account_role_arn
) and create all the needed resources with this provider:
provider "aws" {
region = "eu-west-1"
assume_role {
role_arn = var.account_role_arn
}
}
Once again, where is the problem?
As mentioned at the beginning, this works, but problem appears when we want to remove module/project from the root. In that case we receive a Error: Provider configuration not present
which happens because we use dynamic providers and module is not able to detect which provider to use for destroying resources.
We want to put providers in root, but we also need them to be dynamic, we want to providers with alias from the root inside a module, but that is not doable.
Anyway - is there any other implementation that you suggest?
We wanted to have it more dynamically and avoid repeating the code, but we were not aware it will bring this kind of complications
Thanks in advance.