Hi @linuxbsdfreak,
Terraform 0.11 introduced the concept of passing providers explicitly to child modules as a way to support different modules using different provider configurations without each module declaring its own provider
blocks.
We did this in order to address the long-standing problem that when you have a provider configuration in a child module and you remove that child module from your configuration you would be simultaneously removing both the resources in that module and the provider configurations necessary to destroy the remote objects associated with those resources, creating a situation where removing the module from configuration is impossible without unusual interventions such as manually editing state snapshots.
As part of the Terraform 0.11 release we updated the documentation to describe provider configurations in child modules as not recommended and to show the newer patterns. This documentation was revised for Terraform 0.12 as part of a general revamp of the documentation in light of the language changes in that release, but the substance of the advice remained the same:
In all cases it is recommended to keep explicit provider configurations only in the root module and pass them (whether implicitly or explicitly) down to descendent modules. This avoids the provider configurations from being “lost” when descendent modules are removed from the configuration. It also allows the user of a configuration to determine which providers require credentials by inspecting only the root module.
Terraform 0.13 is taking the deprecation of provider configurations in nested modules further by disallowing them altogether when used with the new module for_each
, count
and depends_on
mechanisms, because using those creates additional situations where changes to configuration can become blocked due to the dependencies between resources and their providers. Using provider
blocks in nested modules remains valid for modules not using those features in the interests of backward compatibility with existing configurations, but the recommendation against that still stands.
I don’t know the details of your use-case, so I can’t really offer more specific advice than this, except to say that the providers
argument that the error message is referring to is what’s described under Passing Providers Explicitly.
I think the main design decision you’ll need to make here is how many provider configurations for each distinct provider your “flux” module will need.
If it needs only one configuration for kubernetes
and one for helm
then you can choose to use default (unaliased) provider configurations for both by moving the two provider
blocks from the child module into the root module, removing the provider = kubernetes.shootconfig
arguments in resources, and then passing the two providers to the flux module in the calling module
block like this:
module "flux" {
source = "./modules/flux"
providers = {
helm = helm
kubernetes = kubernetes.shootconfig
}
# ...
}
The providers
block above means that inside this module the default kubernetes
provider configuration is an alias for the root module’s kubernetes.shootconfig
, and the default helm
provider configuration is an alias for the root module’s default helm
configuration. This providers
argument is the module block equivalent of provider
in a resource
block, and it’s a mapping rather than a single reference because modules can use multiple provider configurations while resources always use exactly one.
If your flux
module actually needs two kubernetes
provider configurations (you showned only one here, but I expect you wouldn’t have set alias = "shootconfig"
if there wasn’t also a default kubernetes
configuration in that module), then you can pass in both a default and an additional (aliased) configuration by assigning both in the providers
argument:
providers = {
helm = helm
kubernetes = kubernetes
kubernetes.shootconfig = kubernetes.shootconfig
}
However, the above won’t be allowed unless the child module declares that it is expecting to receive an additional kubernetes
provider configuration called “shootconfig”, so in this case the module must include what the documentation calls a “proxy provider configuration”, which is a placeholder for a configuration that will be populated by the calling module:
# This block _does_ go in the child module,
# and is a proxy configuration because it
# contains only `alias` and no other arguments.
provider "kubernetes" {
alias = "shootconfig"
}
Once your shared module contains either no provider
blocks or only “proxy” provider
blocks, you should no longer see the error message you mentioned.