Description
Recently support was added for having multiple instances of a given provider with different settings, using the alias
attribute:
provider "aws" {
region = "us-east-2"
alias = "use2"
}
provider "aws" {
region = "us-west-1"
alias = "usw1"
}
resource "aws_something" "foo" {
provider = "aws.use2"
}
resource "aws_something" "bar" {
provider = "aws.usw1"
}
This is very useful for defining multi-region infrastructures, but several unfortunate interactions make this difficult to use in conjunction with reusable modules.
Child modules inherit the providers defined in the root module, but when aliases are in play it's necessary to explicitly specify the provider
on each resource, even when those resources are defined in a module. This is problematic when trying to write a generic module that can be used in multiple contexts, since it needs to "know" the appropriate provider string.
My first thought was to pass the alias into the child module as a variable, but it looks like interpolations are not supported on the provider
attribute.
It feels like fixing this could go in two directions:
- Require each module to define its own providers, rather than inheriting from the root, and have a separate provider alias namespace per module. This allows the modules to be fully encapsulated, but would require many modules to take provider parameters as input variables.
- Allow the
provider
resource attribute to be interpolated, and consider the empty string to be the same as not providing it at all so that there is a way to select the "default" provider of that type. This would still require extra parameters as module input variables, but the parameters would be provider alias names rather than provider parameters directly.
For the sorts of use-cases I've encountered, I prefer the former option. It more cleanly encapsulates module behavior, reduces the need to duplicate the provider
attribute across many resources, and forces a reusable module to be clearer in its interface (via its input variables) which providers it will interact with. However, I could also make the latter work. I'm sure other compromises are possible too.
With the current setup I've been unable to make use of provider aliases at all, and I've been forced to use a separate config per region with a helper module that consumes their states via the terraform_remote_state
resource and exposes the variables in a single spot. (My use case: a reusable module which creates an AWS route table that needs to be duplicated in each region.)