mirror of
https://github.com/opentffoundation/opentf.git
synced 2025-12-21 10:47:34 -05:00
212 lines
7.8 KiB
Plaintext
212 lines
7.8 KiB
Plaintext
---
|
|
description: >-
|
|
The providers meta-argument specifies which provider configurations from a
|
|
parent module are available in a child module.
|
|
---
|
|
|
|
# The Module `providers` Meta-Argument
|
|
|
|
In a [module call](../../language/modules/syntax.mdx) block, the
|
|
optional `providers` meta-argument specifies which
|
|
[provider configurations](../../language/providers/configuration.mdx) from the parent
|
|
module will be available inside the child module.
|
|
|
|
```hcl
|
|
# The default "aws" configuration is used for AWS resources in the root
|
|
# module where no explicit provider instance is selected.
|
|
provider "aws" {
|
|
region = "us-west-1"
|
|
}
|
|
|
|
# An alternate configuration is also defined for a different
|
|
# region, using the alias "usw2".
|
|
provider "aws" {
|
|
alias = "usw2"
|
|
region = "us-west-2"
|
|
}
|
|
|
|
# An example child module is instantiated with the alternate configuration,
|
|
# so any AWS resources it defines will use the us-west-2 region.
|
|
module "example" {
|
|
source = "./example"
|
|
providers = {
|
|
aws = aws.usw2
|
|
}
|
|
}
|
|
```
|
|
|
|
Each module in an OpenTofu configuration has its own separate namespace of
|
|
provider configurations, but a child module's namespace is populated with
|
|
configurations from the root module, either inheriting the default provider
|
|
configurations automatically or explicitly passing them from the parent
|
|
using the `providers` argument.
|
|
|
|
## Default Behavior: Inherit Default Providers
|
|
|
|
If the child module does not declare any [configuration aliases](../../language/modules/develop/providers.mdx#provider-aliases-within-modules),
|
|
the `providers` argument is optional. If you omit it, a child module inherits
|
|
all of the
|
|
[default provider configurations](../../language/providers/configuration.mdx#default-provider-configurations)
|
|
from its parent module. (Default provider configurations are any that don't
|
|
use the `alias` argument.)
|
|
|
|
If you specify a `providers` argument, it cancels this default behavior, and the
|
|
child module will only have access to the provider configurations you specify.
|
|
|
|
## Usage and Behavior
|
|
|
|
The `providers` argument uses a map-like syntax delimited by braces (`{`, `}`).
|
|
In the given mapping:
|
|
|
|
- The keys are the provider configuration addresses that will be used inside the
|
|
child module.
|
|
- The values are provider instance addresses from the parent module.
|
|
|
|
Both parts use
|
|
[provider instance reference syntax](../../language/providers/configuration.mdx#referring-to-provider-instances),
|
|
which for alternative provider configurations appears as `<PROVIDER NAME>.<ALIAS>`.
|
|
|
|
Within a child module, resources are assigned to provider configurations as
|
|
normal — either OpenTofu chooses a default based on the name of the resource
|
|
type, or the resource specifies an alternate configuration with the `provider`
|
|
argument. If the module receives a `providers` map when it's called, the
|
|
provider configuration names used within the module are effectively remapped to
|
|
refer the specified configurations from the parent module.
|
|
|
|
## When to Specify Providers
|
|
|
|
There are two main reasons to use the `providers` argument:
|
|
|
|
- Using different default provider configurations for a child module.
|
|
- Configuring a module that requires multiple configurations of the same provider.
|
|
|
|
### Changing Default Provider Configurations
|
|
|
|
Most re-usable modules only use default provider configurations, which they can
|
|
automatically inherit from their caller when `providers` is omitted.
|
|
|
|
However, in OpenTofu configurations that use multiple configurations of the
|
|
same provider, you might want some child modules to use the default provider
|
|
configuration and other ones to use an alternate. (This usually happens when
|
|
using one configuration to manage resources in multiple different regions of the
|
|
same cloud provider.)
|
|
|
|
By using the `providers` argument (like in the code example above), you can
|
|
accommodate this without needing to edit the child module. Although the code
|
|
within the child module always refers to the default provider configuration, the
|
|
actual configuration of that default can be different for each instance.
|
|
|
|
### Modules With Alternate Provider Configurations
|
|
|
|
In rare cases, a single re-usable module might require multiple configurations
|
|
of the same provider. For example, a module that configures connectivity between
|
|
networks in two AWS regions is likely to need both a source and a destination
|
|
region. In that case, the root module may look something like this:
|
|
|
|
```hcl
|
|
provider "aws" {
|
|
alias = "usw1"
|
|
region = "us-west-1"
|
|
}
|
|
|
|
provider "aws" {
|
|
alias = "usw2"
|
|
region = "us-west-2"
|
|
}
|
|
|
|
module "tunnel" {
|
|
source = "./tunnel"
|
|
providers = {
|
|
aws.src = aws.usw1
|
|
aws.dst = aws.usw2
|
|
}
|
|
}
|
|
```
|
|
|
|
Non-default provider configurations are never automatically inherited, so any
|
|
module that works like this will always need a `providers` argument. The
|
|
documentation for the module should specify all of the provider configuration
|
|
names it needs.
|
|
|
|
### Module instances with differing provider instances
|
|
|
|
When you write a `provider` block using
|
|
[the `for_each` meta-argument](../../language/providers/configuration.mdx#for_each-multiple-instances-of-a-provider-configuration)
|
|
the provider configuration dynamically declares zero or more provider instances.
|
|
|
|
If you also write a `module` block that uses `for_each` you can set its provider
|
|
configuration addresses to refer to dynamically-chosen instances of a multi-instance
|
|
provider configuration, which allows instantiating a module once per provider
|
|
instance.
|
|
|
|
For example, you might instantiate a module for each of a number of different AWS
|
|
regions, declaring foundational infrastructure across all of the regions you use,
|
|
with the module itself using only one default provider configuration that differs
|
|
for each module instance:
|
|
|
|
```hcl
|
|
variable "aws_regions" {
|
|
type = map(object({
|
|
vpc_cidr_block = string
|
|
}))
|
|
}
|
|
|
|
provider "aws" {
|
|
alias = "by_region"
|
|
for_each = var.aws_regions
|
|
|
|
region = each.key
|
|
}
|
|
|
|
module "per_region" {
|
|
source = "./per-region"
|
|
# This expression filters var.aws_regions to include only
|
|
# the elements whose value is not null. Refer to the
|
|
# warning in the text below for more information.
|
|
for_each = {
|
|
for region, config in var.aws_regions : region => config
|
|
if config != null
|
|
}
|
|
providers = {
|
|
aws = aws.by_region[each.key]
|
|
}
|
|
|
|
region_name = each.key
|
|
vpc_cidr_block = each.value.vpc_cidr_block
|
|
}
|
|
```
|
|
|
|
The module in `./per-region` should be written so that all of its AWS resources
|
|
are bound to that module's default configuration for the AWS provider. The
|
|
`providers` argument in the `module` block ensures that each instance of the
|
|
module has its default configuration for the AWS provider bound to a different
|
|
instance of `aws.by_region`.
|
|
|
|
All instances of the module must refer to instances of the same provider
|
|
configuration: only the expression in brackets (`each.key` in the above example)
|
|
can vary between the instances of the module.
|
|
|
|
:::warning
|
|
**The `for_each` expression for a module must *be different from* the
|
|
`for_each` expression for its associated provider configuration.**
|
|
|
|
OpenTofu uses a provider instance to plan and apply _all_ actions related
|
|
to a module instance, including destroying a module instance that
|
|
has been removed from the configuration.
|
|
|
|
Therefore a provider instance passed into a child module that will declare
|
|
resources associated with that provider instance must always remain in the
|
|
configuration for at least one more plan/apply round after the module instance
|
|
has been removed, or OpenTofu will fail to plan to destroy the resource instances
|
|
declared in the module.
|
|
|
|
You can find more information on this constraint in
|
|
[Referring to Provider Instances](../../language/providers/configuration.mdx#referring-to-provider-instances).
|
|
:::
|
|
|
|
## More Information for Module Developers
|
|
|
|
For more details and guidance about working with providers inside a re-usable
|
|
child module, see
|
|
[Module Development: Providers Within Modules](../../language/modules/develop/providers.mdx).
|