website: further copyediting for "Providers within Modules"

The differences between the implicit and explicit modes of passing
provider configurations between modules are significant enough to warrant
giving these approaches different names and describing them separately.

This also includes documentation of the current limitation discussed in
#16612, where explicit passing requires a proxy configuration block even
for a _default_ provider configuration, because that limitation is being
accepted for the 0.11.0 release to limit scope.
This commit is contained in:
Martin Atkins 2017-11-09 16:18:27 -08:00
parent 2889eded3f
commit 1da2464e72
1 changed files with 97 additions and 37 deletions

View File

@ -147,16 +147,86 @@ than waiting for the entire module to be complete before proceeding.
## Providers within Modules ## Providers within Modules
For convenience in simple configurations, child modules automatically inherit In a configuration with multiple modules, there are some special considerations
default (un-aliased) provider configurations from their parent. This means that for how resources are associated with provider configurations.
in most cases only the root module needs explicit `provider` blocks, and then
any defined provider can be freely used with the same settings in child modules.
In more complex situations it may be necessary for a child module to use While in principle `provider` blocks can appear in any module, it is recommended
different provider settings than its parent. In this situation it is that they be placed only in the _root_ module of a configuration, since this
possible to define approach allows users to configure providers just once and re-use them across
[multiple provider instances](/docs/configuration/providers.html#multiple-provider-instances) all descendent modules.
and pass them explicitly and selectively to a child module:
Each resource in the configuration must be associated with one provider
configuration, which may either be within the same module as the resource
or be passed from the parent module. Providers can be passed down to descendent
modules in two ways: either _implicitly_ through inheritance, or _explicitly_
via the `providers` argument within a `module` block. These two options are
discussed in more detail in the following sections.
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.
Provider configurations are used for all operations on associated resources,
including destroying remote objects and refreshing state. Terraform retains, as
part of its state, a reference to the provider configuration that was most
recently used to apply changes to each resource. When a `resource` block is
removed from the configuration, this record in the state is used to locate the
appropriate configuration because the resource's `provider` argument (if any)
is no longer present in the configuration.
As a consequence, it is required that all resources created for a particular
provider configuration must be destroyed before that provider configuration is
removed, unless the related resources are re-configured to use a different
provider configuration first.
### Implicit Provider Inheritance
For convenience in simple configurations, a child module automatically inherits
default (un-aliased) provider configurations from its parent. This means that
explicit `provider` blocks appear only in the root module, and downstream
modules can simply declare resources for that provider and have them
automatically associated with the root provider configurations.
For example, the root module might contain only a `provider` block and a
`module` block to instantiate a child module:
```hcl
provider "aws" {
region = "us-west-1"
}
module "child" {
source = "./child"
}
```
The child module can then use any resource from this provider with no further
provider configuration required:
```hcl
resource "aws_s3_bucket" "example" {
bucket = "provider-inherit-example"
}
```
This approach is recommended in the common case where only a single
configuration is needed for each provider across the entire configuration.
In more complex situations there may be [multiple provider instances](/docs/configuration/providers.html#multiple-provider-instances),
or a child module may need to use different provider settings than
its parent. For such situations, it's necessary to pass providers explicitly
as we will see in the next section.
## Passing Providers Explicitly
When child modules each need a different configuration of a particular
provider, or where the child module requires a different provider configuration
than its parent, the `providers` argument within a `module` block can be
used to define explicitly which provider configs are made available to the
child module. For example:
```hcl ```hcl
# The default "aws" configuration is used for AWS resources in the root # The default "aws" configuration is used for AWS resources in the root
@ -182,16 +252,16 @@ module "example" {
} }
``` ```
The `providers` argument within a `module` block serves the same purpose as The `providers` argument within a `module` block is similar to
the `provider` argument within a resource as described for the `provider` argument within a resource as described for
[multiple provider instances](/docs/configuration/providers.html#multiple-provider-instances), [multiple provider instances](/docs/configuration/providers.html#multiple-provider-instances),
but is a map rather than a single string because a module may contain resources but is a map rather than a single string because a module may contain resources
from many different providers. from many different providers.
Once the `providers` argument is used in a `module` block it overrides all of Once the `providers` argument is used in a `module` block, it overrides all of
the default inheritance behavior, so it is necessary to enumerate mappings the default inheritance behavior, so it is necessary to enumerate mappings
for _all_ of the required providers. This is to avoid confusion and surprises for _all_ of the required providers. This is to avoid confusion and surprises
when mixing both implicit and explicit provider passing. that may result when mixing both implicit and explicit provider passing.
Additional provider configurations (those with the `alias` argument set) are Additional provider configurations (those with the `alias` argument set) are
_never_ inherited automatically by child modules, and so must always be passed _never_ inherited automatically by child modules, and so must always be passed
@ -223,11 +293,11 @@ module "tunnel" {
In the `providers` map, the keys are provider names as expected by the child In the `providers` map, the keys are provider names as expected by the child
module, while the values are the names of corresponding configurations in module, while the values are the names of corresponding configurations in
the _current_ module. The subdirectory `./tunnel` must then contain the _current_ module. The subdirectory `./tunnel` must then contain
`alias`-only configuration blocks like the following, to declare that it _proxy configuration blocks_ like the following, to declare that it
requires these names to be passed from a `providers` block in the parent's requires configurations to be passed with these from the `providers` block in
`module` block: the parent's `module` block:
``` ```hcl
provider "aws" { provider "aws" {
alias = "src" alias = "src"
} }
@ -240,29 +310,19 @@ provider "aws" {
Each resource should then have its own `provider` attribute set to either Each resource should then have its own `provider` attribute set to either
`"aws.src"` or `"aws.dst"` to choose which of the two provider instances to use. `"aws.src"` or `"aws.dst"` to choose which of the two provider instances to use.
It is recommended to use the default inheritance behavior in most cases where At this time it is required to write an explicit proxy configuration block
only a single default instance of each provider is used, and switch to even for default (un-aliased) provider configurations when they will be passed
passing providers explicitly only if multiple instances are needed. via an explicit `providers` block:
In all cases it is recommended to keep explicit provider configurations only in ```hcl
the root module and pass them (either implicitly or explicitly) down to provider "aws" {
descendent modules. This avoids the provider configurations being "lost" }
when descendent providers 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.
Provider configurations are used for all operations on resources, including If such a block is not present, the child module will behave as if it has no
destroying remote objects and refreshing state. Terraform retains, as part of configurations of this type at all, which may cause input prompts to supply
its state, a reference to the provider configuration that was most recently any required provider configuration arguments. This limitation will be
used to apply changes to each resource. When a resource is removed from the addressed in a future version of Terraform.
configuration, this record in state is used to locate the appropriate
configuration because the resource's `provider` argument is no longer present
in the configuration.
As a consequence, it is required that all resources created for a particular
provider configuration must be destroyed before that provider configuration is
removed, unless the related resources are re-configured to use a different
provider configuration first.
## Multiple Instances of a Module ## Multiple Instances of a Module