Skip to content

Provider Aliases Interact Poorly with Reusable Modules #1819

Closed
@apparentlymart

Description

@apparentlymart

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.)

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions