2

I am provisioning a bunch of resources via a module.

module "test" {
  source = "../modules/my-module"

  vpc_id = module.vpc.vpc_id

  subnet_ids = module.subnets.ids
}

Now, in the calling module ( the root module ), I use the alias of the provider that the child module should use. I would use the module providers meta-argument :

provider "my_provider" {
  alias = default

  region = "default"
  ...
}

provider "my_provider" {
  alias = alias1

  region = "region1"
  ...
}

module "test" {
  source = "../modules/my-module"

  providers = {
    my_provider = my_provider.alias1
  }

  vpc_id = module.vpc.vpc_id

  subnet_ids = module.subnets.ids
}

Now, I want to provision the same module, but based on a condition :

module "test" {
  source = "../modules/my-module"

  providers = {
    my_provider = var.region == "region1" ? my_provider.alias1 : my_provider.default
  }

  vpc_id = module.vpc.vpc_id

  subnet_ids = module.subnets.ids
}

And I get thrown The providers argument requires a provider type name, optionally followed by a period and then a configuration alias.

Then I tried treating the providers meta-argument as a normal argument ( I knew it would not work, but still tried anyway ) :

module "test" {
  source = "../modules/my-module"

  providers = var.region == "region1" ? { my_provider = my_provider.alias1 } : { my_provider = my_provider.default }

  vpc_id = module.vpc.vpc_id

  subnet_ids = module.subnets.ids
}

This time, the error was more logical - A static map expression is required.


It does seem like the providers meta-argument for modules are always supposed to be static ( essentially hard-coded ) just like the backend argument.

Would there be a native way of re-using the same module declaration to switch between 2 different providers?

Or is the only way to achieve this would be code duplication and the count meta-argument based on the condition?

1 Answer 1

2

The relationship between a resource and its provider configuration is an important part of building the dependency graph, and Terraform must build the dependency graph before it can evaluate any expressions, so there is no way to use arbitrary expressions to describe the relationship between a resource and its provider configuration.

The providers argument in a module block isn't directly specifying the relationship between the resource and its provider configuration, but it is still data used by the algorithm that ultimately resolves those connections and so it too needs to be resolved before it's possible to evaluate expressions.

Although you cannot dynamically choose which provider configuration to assign to a resource, you can make the provider configuration itself include dynamic expressions:

provider "my_provider" {
  alias = "for_test_module"

  region = var.region == "region1" ? "region1" : "default"
}

module "test" {
  source = "../modules/my-module"
  providers = {
    my_provider = my_provider.for_test_module
  }

  vpc_id     = module.vpc.vpc_id
  subnet_ids = module.subnets.ids
}

In this example the module is always associated with the same provider configuration object but the arguments inside that block will vary depending on the value of var.region, thereby achieving the same effect.

1
  • Thank you for the answer. It gives a sense of how the providers meta-argument fits in the module 'call-stack'. Also, thank you for the workaround that provides the same effect.
    – shine
    Jan 24, 2023 at 4:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.