Merge pull request #24635 from hashicorp/pselle/docs-mod-count
Docs for count/for_each on modules
This commit is contained in:
commit
ab101f99df
|
@ -155,7 +155,7 @@ described in more detail in other sections:
|
||||||
If not specified, the child module inherits all of the default (un-aliased)
|
If not specified, the child module inherits all of the default (un-aliased)
|
||||||
provider configurations from the calling module.
|
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
|
`lifecycle` are not currently used by Terraform but are reserved for planned
|
||||||
future features.
|
future features.
|
||||||
|
|
||||||
|
@ -361,25 +361,23 @@ setting inside a `terraform` block.
|
||||||
|
|
||||||
## Multiple Instances of a Module
|
## 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
|
```hcl
|
||||||
# my_buckets.tf
|
# my_buckets.tf
|
||||||
|
module "bucket" {
|
||||||
module "assets_bucket" {
|
for_each = toset(["assets", "media"])
|
||||||
source = "./publish_bucket"
|
source = "./publish_bucket"
|
||||||
name = "assets"
|
name = "${each.key}_bucket"
|
||||||
}
|
|
||||||
|
|
||||||
module "media_bucket" {
|
|
||||||
source = "./publish_bucket"
|
|
||||||
name = "media"
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
# publish_bucket/bucket-and-cloudfront.tf
|
# publish_bucket/bucket-and-cloudfront.tf
|
||||||
|
|
||||||
variable "name" {} # this is the input parameter of the module
|
variable "name" {} # this is the input parameter of the module
|
||||||
|
|
||||||
resource "aws_s3_bucket" "example" {
|
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
|
wraps the bucket and all the other implementation details required to configure
|
||||||
a bucket.
|
a bucket.
|
||||||
|
|
||||||
We can then instantiate the module multiple times in our configuration by
|
We declare multiple module instances by using the `for_each` attribute,
|
||||||
giving each instance a unique name -- here `module "assets_bucket"` and
|
which accepts a map (with string keys) or a set of strings as its value. Additionally,
|
||||||
`module "media_bucket"` -- whilst specifying the same `source` value.
|
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>`
|
Resources from child modules are prefixed with `module.module_name[module index]`
|
||||||
when displayed in plan output and elsewhere in the UI. For example, the
|
when displayed in plan output and elsewhere in the UI. For a module with without
|
||||||
`./publish_bucket` module contains `aws_s3_bucket.example`, and so the two
|
`count` or `for_each`, the address will not contain the module index as the module's
|
||||||
instances of this module produce S3 bucket resources with [_resource addresses_](/docs/internals/resource-addressing.html)
|
name suffices to reference the module.
|
||||||
`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
|
In our example, the `./publish_bucket` module contains `aws_s3_bucket.example`, and so the two
|
||||||
line, but are not valid within interpolation expressions due to the
|
instances of this module produce S3 bucket resources with [resource addresses](/docs/internals/resource-addressing.html) of `module.bucket["assets"].aws_s3_bucket.example`
|
||||||
encapsulation behavior described above.
|
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
|
When refactoring an existing configuration to introduce modules, moving
|
||||||
resource blocks between modules causes Terraform to see the new location
|
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
|
after performing such actions to ensure that no resources are surprisingly
|
||||||
deleted.
|
deleted.
|
||||||
|
|
||||||
Each instance of a module may optionally have different providers passed to it
|
### Limitations when using module expansion
|
||||||
using the `providers` argument described above. This can be useful in situations
|
|
||||||
where, for example, a duplicated set of resources must be created across
|
Modules using `count` or `for_each` cannot pass different sets of providers to different instances.
|
||||||
several regions or datacenters.
|
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
|
## Tainting resources within a module
|
||||||
|
|
||||||
|
|
|
@ -16,19 +16,37 @@ larger infrastructure. An address is made up of two parts:
|
||||||
[module path][resource spec]
|
[module path][resource spec]
|
||||||
```
|
```
|
||||||
|
|
||||||
__Module path__:
|
## Module path
|
||||||
|
|
||||||
A module path addresses a module within the tree of modules. It takes the form:
|
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
|
* `module` - Module keyword indicating a child module (non-root). Multiple `module`
|
||||||
without a resource spec, the address applies to every resource within the
|
keywords in a path indicate nesting.
|
||||||
module. If the module path is omitted, this addresses the root module.
|
* `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:
|
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_type` - Type of the resource being addressed.
|
||||||
* `resource_name` - User-defined name of the resource.
|
* `resource_name` - User-defined name of the resource.
|
||||||
* `[resource index]` - an optional index into a resource with multiple
|
* `[resource index]` - (Optional) [Index](#index-values-for-modules-and-resources)
|
||||||
instances, surrounded by square brace characters (`[` and `]`).
|
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
|
-> 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
|
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
|
without a module path prefix will match resources with the same type and name
|
||||||
in any descendent module.
|
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
|
* `[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
|
instances specified by the `count` meta-argument. Omitting an index when
|
||||||
|
|
Loading…
Reference in New Issue