Answers: <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>
  
Answers: CC BY-SA 4.0
Answers: 2023-01-24T04:36:03.123Z
Answers: 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.
Answers: shine
Answers: CC BY-SA 4.0
Answers: 2023-01-24T00:59:52.750Z
Answers: 2023-01-24T00:59:52.750Z
Answers: Martin Atkins
Body: <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>
  
Tags: <terraform><terraform-module>
Title: conditionals in module providers meta-argument
UserDisplayName: shine
ThreadText: # 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](https://developer.hashicorp.com/terraform/language/meta-arguments/module-providers) :
  
  ```
  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.  
  
  ---
  
  