<p>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.</p>
<p>The <code>providers</code> argument in a <code>module</code> block isn't <em>directly</em> 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.</p>
<p>Although you cannot dynamically choose which provider configuration to assign to a resource, you <em>can</em> make the provider configuration itself include dynamic expressions:</p>
<pre><code>provider &quot;my_provider&quot; {
  alias = &quot;for_test_module&quot;

  region = var.region == &quot;region1&quot; ? &quot;region1&quot; : &quot;default&quot;
}

module &quot;test&quot; {
  source = &quot;../modules/my-module&quot;
  providers = {
    my_provider = my_provider.for_test_module
  }

  vpc_id     = module.vpc.vpc_id
  subnet_ids = module.subnets.ids
}
</code></pre>
<p>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 <code>var.region</code>, thereby achieving the same effect.</p>

CC BY-SA 4.0
2023-01-24T04:36:03.123Z
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
CC BY-SA 4.0
2023-01-24T00:59:52.750Z
2023-01-24T00:59:52.750Z
Martin Atkins
<p>I am provisioning a bunch of resources via a module.</p>
<pre><code>module &quot;test&quot; {
  source = &quot;../modules/my-module&quot;

  vpc_id = module.vpc.vpc_id

  subnet_ids = module.subnets.ids
}
</code></pre>
<p>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 <a href="https://developer.hashicorp.com/terraform/language/meta-arguments/module-providers" rel="nofollow noreferrer">module <code>providers</code> meta-argument</a> :</p>
<pre><code>provider &quot;my_provider&quot; {
  alias = default

  region = &quot;default&quot;
  ...
}

provider &quot;my_provider&quot; {
  alias = alias1

  region = &quot;region1&quot;
  ...
}

module &quot;test&quot; {
  source = &quot;../modules/my-module&quot;

  providers = {
    my_provider = my_provider.alias1
  }

  vpc_id = module.vpc.vpc_id

  subnet_ids = module.subnets.ids
}
</code></pre>
<p>Now, I want to provision the same module, but based on a condition :</p>
<pre><code>module &quot;test&quot; {
  source = &quot;../modules/my-module&quot;

  providers = {
    my_provider = var.region == &quot;region1&quot; ? my_provider.alias1 : my_provider.default
  }

  vpc_id = module.vpc.vpc_id

  subnet_ids = module.subnets.ids
}
</code></pre>
<p>And I get thrown <code>The providers argument requires a provider type name, optionally followed by a period and then a configuration alias.</code></p>
<p>Then I tried treating the providers meta-argument as a normal argument ( I knew it would not work, but still tried anyway ) :</p>
<pre><code>module &quot;test&quot; {
  source = &quot;../modules/my-module&quot;

  providers = var.region == &quot;region1&quot; ? { my_provider = my_provider.alias1 } : { my_provider = my_provider.default }

  vpc_id = module.vpc.vpc_id

  subnet_ids = module.subnets.ids
}
</code></pre>
<p>This time, the error was more logical - <code>A static map expression is required.</code></p>
<hr />
<p>It does seem like the <code>providers</code> meta-argument for modules are always supposed to be static ( essentially hard-coded ) just like the <code>backend</code> argument.</p>
<p>Would there be a native way of re-using the same module declaration to switch between 2 different providers?</p>
<p>Or is the only way to achieve this would be code duplication and the <code>count</code> meta-argument based on the condition?</p>

<terraform><terraform-module>
conditionals in module providers meta-argument
shine
# conditionals in module providers meta-argument

(Asked by: username_0 on 2023-01-23)

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?

**Tags:** terraform, terraform-module


---

## 1 answers

### Answer by username_1 on 2023-01-24. Score: 2 | Accepted answer

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.

> **Comments:**
> **username_0**: 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.  

---

