Hi @woter324,
In Terraform provider configurations are a special kind of object that, unlike all other kinds of object in Terraform, can automatically propagate between module boundaries so that things are simpler in the common case where there’s only one configuration for each provider.
However, that does mean that when things get more complicated – like in your case, where you have multiple provider configurations – the syntax for talking about provider configurations is quite different than the syntax for passing “normal” values between modules.
I’m making some guesses because you’ve only shared a tiny fragment of your configuration, but my assumption is that you’ve written a shared module which is designed to work with a single provider but then you’ve called it multiple times from your root module and want to pass a different provider configuration to each instance.
It is possible to write a configuration structured in that way. There are two parts to it: writing the shared module, and then writing the calls to that module.
Writing the shared module
If each instance of your shared module only works with one provider configuration at a time then this part is relatively “normal”: you can just write it to assume that a default (unaliased) configuration of hashicorp/azurerm
will be provided by the caller of the module.
That means that you’d omit any provider
arguments inside all of your resource
blocks. As far as this module is concerned, you’re using the default (unaliased) configuration, which is the default behavior.
Writing the calling module
The module which calls the shared module is the one that must deal with the additional complexity of there being multiple configurations of the same provider.
Assuming that the module is being called from the root module, the root module has two responsibilities:
- To declare each of the multiple aliased provider configurations.
- To pass the appropriate aliased configuration as the default configuration for each instance of the module.
Here’s a concrete example of that:
provider "azurerm" {
alias = "a"
# ...
}
provider "azurerm" {
alias = "b"
# ...
}
module "example_a" {
# This should be the "shared module" discussed
# in the previous section.
source = "../modules/example"
providers = {
azurerm = azurerm.a
}
# (any normal variable definitions here)
}
module "example_b" {
# This should be the "shared module" discussed
# in the previous section.
source = "../modules/example"
providers = {
azurerm = azurerm.b
}
# (any normal variable definitions here)
}
The above declares that the root module has two non-default (aliased) configurations for the provider, named azurerm.a
and azurerm.b
.
It then makes two calls to the shared module discussed in the previous section. That module expects to be provided a default (unaliased) configuration for the provider, so you’d use the providers
argument to explain to Terraform how to populate the child module’s namespace of provider configurations based on what’s available in the calling module.
The providers
argument in a module
block is the same idea as the provider
argument in a resource
block, but it chooses the entire table of provider configurations available to the child module rather than just a single provider.
providers = {
azurerm = azurerm.a
}
The above example means “the default configuration for azurerm
in the child module is the same as the azurerm.a
configuration in this module”. The child module can then just use the default provider assignment behavior without any special additional arguments.