Merge pull request #24635 from hashicorp/pselle/docs-mod-count

Docs for count/for_each on modules
This commit is contained in:
Pam Selle 2020-04-13 18:39:59 -04:00 committed by GitHub
commit ab101f99df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 113 additions and 36 deletions

View File

@ -155,7 +155,7 @@ described in more detail in other sections:
If not specified, the child module inherits all of the default (un-aliased)
provider configurations from the calling module.
In addition to the above, the argument names `count`, `for_each` and
In addition to the above, the argument names `depends_on` and
`lifecycle` are not currently used by Terraform but are reserved for planned
future features.
@ -361,25 +361,23 @@ setting inside a `terraform` block.
## Multiple Instances of a Module
A particular module source can be instantiated multiple times:
Use the `count` or `for_each` arguments to create multiple instances of a module.
These arguments have the same syntax and type constraints as
[`count`](./resources.html#count-multiple-resource-instances-by-count) and
[`for_each`](./resources.html#for_each-multiple-resource-instances-defined-by-a-map-or-set-of-strings)
as defined for managed resources.
```hcl
# my_buckets.tf
module "assets_bucket" {
source = "./publish_bucket"
name = "assets"
}
module "media_bucket" {
source = "./publish_bucket"
name = "media"
module "bucket" {
for_each = toset(["assets", "media"])
source = "./publish_bucket"
name = "${each.key}_bucket"
}
```
```hcl
# publish_bucket/bucket-and-cloudfront.tf
variable "name" {} # this is the input parameter of the module
resource "aws_s3_bucket" "example" {
@ -396,18 +394,23 @@ subdirectory. That module has configuration to create an S3 bucket. The module
wraps the bucket and all the other implementation details required to configure
a bucket.
We can then instantiate the module multiple times in our configuration by
giving each instance a unique name -- here `module "assets_bucket"` and
`module "media_bucket"` -- whilst specifying the same `source` value.
We declare multiple module instances by using the `for_each` attribute,
which accepts a map (with string keys) or a set of strings as its value. Additionally,
we use the `each.key` in our module block, because the
[`each`](/docs/configuration/resources.html#the-each-object) object is available when
we have declared `for_each` on the module block. When using the `count` argument, the
[`count`](/docs/configuration/resources.html#the-count-object) object is available.
Resources from child modules are prefixed with `module.<module-instance-name>`
when displayed in plan output and elsewhere in the UI. For example, the
`./publish_bucket` module contains `aws_s3_bucket.example`, and so the two
instances of this module produce S3 bucket resources with [_resource addresses_](/docs/internals/resource-addressing.html)
`module.assets_bucket.aws_s3_bucket.example` and `module.media_bucket.aws_s3_bucket.example`
respectively. These full addresses are used within the UI and on the command
line, but are not valid within interpolation expressions due to the
encapsulation behavior described above.
Resources from child modules are prefixed with `module.module_name[module index]`
when displayed in plan output and elsewhere in the UI. For a module with without
`count` or `for_each`, the address will not contain the module index as the module's
name suffices to reference the module.
In our example, the `./publish_bucket` module contains `aws_s3_bucket.example`, and so the two
instances of this module produce S3 bucket resources with [resource addresses](/docs/internals/resource-addressing.html) of `module.bucket["assets"].aws_s3_bucket.example`
and `module.bucket["media"].aws_s3_bucket.example` respectively. These full addresses
are used within the UI and on the command line, but only [outputs](docs/configuration/outputs.html)
from a module can be referenced from elsewhere in your configuration.
When refactoring an existing configuration to introduce modules, moving
resource blocks between modules causes Terraform to see the new location
@ -415,10 +418,64 @@ as an entirely separate resource to the old. Always check the execution plan
after performing such actions to ensure that no resources are surprisingly
deleted.
Each instance of a module may optionally have different providers passed to it
using the `providers` argument described above. This can be useful in situations
where, for example, a duplicated set of resources must be created across
several regions or datacenters.
### Limitations when using module expansion
Modules using `count` or `for_each` cannot pass different sets of providers to different instances.
This is because when a module instance is destroyed (such as a key-value being removed from the
`for_each` map), the provider must be available in order to perform the destroy. You can pass
different sets of providers by using multiple `module` blocks:
```
# my_buckets.tf
provider "aws" {
alias = "usw1"
region = "us-west-1"
}
provider "aws" {
alias = "usw2"
region = "us-west-2"
}
provider "google" {
alias = "usw1"
credentials = "${file("account.json")}"
project = "my-project-id"
region = "us-west1"
zone = "us-west1-a"
}
provider "google" {
alias = "usw2"
credentials = "${file("account.json")}"
project = "my-project-id"
region = "us-west2"
zone = "us-west2-a"
}
module "bucket_w1" {
source = "./publish_bucket"
providers = {
aws.src = "aws.usw1"
google.src = "google.usw2"
}
}
module "bucket_w2" {
source = "./publish_bucket"
providers = {
aws.src = "aws.usw2"
google.src = "google.usw2"
}
}
```
Each module block may optionally have different providers passed to it
using the [`providers`](/docs/configuration/modules.html#passing-providers-explicitly)
argument. This can be useful in situations where, for example, a duplicated set of
resources must be created across several regions or datacenters.
## Tainting resources within a module

View File

@ -16,19 +16,37 @@ larger infrastructure. An address is made up of two parts:
[module path][resource spec]
```
__Module path__:
## Module path
A module path addresses a module within the tree of modules. It takes the form:
```
module.A.module.B.module.C...
module.module_name[module index]
```
Multiple modules in a path indicate nesting. If a module path is specified
without a resource spec, the address applies to every resource within the
module. If the module path is omitted, this addresses the root module.
* `module` - Module keyword indicating a child module (non-root). Multiple `module`
keywords in a path indicate nesting.
* `module_name` - User-defined name of the module.
* `[module index]` - (Optional) [Index](#index-values-for-modules-and-resources) into a
module with multiple instances, surrounded by square brace characters (`[` and `]`).
__Resource spec__:
An address without a resource spec, i.e. `module.foo` applies to every resource within
the module if a single module, or all instances of a module if a module has multiple instances.
To address all resources of a particular module instance, include the module index in the address,
such as `module.foo[0]`.
If the module path is omitted, the address applies to the root module.
An example of the `module` keyword delineating between two modules that have multiple instances:
```
module.foo[0].module.bar["a"]
```
-> Module index only applies to modules in Terraform v0.13 or later, as in earlier
versions of Terraform, a module could not have multiple instances.
## Resource spec
A resource spec addresses a specific resource in the config. It takes the form:
@ -38,15 +56,17 @@ resource_type.resource_name[resource index]
* `resource_type` - Type of the resource being addressed.
* `resource_name` - User-defined name of the resource.
* `[resource index]` - an optional index into a resource with multiple
instances, surrounded by square brace characters (`[` and `]`).
* `[resource index]` - (Optional) [Index](#index-values-for-modules-and-resources)
into a resource with multiple instances, surrounded by square brace characters (`[` and `]`).
-> In Terraform v0.12 and later, a resource spec without a module path prefix
matches only resources in the root module. In earlier versions, a resource spec
without a module path prefix will match resources with the same type and name
in any descendent module.
__Resource index__:
## Index values for Modules and Resources
The following specifications apply to index values on modules and resources with multiple instances:
* `[N]` where `N` is a `0`-based numerical index into a resource with multiple
instances specified by the `count` meta-argument. Omitting an index when