website: Break up Resources page into smaller chunks
- Resource behavior gets its own page. - Meta-arguments all get their own pages. - Stuff about resource syntax itself gets a page. In the process of breaking the meta-arguments out into their own pages, I revised them (with the exception of `provider`) so that they apply to both resources and modules. Like with Expressions, this commit repurposes the old resources.html URL as a landing page for old links.
This commit is contained in:
parent
a446ecb7b7
commit
6e2f5eb0be
|
@ -0,0 +1,107 @@
|
||||||
|
---
|
||||||
|
layout: "language"
|
||||||
|
page_title: "Resource Behavior - Configuration Language"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Resource Behavior
|
||||||
|
|
||||||
|
A `resource` block declares that you want a particular infrastructure object
|
||||||
|
to exist with the given settings. If you are writing a new configuration for
|
||||||
|
the first time, the resources it defines will exist _only_ in the configuration,
|
||||||
|
and will not yet represent real infrastructure objects in the target platform.
|
||||||
|
|
||||||
|
_Applying_ a Terraform configuration is the process of creating, updating,
|
||||||
|
and destroying real infrastructure objects in order to make their settings
|
||||||
|
match the configuration.
|
||||||
|
|
||||||
|
## How Terraform Applies a Configuration
|
||||||
|
|
||||||
|
When Terraform creates a new infrastructure object represented by a `resource`
|
||||||
|
block, the identifier for that real object is saved in Terraform's
|
||||||
|
[state](/docs/state/index.html), allowing it to be updated and destroyed
|
||||||
|
in response to future changes. For resource blocks that already have an
|
||||||
|
associated infrastructure object in the state, Terraform compares the
|
||||||
|
actual configuration of the object with the arguments given in the
|
||||||
|
configuration and, if necessary, updates the object to match the configuration.
|
||||||
|
|
||||||
|
In summary, applying a Terraform configuration will:
|
||||||
|
|
||||||
|
- _Create_ resources that exist in the configuration but are not associated with a real infrastructure object in the state.
|
||||||
|
- _Destroy_ resources that exist in the state but no longer exist in the configuration.
|
||||||
|
- _Update in-place_ resources whose arguments have changed.
|
||||||
|
- _Destroy and re-create_ resources whose arguments have changed but which cannot be updated in-place due to remote API limitations.
|
||||||
|
|
||||||
|
This general behavior applies for all resources, regardless of type. The
|
||||||
|
details of what it means to create, update, or destroy a resource are different
|
||||||
|
for each resource type, but this standard set of verbs is common across them
|
||||||
|
all.
|
||||||
|
|
||||||
|
The meta-arguments within `resource` blocks, documented in the
|
||||||
|
sections below, allow some details of this standard resource behavior to be
|
||||||
|
customized on a per-resource basis.
|
||||||
|
|
||||||
|
## Accessing Resource Attributes
|
||||||
|
|
||||||
|
[Expressions](/docs/configuration/expressions/index.html) within a Terraform module can access
|
||||||
|
information about resources in the same module, and you can use that information
|
||||||
|
to help configure other resources. Use the `<RESOURCE TYPE>.<NAME>.<ATTRIBUTE>`
|
||||||
|
syntax to reference a resource attribute in an expression.
|
||||||
|
|
||||||
|
In addition to arguments specified in the configuration, resources often provide
|
||||||
|
read-only attributes with information obtained from the remote API; this often
|
||||||
|
includes things that can't be known until the resource is created, like the
|
||||||
|
resource's unique random ID.
|
||||||
|
|
||||||
|
Many providers also include [data sources](./data-sources.html), which are a
|
||||||
|
special type of resource used only for looking up information.
|
||||||
|
|
||||||
|
For a list of the attributes a resource or data source type provides, consult
|
||||||
|
its documentation; these are generally included in a second list below its list
|
||||||
|
of configurable arguments.
|
||||||
|
|
||||||
|
For more information about referencing resource attributes in expressions, see
|
||||||
|
[Expressions: References to Resource Attributes](/docs/configuration/expressions/references.html#references-to-resource-attributes).
|
||||||
|
|
||||||
|
## Resource Dependencies
|
||||||
|
|
||||||
|
Most resources in a configuration don't have any particular relationship, and
|
||||||
|
Terraform can make changes to several unrelated resources in parallel.
|
||||||
|
|
||||||
|
However, some resources must be processed after other specific resources;
|
||||||
|
sometimes this is because of how the resource works, and sometimes the
|
||||||
|
resource's configuration just requires information generated by another
|
||||||
|
resource.
|
||||||
|
|
||||||
|
Most resource dependencies are handled automatically. Terraform analyses any
|
||||||
|
[expressions](/docs/configuration/expressions/index.html) within a `resource` block to find references
|
||||||
|
to other objects, and treats those references as implicit ordering requirements
|
||||||
|
when creating, updating, or destroying resources. Since most resources with
|
||||||
|
behavioral dependencies on other resources also refer to those resources' data,
|
||||||
|
it's usually not necessary to manually specify dependencies between resources.
|
||||||
|
|
||||||
|
However, some dependencies cannot be recognized implicitly in configuration. For
|
||||||
|
example, if Terraform must manage access control policies _and_ take actions
|
||||||
|
that require those policies to be present, there is a hidden dependency between
|
||||||
|
the access policy and a resource whose creation depends on it. In these rare
|
||||||
|
cases, [the `depends_on` meta-argument](./depends_on.html) can explicitly specify a
|
||||||
|
dependency.
|
||||||
|
|
||||||
|
## Local-only Resources
|
||||||
|
|
||||||
|
While most resource types correspond to an infrastructure object type that
|
||||||
|
is managed via a remote network API, there are certain specialized resource
|
||||||
|
types that operate only within Terraform itself, calculating some results and
|
||||||
|
saving those results in the state for future use.
|
||||||
|
|
||||||
|
For example, local-only resource types exist for
|
||||||
|
[generating private keys](/docs/providers/tls/r/private_key.html),
|
||||||
|
[issuing self-signed TLS certificates](/docs/providers/tls/r/self_signed_cert.html),
|
||||||
|
and even [generating random ids](/docs/providers/random/r/id.html).
|
||||||
|
While these resource types often have a more marginal purpose than those
|
||||||
|
managing "real" infrastructure objects, they can be useful as glue to help
|
||||||
|
connect together other resources.
|
||||||
|
|
||||||
|
The behavior of local-only resources is the same as all other resources, but
|
||||||
|
their result data exists only within the Terraform state. "Destroying" such
|
||||||
|
a resource means only to remove it from the state, discarding its data.
|
||||||
|
|
|
@ -12,8 +12,21 @@ Each resource block describes one or more infrastructure objects, such
|
||||||
as virtual networks, compute instances, or higher-level components such
|
as virtual networks, compute instances, or higher-level components such
|
||||||
as DNS records.
|
as DNS records.
|
||||||
|
|
||||||
- [Resource Blocks](/docs/configuration/resources.html) documents how to declare
|
- [Resource Blocks](/docs/configuration/blocks/resources/syntax.html) documents
|
||||||
resources, including information about meta-arguments like `for_each`.
|
the syntax for declaring resources.
|
||||||
|
|
||||||
|
- [Resource Behavior](/docs/configuration/resources/behavior.html) explains in
|
||||||
|
more detail how Terraform handles resource declarations when applying a
|
||||||
|
configuration.
|
||||||
|
|
||||||
|
- The Meta-Arguments section documents special arguments that can be used with
|
||||||
|
every resource type, including
|
||||||
|
[`depends_on`](/docs/configuration/meta-arguments/depends_on.html),
|
||||||
|
[`count`](/docs/configuration/meta-arguments/count.html),
|
||||||
|
[`for_each`](/docs/configuration/meta-arguments/for_each.html),
|
||||||
|
[`provider`](/docs/configuration/meta-arguments/resource-provider.html),
|
||||||
|
and [`lifecycle`](/docs/configuration/meta-arguments/lifecycle.html).
|
||||||
|
|
||||||
- [Provisioners](/docs/configuration/blocks/resources/provisioners/index.html)
|
- [Provisioners](/docs/configuration/blocks/resources/provisioners/index.html)
|
||||||
documents configuring post-creation actions for a resource using the
|
documents configuring post-creation actions for a resource using the
|
||||||
`provisioner` and `connection` blocks. Since provisioners are non-declarative
|
`provisioner` and `connection` blocks. Since provisioners are non-declarative
|
||||||
|
|
|
@ -0,0 +1,171 @@
|
||||||
|
---
|
||||||
|
layout: "language"
|
||||||
|
page_title: "Resources - Configuration Language"
|
||||||
|
sidebar_current: "docs-config-resources"
|
||||||
|
description: |-
|
||||||
|
Resources are the most important element in a Terraform configuration.
|
||||||
|
Each resource corresponds to an infrastructure object, such as a virtual
|
||||||
|
network or compute instance.
|
||||||
|
---
|
||||||
|
|
||||||
|
# Resource Blocks
|
||||||
|
|
||||||
|
-> **Note:** This page is about Terraform 0.12 and later. For Terraform 0.11 and
|
||||||
|
earlier, see
|
||||||
|
[0.11 Configuration Language: Resources](../configuration-0-11/resources.html).
|
||||||
|
|
||||||
|
> **Hands-on:** Try the [Terraform: Get Started](https://learn.hashicorp.com/collections/terraform/aws-get-started?utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) collection on HashiCorp Learn.
|
||||||
|
|
||||||
|
_Resources_ are the most important element in the Terraform language.
|
||||||
|
Each resource block describes one or more infrastructure objects, such
|
||||||
|
as virtual networks, compute instances, or higher-level components such
|
||||||
|
as DNS records.
|
||||||
|
|
||||||
|
## Resource Syntax
|
||||||
|
|
||||||
|
Resource declarations can include a number of advanced features, but only
|
||||||
|
a small subset are required for initial use. More advanced syntax features,
|
||||||
|
such as single resource declarations that produce multiple similar remote
|
||||||
|
objects, are described later in this page.
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
resource "aws_instance" "web" {
|
||||||
|
ami = "ami-a1b2c3d4"
|
||||||
|
instance_type = "t2.micro"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
A `resource` block declares a resource of a given type ("aws_instance")
|
||||||
|
with a given local name ("web"). The name is used to refer to this resource
|
||||||
|
from elsewhere in the same Terraform module, but has no significance outside
|
||||||
|
that module's scope.
|
||||||
|
|
||||||
|
The resource type and name together serve as an identifier for a given
|
||||||
|
resource and so must be unique within a module.
|
||||||
|
|
||||||
|
Within the block body (between `{` and `}`) are the configuration arguments
|
||||||
|
for the resource itself. Most arguments in this section depend on the
|
||||||
|
resource type, and indeed in this example both `ami` and `instance_type` are
|
||||||
|
arguments defined specifically for [the `aws_instance` resource type](/docs/providers/aws/r/instance.html).
|
||||||
|
|
||||||
|
-> **Note:** Resource names must start with a letter or underscore, and may
|
||||||
|
contain only letters, digits, underscores, and dashes.
|
||||||
|
|
||||||
|
## Resource Types
|
||||||
|
|
||||||
|
Each resource is associated with a single _resource type_, which determines
|
||||||
|
the kind of infrastructure object it manages and what arguments and other
|
||||||
|
attributes the resource supports.
|
||||||
|
|
||||||
|
### Providers
|
||||||
|
|
||||||
|
Each resource type is implemented by a [provider](/docs/configuration/provider-requirements.html),
|
||||||
|
which is a plugin for Terraform that offers a collection of resource types. A
|
||||||
|
provider usually provides resources to manage a single cloud or on-premises
|
||||||
|
infrastructure platform. Providers are distributed separately from Terraform
|
||||||
|
itself, but Terraform can automatically install most providers when initializing
|
||||||
|
a working directory.
|
||||||
|
|
||||||
|
In order to manage resources, a Terraform module must specify which providers it
|
||||||
|
requires. Additionally, most providers need some configuration in order to
|
||||||
|
access their remote APIs, and the root module must provide that configuration.
|
||||||
|
|
||||||
|
For more information, see:
|
||||||
|
|
||||||
|
- [Provider Requirements](/docs/configuration/provider-requirements.html), for declaring which
|
||||||
|
providers a module uses.
|
||||||
|
- [Provider Configuration](/docs/configuration/providers.html), for configuring provider settings.
|
||||||
|
|
||||||
|
Terraform usually automatically determines which provider to use based on a
|
||||||
|
resource type's name. (By convention, resource type names start with their
|
||||||
|
provider's preferred local name.) When using multiple configurations of a
|
||||||
|
provider (or non-preferred local provider names), you must use the `provider`
|
||||||
|
meta-argument to manually choose an alternate provider configuration. See
|
||||||
|
[the `provider` meta-argument](/docs/configuration/meta-arguments/resource-provider.html) for more details.
|
||||||
|
|
||||||
|
### Resource Arguments
|
||||||
|
|
||||||
|
Most of the arguments within the body of a `resource` block are specific to the
|
||||||
|
selected resource type. The resource type's documentation lists which arguments
|
||||||
|
are available and how their values should be formatted.
|
||||||
|
|
||||||
|
The values for resource arguments can make full use of
|
||||||
|
[expressions](/docs/configuration/expressions/index.html) and other dynamic Terraform
|
||||||
|
language features.
|
||||||
|
|
||||||
|
There are also some _meta-arguments_ that are defined by Terraform itself
|
||||||
|
and apply across all resource types. (See [Meta-Arguments](#meta-arguments) below.)
|
||||||
|
|
||||||
|
### Documentation for Resource Types
|
||||||
|
|
||||||
|
Every Terraform provider has its own documentation, describing its resource
|
||||||
|
types and their arguments.
|
||||||
|
|
||||||
|
Most publicly available providers are distributed on the
|
||||||
|
[Terraform Registry](https://registry.terraform.io/browse/providers), which also
|
||||||
|
hosts their documentation. When viewing a provider's page on the Terraform
|
||||||
|
Registry, you can click the "Documentation" link in the header to browse its
|
||||||
|
documentation. Provider documentation on the registry is versioned, and you can
|
||||||
|
use the dropdown version menu in the header to switch which version's
|
||||||
|
documentation you are viewing.
|
||||||
|
|
||||||
|
To browse the publicly available providers and their documentation, see
|
||||||
|
[the providers section of the Terraform Registry](https://registry.terraform.io/browse/providers).
|
||||||
|
|
||||||
|
-> **Note:** Provider documentation used to be hosted directly on terraform.io,
|
||||||
|
as part of Terraform's core documentation. Although some provider documentation
|
||||||
|
might still be hosted here, the Terraform Registry is now the main home for all
|
||||||
|
public provider docs. (The exception is the built-in
|
||||||
|
[`terraform` provider](/docs/providers/terraform/index.html) for reading state
|
||||||
|
data, since it is not available on the Terraform Registry.)
|
||||||
|
|
||||||
|
## Resource Behavior
|
||||||
|
|
||||||
|
For more information about how Terraform manages resources when applying a
|
||||||
|
configuration, see
|
||||||
|
[Resource Behavior](/docs/configuration/blocks/resources/behavior.html).
|
||||||
|
|
||||||
|
## Meta-Arguments
|
||||||
|
|
||||||
|
The Terraform language defines several meta-arguments, which can be used with
|
||||||
|
any resource type to change the behavior of resources.
|
||||||
|
|
||||||
|
The following meta-arguments are documented on separate pages:
|
||||||
|
|
||||||
|
- [`depends_on`, for specifying hidden dependencies](/docs/configuration/meta-arguments/depends_on.html)
|
||||||
|
- [`count`, for creating multiple resource instances according to a count](/docs/configuration/meta-arguments/count.html)
|
||||||
|
- [`for_each`, to create multiple instances according to a map, or set of strings](/docs/configuration/meta-arguments/for_each.html)
|
||||||
|
- [`provider`, for selecting a non-default provider configuration](/docs/configuration/meta-arguments/resource-provider.html)
|
||||||
|
- [`lifecycle`, for lifecycle customizations](/docs/configuration/meta-arguments/lifecycle.html)
|
||||||
|
- [`provisioner` and `connection`, for taking extra actions after resource creation](/docs/configuration/blocks/resources/provisioners/index.html)
|
||||||
|
|
||||||
|
## Operation Timeouts
|
||||||
|
|
||||||
|
Some resource types provide a special `timeouts` nested block argument that
|
||||||
|
allows you to customize how long certain operations are allowed to take
|
||||||
|
before being considered to have failed.
|
||||||
|
For example, [`aws_db_instance`](/docs/providers/aws/r/db_instance.html)
|
||||||
|
allows configurable timeouts for `create`, `update` and `delete` operations.
|
||||||
|
|
||||||
|
Timeouts are handled entirely by the resource type implementation in the
|
||||||
|
provider, but resource types offering these features follow the convention
|
||||||
|
of defining a child block called `timeouts` that has a nested argument
|
||||||
|
named after each operation that has a configurable timeout value.
|
||||||
|
Each of these arguments takes a string representation of a duration, such
|
||||||
|
as `"60m"` for 60 minutes, `"10s"` for ten seconds, or `"2h"` for two hours.
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
resource "aws_db_instance" "example" {
|
||||||
|
# ...
|
||||||
|
|
||||||
|
timeouts {
|
||||||
|
create = "60m"
|
||||||
|
delete = "2h"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The set of configurable operations is chosen by each resource type. Most
|
||||||
|
resource types do not support the `timeouts` block at all. Consult the
|
||||||
|
documentation for each resource type to see which operations it offers
|
||||||
|
for configuration, if any.
|
|
@ -0,0 +1,122 @@
|
||||||
|
---
|
||||||
|
layout: "language"
|
||||||
|
page_title: "The count Meta-Argument - Configuration Language"
|
||||||
|
---
|
||||||
|
|
||||||
|
# The `count` Meta-Argument
|
||||||
|
|
||||||
|
-> **Version note:** Module support for `count` was added in Terraform 0.13, and
|
||||||
|
previous versions can only use it with resources.
|
||||||
|
|
||||||
|
-> **Note:** A given resource or module block cannot use both `count` and `for_each`.
|
||||||
|
|
||||||
|
> **Hands-on:** Try the [Manage Similar Resources With Count](https://learn.hashicorp.com/tutorials/terraform/count?in=terraform/0-13&utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) tutorial on HashiCorp Learn.
|
||||||
|
|
||||||
|
By default, a [resource block](/docs/configuration/blocks/resources/syntax.html) configures one real
|
||||||
|
infrastructure object. (Similarly, a
|
||||||
|
[module block](/docs/configuration/blocks/modules/syntax.html) includes a
|
||||||
|
child module's contents into the configuration one time.)
|
||||||
|
However, sometimes you want to manage several similar objects (like a fixed
|
||||||
|
pool of compute instances) without writing a separate block for each one.
|
||||||
|
Terraform has two ways to do this:
|
||||||
|
`count` and [`for_each`](/docs/configuration/meta-arguments/for_each.html).
|
||||||
|
|
||||||
|
If a resource or module block includes a `count` argument whose value is a whole number,
|
||||||
|
Terraform will create that many instances.
|
||||||
|
|
||||||
|
## Basic Syntax
|
||||||
|
|
||||||
|
`count` is a meta-argument defined by the Terraform language. It can be used
|
||||||
|
with modules and with every resource type.
|
||||||
|
|
||||||
|
The `count` meta-argument accepts a whole number, and creates that many
|
||||||
|
instances of the resource or module. Each instance has a distinct infrastructure object
|
||||||
|
associated with it, and each is separately created,
|
||||||
|
updated, or destroyed when the configuration is applied.
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
resource "aws_instance" "server" {
|
||||||
|
count = 4 # create four similar EC2 instances
|
||||||
|
|
||||||
|
ami = "ami-a1b2c3d4"
|
||||||
|
instance_type = "t2.micro"
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
Name = "Server ${count.index}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## The `count` Object
|
||||||
|
|
||||||
|
In blocks where `count` is set, an additional `count` object is
|
||||||
|
available in expressions, so you can modify the configuration of each instance.
|
||||||
|
This object has one attribute:
|
||||||
|
|
||||||
|
- `count.index` — The distinct index number (starting with `0`) corresponding
|
||||||
|
to this instance.
|
||||||
|
|
||||||
|
## Using Expressions in `count`
|
||||||
|
|
||||||
|
The `count` meta-argument accepts numeric [expressions](/docs/configuration/expressions/index.html).
|
||||||
|
However, unlike most arguments, the `count` value must be known
|
||||||
|
_before_ Terraform performs any remote resource actions. This means `count`
|
||||||
|
can't refer to any resource attributes that aren't known until after a
|
||||||
|
configuration is applied (such as a unique ID generated by the remote API when
|
||||||
|
an object is created).
|
||||||
|
|
||||||
|
## Referring to Instances
|
||||||
|
|
||||||
|
When `count` is set, Terraform distinguishes between the block itself
|
||||||
|
and the multiple _resource or module instances_ associated with it. Instances are
|
||||||
|
identified by an index number, starting with `0`.
|
||||||
|
|
||||||
|
- `<TYPE>.<NAME>` or `module.<NAME>` (for example, `aws_instance.server`) refers to the resource block.
|
||||||
|
- `<TYPE>.<NAME>[<INDEX>]` or `module.<NAME>[<INDEX>]` (for example, `aws_instance.server[0]`,
|
||||||
|
`aws_instance.server[1]`, etc.) refers to individual instances.
|
||||||
|
|
||||||
|
This is different from resources and modules without `count` or `for_each`, which can be
|
||||||
|
referenced without an index or key.
|
||||||
|
|
||||||
|
Similarly, resources from child modules with multiple instances are prefixed
|
||||||
|
with `module.<NAME>[<KEY>]` when displayed in plan output and elsewhere in the UI.
|
||||||
|
For a module without `count` or `for_each`, the address will not contain
|
||||||
|
the module index as the module's name suffices to reference the module.
|
||||||
|
|
||||||
|
-> **Note:** Within nested `provisioner` or `connection` blocks, the special
|
||||||
|
`self` object refers to the current _resource instance,_ not the resource block
|
||||||
|
as a whole.
|
||||||
|
|
||||||
|
## When to Use `for_each` Instead of `count`
|
||||||
|
|
||||||
|
If your instances are almost identical, `count` is appropriate. If some
|
||||||
|
of their arguments need distinct values that can't be directly derived from an
|
||||||
|
integer, it's safer to use `for_each`.
|
||||||
|
|
||||||
|
Before `for_each` was available, it was common to derive `count` from the
|
||||||
|
length of a list and use `count.index` to look up the original list value:
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
variable "subnet_ids" {
|
||||||
|
type = list(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_instance" "server" {
|
||||||
|
# Create one instance for each subnet
|
||||||
|
count = length(var.subnet_ids)
|
||||||
|
|
||||||
|
ami = "ami-a1b2c3d4"
|
||||||
|
instance_type = "t2.micro"
|
||||||
|
subnet_id = var.subnet_ids[count.index]
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
Name = "Server ${count.index}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This was fragile, because the resource instances were still identified by their
|
||||||
|
_index_ instead of the string values in the list. If an element was removed from
|
||||||
|
the middle of the list, every instance _after_ that element would see its
|
||||||
|
`subnet_id` value change, resulting in more remote object changes than intended.
|
||||||
|
Using `for_each` gives the same flexibility without the extra churn.
|
|
@ -0,0 +1,76 @@
|
||||||
|
---
|
||||||
|
layout: "language"
|
||||||
|
page_title: "The depends_on Meta-Argument - Configuration Language"
|
||||||
|
---
|
||||||
|
|
||||||
|
# The `depends_on` Meta-Argument
|
||||||
|
|
||||||
|
-> **Version note:** Module support for `depends_on` was added in Terraform 0.13, and
|
||||||
|
previous versions can only use it with resources.
|
||||||
|
|
||||||
|
Use the `depends_on` meta-argument to handle hidden resource or module dependencies that
|
||||||
|
Terraform can't automatically infer.
|
||||||
|
|
||||||
|
Explicitly specifying a dependency is only necessary when a resource or module relies on
|
||||||
|
some other resource's behavior but _doesn't_ access any of that resource's data
|
||||||
|
in its arguments.
|
||||||
|
|
||||||
|
This argument is available in `module` blocks and in all `resource` blocks,
|
||||||
|
regardless of resource type. For example:
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
resource "aws_iam_role" "example" {
|
||||||
|
name = "example"
|
||||||
|
|
||||||
|
# assume_role_policy is omitted for brevity in this example. See the
|
||||||
|
# documentation for aws_iam_role for a complete example.
|
||||||
|
assume_role_policy = "..."
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_instance_profile" "example" {
|
||||||
|
# Because this expression refers to the role, Terraform can infer
|
||||||
|
# automatically that the role must be created first.
|
||||||
|
role = aws_iam_role.example.name
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_role_policy" "example" {
|
||||||
|
name = "example"
|
||||||
|
role = aws_iam_role.example.name
|
||||||
|
policy = jsonencode({
|
||||||
|
"Statement" = [{
|
||||||
|
# This policy allows software running on the EC2 instance to
|
||||||
|
# access the S3 API.
|
||||||
|
"Action" = "s3:*",
|
||||||
|
"Effect" = "Allow",
|
||||||
|
}],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_instance" "example" {
|
||||||
|
ami = "ami-a1b2c3d4"
|
||||||
|
instance_type = "t2.micro"
|
||||||
|
|
||||||
|
# Terraform can infer from this that the instance profile must
|
||||||
|
# be created before the EC2 instance.
|
||||||
|
iam_instance_profile = aws_iam_instance_profile.example
|
||||||
|
|
||||||
|
# However, if software running in this EC2 instance needs access
|
||||||
|
# to the S3 API in order to boot properly, there is also a "hidden"
|
||||||
|
# dependency on the aws_iam_role_policy that Terraform cannot
|
||||||
|
# automatically infer, so it must be declared explicitly:
|
||||||
|
depends_on = [
|
||||||
|
aws_iam_role_policy.example,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The `depends_on` meta-argument, if present, must be a list of references
|
||||||
|
to other resources or child modules in the same calling module.
|
||||||
|
Arbitrary expressions are not allowed in the `depends_on` argument value,
|
||||||
|
because its value must be known before Terraform knows resource relationships
|
||||||
|
and thus before it can safely evaluate expressions.
|
||||||
|
|
||||||
|
The `depends_on` argument should be used only as a last resort. When using it,
|
||||||
|
always include a comment explaining why it is being used, to help future
|
||||||
|
maintainers understand the purpose of the additional dependency.
|
||||||
|
|
|
@ -0,0 +1,199 @@
|
||||||
|
---
|
||||||
|
layout: "language"
|
||||||
|
page_title: "The for_each Meta-Argument - Configuration Language"
|
||||||
|
---
|
||||||
|
|
||||||
|
# The `for_each` Meta-Argument
|
||||||
|
|
||||||
|
-> **Version note:** `for_each` was added in Terraform 0.12.6. Module support
|
||||||
|
for `for_each` was added in Terraform 0.13, and previous versions can only use
|
||||||
|
it with resources.
|
||||||
|
|
||||||
|
-> **Note:** A given resource or module block cannot use both `count` and `for_each`.
|
||||||
|
|
||||||
|
> **Hands-on:** Try the [Manage Similar Resources With For Each](https://learn.hashicorp.com/tutorials/terraform/for-each?in=terraform/0-13&utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) tutorial on HashiCorp Learn.
|
||||||
|
|
||||||
|
By default, a [resource block](/docs/configuration/blocks/resources/syntax.html) configures one real
|
||||||
|
infrastructure object. (Similarly, a
|
||||||
|
[module block](/docs/configuration/blocks/modules/syntax.html) includes a
|
||||||
|
child module's contents into the configuration one time.)
|
||||||
|
However, sometimes you want to manage several similar objects (like a fixed
|
||||||
|
pool of compute instances) without writing a separate block for each one.
|
||||||
|
Terraform has two ways to do this:
|
||||||
|
[`count`](/docs/configuration/meta-arguments/count.html) and `for_each`.
|
||||||
|
|
||||||
|
If a resource or module block includes a `for_each` argument whose value is a map or
|
||||||
|
a set of strings, Terraform will create one instance for each member of
|
||||||
|
that map or set.
|
||||||
|
|
||||||
|
## Basic Syntax
|
||||||
|
|
||||||
|
`for_each` is a meta-argument defined by the Terraform language. It can be used
|
||||||
|
with modules and with every resource type.
|
||||||
|
|
||||||
|
The `for_each` meta-argument accepts a map or a set of strings, and creates an
|
||||||
|
instance for each item in that map or set. Each instance has a distinct
|
||||||
|
infrastructure object associated with it, and each is separately created,
|
||||||
|
updated, or destroyed when the configuration is applied.
|
||||||
|
|
||||||
|
-> **Note:** The keys of the map (or all the values in the case of a set of strings) must
|
||||||
|
be _known values_, or you will get an error message that `for_each` has dependencies
|
||||||
|
that cannot be determined before apply, and a `-target` may be needed. `for_each` keys
|
||||||
|
cannot be the result (or rely on the result of) of impure functions, including `uuid`, `bcrypt`,
|
||||||
|
or `timestamp`, as their evaluation is deferred during the main evaluation step.
|
||||||
|
|
||||||
|
Map:
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
resource "azurerm_resource_group" "rg" {
|
||||||
|
for_each = {
|
||||||
|
a_group = "eastus"
|
||||||
|
another_group = "westus2"
|
||||||
|
}
|
||||||
|
name = each.key
|
||||||
|
location = each.value
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Set of strings:
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
resource "aws_iam_user" "the-accounts" {
|
||||||
|
for_each = toset( ["Todd", "James", "Alice", "Dottie"] )
|
||||||
|
name = each.key
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Child module:
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
# my_buckets.tf
|
||||||
|
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" {
|
||||||
|
# Because var.name includes each.key in the calling
|
||||||
|
# module block, its value will be different for
|
||||||
|
# each instance of this module.
|
||||||
|
bucket = var.name
|
||||||
|
|
||||||
|
# ...
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_iam_user" "deploy_user" {
|
||||||
|
# ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## The `each` Object
|
||||||
|
|
||||||
|
In blocks where `for_each` is set, an additional `each` object is
|
||||||
|
available in expressions, so you can modify the configuration of each instance.
|
||||||
|
This object has two attributes:
|
||||||
|
|
||||||
|
- `each.key` — The map key (or set member) corresponding to this instance.
|
||||||
|
- `each.value` — The map value corresponding to this instance. (If a set was
|
||||||
|
provided, this is the same as `each.key`.)
|
||||||
|
|
||||||
|
## Using Expressions in `for_each`
|
||||||
|
|
||||||
|
The `for_each` meta-argument accepts map or set [expressions](/docs/configuration/expressions/index.html).
|
||||||
|
However, unlike most arguments, the `for_each` value must be known
|
||||||
|
_before_ Terraform performs any remote resource actions. This means `for_each`
|
||||||
|
can't refer to any resource attributes that aren't known until after a
|
||||||
|
configuration is applied (such as a unique ID generated by the remote API when
|
||||||
|
an object is created).
|
||||||
|
|
||||||
|
The `for_each` value must be a map or set with one element per desired
|
||||||
|
resource instance. When providing a set, you must use an expression that
|
||||||
|
explicitly returns a set value, like the [`toset`](/docs/configuration/functions/toset.html)
|
||||||
|
function; to prevent unwanted surprises during conversion, the `for_each`
|
||||||
|
argument does not implicitly convert lists or tuples to sets.
|
||||||
|
If you need to declare resource instances based on a nested
|
||||||
|
data structure or combinations of elements from multiple data structures you
|
||||||
|
can use Terraform expressions and functions to derive a suitable value.
|
||||||
|
For example:
|
||||||
|
|
||||||
|
* Transform a multi-level nested structure into a flat list by
|
||||||
|
[using nested `for` expressions with the `flatten` function](/docs/configuration/functions/flatten.html#flattening-nested-structures-for-for_each).
|
||||||
|
* Produce an exhaustive list of combinations of elements from two or more
|
||||||
|
collections by
|
||||||
|
[using the `setproduct` function inside a `for` expression](/docs/configuration/functions/setproduct.html#finding-combinations-for-for_each).
|
||||||
|
|
||||||
|
## Referring to Instances
|
||||||
|
|
||||||
|
When `for_each` is set, Terraform distinguishes between the block itself
|
||||||
|
and the multiple _resource or module instances_ associated with it. Instances are
|
||||||
|
identified by a map key (or set member) from the value provided to `for_each`.
|
||||||
|
|
||||||
|
- `<TYPE>.<NAME>` or `module.<NAME>` (for example, `azurerm_resource_group.rg`) refers to the block.
|
||||||
|
- `<TYPE>.<NAME>[<KEY>]` or `module.<NAME>[<KEY>]` (for example, `azurerm_resource_group.rg["a_group"]`,
|
||||||
|
`azurerm_resource_group.rg["another_group"]`, etc.) refers to individual instances.
|
||||||
|
|
||||||
|
This is different from resources and modules without `count` or `for_each`, which can be
|
||||||
|
referenced without an index or key.
|
||||||
|
|
||||||
|
Similarly, resources from child modules with multiple instances are prefixed
|
||||||
|
with `module.<NAME>[<KEY>]` when displayed in plan output and elsewhere in the UI.
|
||||||
|
For a module without `count` or `for_each`, the address will not contain
|
||||||
|
the module index as the module's name suffices to reference the module.
|
||||||
|
|
||||||
|
-> **Note:** Within nested `provisioner` or `connection` blocks, the special
|
||||||
|
`self` object refers to the current _resource instance,_ not the resource block
|
||||||
|
as a whole.
|
||||||
|
|
||||||
|
## Using Sets
|
||||||
|
|
||||||
|
The Terraform language doesn't have a literal syntax for
|
||||||
|
[set values](/docs/configuration/types.html#collection-types), but you can use the `toset`
|
||||||
|
function to explicitly convert a list of strings to a set:
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
locals {
|
||||||
|
subnet_ids = toset([
|
||||||
|
"subnet-abcdef",
|
||||||
|
"subnet-012345",
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_instance" "server" {
|
||||||
|
for_each = local.subnet_ids
|
||||||
|
|
||||||
|
ami = "ami-a1b2c3d4"
|
||||||
|
instance_type = "t2.micro"
|
||||||
|
subnet_id = each.key # note: each.key and each.value are the same for a set
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
Name = "Server ${each.key}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Conversion from list to set discards the ordering of the items in the list and
|
||||||
|
removes any duplicate elements. `toset(["b", "a", "b"])` will produce a set
|
||||||
|
containing only `"a"` and `"b"` in no particular order; the second `"b"` is
|
||||||
|
discarded.
|
||||||
|
|
||||||
|
If you are writing a module with an [input variable](/docs/configuration/variables.html) that
|
||||||
|
will be used as a set of strings for `for_each`, you can set its type to
|
||||||
|
`set(string)` to avoid the need for an explicit type conversion:
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
variable "subnet_ids" {
|
||||||
|
type = set(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_instance" "server" {
|
||||||
|
for_each = var.subnet_ids
|
||||||
|
|
||||||
|
# (and the other arguments as above)
|
||||||
|
}
|
||||||
|
```
|
|
@ -0,0 +1,110 @@
|
||||||
|
---
|
||||||
|
layout: "language"
|
||||||
|
page_title: "The lifecycle Meta-Argument - Configuration Language"
|
||||||
|
---
|
||||||
|
|
||||||
|
# The `lifecycle` Meta-Argument
|
||||||
|
|
||||||
|
The general lifecycle for resources is described in the
|
||||||
|
[Resource Behavior](/docs/configuration/blocks/resources/behavior.html) page. Some details of
|
||||||
|
that behavior can be customized using the special nested `lifecycle` block
|
||||||
|
within a resource block body:
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
resource "azurerm_resource_group" "example" {
|
||||||
|
# ...
|
||||||
|
|
||||||
|
lifecycle {
|
||||||
|
create_before_destroy = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Syntax and Arguments
|
||||||
|
|
||||||
|
`lifecycle` is a nested block that can appear within a resource block.
|
||||||
|
The `lifecycle` block and its contents are meta-arguments, available
|
||||||
|
for all `resource` blocks regardless of type.
|
||||||
|
|
||||||
|
The following arguments can be used within a `lifecycle` block:
|
||||||
|
|
||||||
|
* `create_before_destroy` (bool) - By default, when Terraform must change
|
||||||
|
a resource argument that cannot be updated in-place due to
|
||||||
|
remote API limitations, Terraform will instead destroy the existing object
|
||||||
|
and then create a new replacement object with the new configured arguments.
|
||||||
|
|
||||||
|
The `create_before_destroy` meta-argument changes this behavior so that
|
||||||
|
the new replacement object is created _first,_ and the prior object
|
||||||
|
is destroyed after the replacement is created.
|
||||||
|
|
||||||
|
This is an opt-in behavior because many remote object types have unique
|
||||||
|
name requirements or other constraints that must be accommodated for
|
||||||
|
both a new and an old object to exist concurrently. Some resource types
|
||||||
|
offer special options to append a random suffix onto each object name to
|
||||||
|
avoid collisions, for example. Terraform CLI cannot automatically activate
|
||||||
|
such features, so you must understand the constraints for each resource
|
||||||
|
type before using `create_before_destroy` with it.
|
||||||
|
|
||||||
|
* `prevent_destroy` (bool) - This meta-argument, when set to `true`, will
|
||||||
|
cause Terraform to reject with an error any plan that would destroy the
|
||||||
|
infrastructure object associated with the resource, as long as the argument
|
||||||
|
remains present in the configuration.
|
||||||
|
|
||||||
|
This can be used as a measure of safety against the accidental replacement
|
||||||
|
of objects that may be costly to reproduce, such as database instances.
|
||||||
|
However, it will make certain configuration changes impossible to apply,
|
||||||
|
and will prevent the use of the `terraform destroy` command once such
|
||||||
|
objects are created, and so this option should be used sparingly.
|
||||||
|
|
||||||
|
Since this argument must be present in configuration for the protection to
|
||||||
|
apply, note that this setting does not prevent the remote object from
|
||||||
|
being destroyed if the `resource` block were removed from configuration
|
||||||
|
entirely: in that case, the `prevent_destroy` setting is removed along
|
||||||
|
with it, and so Terraform will allow the destroy operation to succeed.
|
||||||
|
|
||||||
|
* `ignore_changes` (list of attribute names) - By default, Terraform detects
|
||||||
|
any difference in the current settings of a real infrastructure object
|
||||||
|
and plans to update the remote object to match configuration.
|
||||||
|
|
||||||
|
The `ignore_changes` feature is intended to be used when a resource is
|
||||||
|
created with references to data that may change in the future, but should
|
||||||
|
not affect said resource after its creation. In some rare cases, settings
|
||||||
|
of a remote object are modified by processes outside of Terraform, which
|
||||||
|
Terraform would then attempt to "fix" on the next run. In order to make
|
||||||
|
Terraform share management responsibilities of a single object with a
|
||||||
|
separate process, the `ignore_changes` meta-argument specifies resource
|
||||||
|
attributes that Terraform should ignore when planning updates to the
|
||||||
|
associated remote object.
|
||||||
|
|
||||||
|
The arguments corresponding to the given attribute names are considered
|
||||||
|
when planning a _create_ operation, but are ignored when planning an
|
||||||
|
_update_. The arguments are the relative address of the attributes in the
|
||||||
|
resource. Map and list elements can be referenced using index notation,
|
||||||
|
like `tags["Name"]` and `list[0]` respectively.
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
resource "aws_instance" "example" {
|
||||||
|
# ...
|
||||||
|
|
||||||
|
lifecycle {
|
||||||
|
ignore_changes = [
|
||||||
|
# Ignore changes to tags, e.g. because a management agent
|
||||||
|
# updates these based on some ruleset managed elsewhere.
|
||||||
|
tags,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Instead of a list, the special keyword `all` may be used to instruct
|
||||||
|
Terraform to ignore _all_ attributes, which means that Terraform can
|
||||||
|
create and destroy the remote object but will never propose updates to it.
|
||||||
|
|
||||||
|
Only attributes defined by the resource type can be ignored.
|
||||||
|
`ignore_changes` cannot be applied to itself or to any other meta-arguments.
|
||||||
|
|
||||||
|
## Literal Values Only
|
||||||
|
|
||||||
|
The `lifecycle` settings all affect how Terraform constructs and traverses
|
||||||
|
the dependency graph. As a result, only literal values can be used because
|
||||||
|
the processing happens too early for arbitrary expression evaluation.
|
|
@ -0,0 +1,58 @@
|
||||||
|
---
|
||||||
|
layout: "language"
|
||||||
|
page_title: "The Resource provider Meta-Argument - Configuration Language"
|
||||||
|
---
|
||||||
|
|
||||||
|
# The Resource `provider` Meta-Argument
|
||||||
|
|
||||||
|
The `provider` meta-argument specifies which provider configuration to use for a resource,
|
||||||
|
overriding Terraform's default behavior of selecting one based on the resource
|
||||||
|
type name. Its value should be an unquoted `<PROVIDER>.<ALIAS>` reference.
|
||||||
|
|
||||||
|
As described in [Provider Configuration](/docs/configuration/providers.html), you can optionally
|
||||||
|
create multiple configurations for a single provider (usually to manage
|
||||||
|
resources in different regions of multi-region services). Each provider can have
|
||||||
|
one default configuration, and any number of alternate configurations that
|
||||||
|
include an extra name segment (or "alias").
|
||||||
|
|
||||||
|
By default, Terraform interprets the initial word in the resource type name
|
||||||
|
(separated by underscores) as the local name of a provider, and uses that
|
||||||
|
provider's default configuration. For example, the resource type
|
||||||
|
`google_compute_instance` is associated automatically with the default
|
||||||
|
configuration for the provider named `google`.
|
||||||
|
|
||||||
|
By using the `provider` meta-argument, you can select an alternate provider
|
||||||
|
configuration for a resource:
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
# default configuration
|
||||||
|
provider "google" {
|
||||||
|
region = "us-central1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# alternate configuration, whose alias is "europe"
|
||||||
|
provider "google" {
|
||||||
|
alias = "europe"
|
||||||
|
region = "europe-west1"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_compute_instance" "example" {
|
||||||
|
# This "provider" meta-argument selects the google provider
|
||||||
|
# configuration whose alias is "europe", rather than the
|
||||||
|
# default configuration.
|
||||||
|
provider = google.europe
|
||||||
|
|
||||||
|
# ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
A resource always has an implicit dependency on its associated provider, to
|
||||||
|
ensure that the provider is fully configured before any resource actions
|
||||||
|
are taken.
|
||||||
|
|
||||||
|
The `provider` meta-argument expects
|
||||||
|
[a `<PROVIDER>.<ALIAS>` reference](/docs/configuration/providers.html#referring-to-alternate-providers),
|
||||||
|
which does not need to be quoted. Arbitrary expressions are not permitted for
|
||||||
|
`provider` because it must be resolved while Terraform is constructing the
|
||||||
|
dependency graph, before it is safe to evaluate expressions.
|
||||||
|
|
|
@ -1,764 +1,86 @@
|
||||||
---
|
---
|
||||||
layout: "language"
|
layout: "language"
|
||||||
page_title: "Resources - Configuration Language"
|
page_title: "Resources Landing Page - Configuration Language"
|
||||||
sidebar_current: "docs-config-resources"
|
|
||||||
description: |-
|
|
||||||
Resources are the most important element in a Terraform configuration.
|
|
||||||
Each resource corresponds to an infrastructure object, such as a virtual
|
|
||||||
network or compute instance.
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# Resources
|
# Resources Landing Page
|
||||||
|
|
||||||
-> **Note:** This page is about Terraform 0.12 and later. For Terraform 0.11 and
|
To improve navigation, we've split the old Resources page into several smaller
|
||||||
earlier, see
|
pages.
|
||||||
[0.11 Configuration Language: Resources](../configuration-0-11/resources.html).
|
|
||||||
|
|
||||||
> **Hands-on:** Try the [Terraform: Get Started](https://learn.hashicorp.com/collections/terraform/aws-get-started?utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) collection on HashiCorp Learn.
|
<a id="resource-syntax"></a>
|
||||||
|
<a id="resource-types"></a>
|
||||||
|
<a id="providers"></a>
|
||||||
|
<a id="resource-arguments"></a>
|
||||||
|
<a id="documentation-for-resource-types"></a>
|
||||||
|
<a id="meta-arguments"></a>
|
||||||
|
<a id="operation-timeouts"></a>
|
||||||
|
|
||||||
_Resources_ are the most important element in the Terraform language.
|
## Syntax and Elements of Resource Blocks
|
||||||
Each resource block describes one or more infrastructure objects, such
|
|
||||||
as virtual networks, compute instances, or higher-level components such
|
|
||||||
as DNS records.
|
|
||||||
|
|
||||||
## Resource Syntax
|
This information has moved to
|
||||||
|
[Resource Blocks](/docs/configuration/blocks/resources/syntax.html).
|
||||||
|
|
||||||
Resource declarations can include a number of advanced features, but only
|
<a id="resource-behavior"></a>
|
||||||
a small subset are required for initial use. More advanced syntax features,
|
<a id="accessing-resource-attributes"></a>
|
||||||
such as single resource declarations that produce multiple similar remote
|
<a id="resource-dependencies"></a>
|
||||||
objects, are described later in this page.
|
<a id="local-only-resources"></a>
|
||||||
|
|
||||||
```hcl
|
## Details of Resource Behavior
|
||||||
resource "aws_instance" "web" {
|
|
||||||
ami = "ami-a1b2c3d4"
|
|
||||||
instance_type = "t2.micro"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
A `resource` block declares a resource of a given type ("aws_instance")
|
This information has moved to
|
||||||
with a given local name ("web"). The name is used to refer to this resource
|
[Resource Behavior](/docs/configuration/blocks/resources/behavior.html).
|
||||||
from elsewhere in the same Terraform module, but has no significance outside
|
|
||||||
that module's scope.
|
|
||||||
|
|
||||||
The resource type and name together serve as an identifier for a given
|
## Resource Meta-Arguments
|
||||||
resource and so must be unique within a module.
|
|
||||||
|
|
||||||
Within the block body (between `{` and `}`) are the configuration arguments
|
Each resource meta-argument has moved to its own page.
|
||||||
for the resource itself. Most arguments in this section depend on the
|
|
||||||
resource type, and indeed in this example both `ami` and `instance_type` are
|
|
||||||
arguments defined specifically for [the `aws_instance` resource type](/docs/providers/aws/r/instance.html).
|
|
||||||
|
|
||||||
-> **Note:** Resource names must start with a letter or underscore, and may
|
<a id="depends_on-explicit-resource-dependencies"></a>
|
||||||
contain only letters, digits, underscores, and dashes.
|
|
||||||
|
|
||||||
## Resource Types
|
### `depends_on`
|
||||||
|
|
||||||
Each resource is associated with a single _resource type_, which determines
|
This information has moved to
|
||||||
the kind of infrastructure object it manages and what arguments and other
|
[`depends_on`](/docs/configuration/meta-arguments/depends_on.html).
|
||||||
attributes the resource supports.
|
|
||||||
|
|
||||||
### Providers
|
<a id="count-multiple-resource-instances-by-count"></a>
|
||||||
|
<a id="the-count-object"></a>
|
||||||
|
<a id="referring-to-instances"></a>
|
||||||
|
<a id="using-expressions-in-count"></a>
|
||||||
|
<a id="when-to-use-for_each-instead-of-count"></a>
|
||||||
|
|
||||||
Each resource type is implemented by a [provider](./provider-requirements.html),
|
### `count`
|
||||||
which is a plugin for Terraform that offers a collection of resource types. A
|
|
||||||
provider usually provides resources to manage a single cloud or on-premises
|
|
||||||
infrastructure platform. Providers are distributed separately from Terraform
|
|
||||||
itself, but Terraform can automatically install most providers when initializing
|
|
||||||
a working directory.
|
|
||||||
|
|
||||||
In order to manage resources, a Terraform module must specify which providers it
|
This information has moved to
|
||||||
requires. Additionally, most providers need some configuration in order to
|
[`count`](/docs/configuration/meta-arguments/count.html).
|
||||||
access their remote APIs, and the root module must provide that configuration.
|
|
||||||
|
|
||||||
For more information, see:
|
<a id="for_each-multiple-resource-instances-defined-by-a-map-or-set-of-strings"></a>
|
||||||
|
<a id="the-each-object"></a>
|
||||||
|
<a id="using-expressions-in-for_each"></a>
|
||||||
|
<a id="referring-to-instances-1"></a>
|
||||||
|
<a id="using-sets"></a>
|
||||||
|
|
||||||
- [Provider Requirements](./provider-requirements.html), for declaring which
|
### `for_each`
|
||||||
providers a module uses.
|
|
||||||
- [Provider Configuration](./providers.html), for configuring provider settings.
|
|
||||||
|
|
||||||
Terraform usually automatically determines which provider to use based on a
|
This information has moved to
|
||||||
resource type's name. (By convention, resource type names start with their
|
[`for_each`](/docs/configuration/meta-arguments/for_each.html).
|
||||||
provider's preferred local name.) When using multiple configurations of a
|
|
||||||
provider (or non-preferred local provider names), you must use the `provider`
|
|
||||||
meta-argument to manually choose an alternate provider configuration. See
|
|
||||||
[the section on `provider` below][inpage-provider] for more details.
|
|
||||||
|
|
||||||
### Resource Arguments
|
<a id="provider-selecting-a-non-default-provider-configuration"></a>
|
||||||
|
|
||||||
Most of the arguments within the body of a `resource` block are specific to the
|
### `provider`
|
||||||
selected resource type. The resource type's documentation lists which arguments
|
|
||||||
are available and how their values should be formatted.
|
|
||||||
|
|
||||||
The values for resource arguments can make full use of
|
This information has moved to
|
||||||
[expressions](./expressions.html) and other dynamic Terraform
|
[`provider`](/docs/configuration/meta-arguments/resource-provider.html).
|
||||||
language features.
|
|
||||||
|
|
||||||
There are also some _meta-arguments_ that are defined by Terraform itself
|
<a id="lifecycle-lifecycle-customizations"></a>
|
||||||
and apply across all resource types. (See [Meta-Arguments](#meta-arguments) below.)
|
|
||||||
|
|
||||||
### Documentation for Resource Types
|
### `lifecycle`
|
||||||
|
|
||||||
Every Terraform provider has its own documentation, describing its resource
|
This information has moved to
|
||||||
types and their arguments.
|
[`lifecycle`](/docs/configuration/meta-arguments/lifecycle.html).
|
||||||
|
|
||||||
Most publicly available providers are distributed on the
|
<a id="provisioner-and-connection-resource-provisioners"></a>
|
||||||
[Terraform Registry](https://registry.terraform.io/browse/providers), which also
|
|
||||||
hosts their documentation. When viewing a provider's page on the Terraform
|
|
||||||
Registry, you can click the "Documentation" link in the header to browse its
|
|
||||||
documentation. Provider documentation on the registry is versioned, and you can
|
|
||||||
use the dropdown version menu in the header to switch which version's
|
|
||||||
documentation you are viewing.
|
|
||||||
|
|
||||||
To browse the publicly available providers and their documentation, see
|
### Provisioners
|
||||||
[the providers section of the Terraform Registry](https://registry.terraform.io/browse/providers).
|
|
||||||
|
|
||||||
-> **Note:** Provider documentation used to be hosted directly on terraform.io,
|
This information has moved to
|
||||||
as part of Terraform's core documentation. Although some provider documentation
|
[Provisioners](/docs/configuration/blocks/resources/provisioners/index.html).
|
||||||
might still be hosted here, the Terraform Registry is now the main home for all
|
|
||||||
public provider docs. (The exception is the built-in
|
|
||||||
[`terraform` provider](/docs/providers/terraform/index.html) for reading state
|
|
||||||
data, since it is not available on the Terraform Registry.)
|
|
||||||
|
|
||||||
## Resource Behavior
|
|
||||||
|
|
||||||
A `resource` block declares that you want a particular infrastructure object
|
|
||||||
to exist with the given settings. If you are writing a new configuration for
|
|
||||||
the first time, the resources it defines will exist _only_ in the configuration,
|
|
||||||
and will not yet represent real infrastructure objects in the target platform.
|
|
||||||
|
|
||||||
_Applying_ a Terraform configuration is the process of creating, updating,
|
|
||||||
and destroying real infrastructure objects in order to make their settings
|
|
||||||
match the configuration.
|
|
||||||
|
|
||||||
When Terraform creates a new infrastructure object represented by a `resource`
|
|
||||||
block, the identifier for that real object is saved in Terraform's
|
|
||||||
[state](/docs/state/index.html), allowing it to be updated and destroyed
|
|
||||||
in response to future changes. For resource blocks that already have an
|
|
||||||
associated infrastructure object in the state, Terraform compares the
|
|
||||||
actual configuration of the object with the arguments given in the
|
|
||||||
configuration and, if necessary, updates the object to match the configuration.
|
|
||||||
|
|
||||||
This general behavior applies for all resources, regardless of type. The
|
|
||||||
details of what it means to create, update, or destroy a resource are different
|
|
||||||
for each resource type, but this standard set of verbs is common across them
|
|
||||||
all.
|
|
||||||
|
|
||||||
The meta-arguments within `resource` blocks, documented in the
|
|
||||||
sections below, allow some details of this standard resource behavior to be
|
|
||||||
customized on a per-resource basis.
|
|
||||||
|
|
||||||
### Accessing Resource Attributes
|
|
||||||
|
|
||||||
[Expressions](./expressions.html) within a Terraform module can access
|
|
||||||
information about resources in the same module, and you can use that information
|
|
||||||
to help configure other resources. Use the `<RESOURCE TYPE>.<NAME>.<ATTRIBUTE>`
|
|
||||||
syntax to reference a resource attribute in an expression.
|
|
||||||
|
|
||||||
In addition to arguments specified in the configuration, resources often provide
|
|
||||||
read-only attributes with information obtained from the remote API; this often
|
|
||||||
includes things that can't be known until the resource is created, like the
|
|
||||||
resource's unique random ID.
|
|
||||||
|
|
||||||
Many providers also include [data sources](./data-sources.html), which are a
|
|
||||||
special type of resource used only for looking up information.
|
|
||||||
|
|
||||||
For a list of the attributes a resource or data source type provides, consult
|
|
||||||
its documentation; these are generally included in a second list below its list
|
|
||||||
of configurable arguments.
|
|
||||||
|
|
||||||
For more information about referencing resource attributes in expressions, see
|
|
||||||
[Expressions: References to Resource Attributes](./expressions.html#references-to-resource-attributes).
|
|
||||||
|
|
||||||
### Resource Dependencies
|
|
||||||
|
|
||||||
Most resources in a configuration don't have any particular relationship, and
|
|
||||||
Terraform can make changes to several unrelated resources in parallel.
|
|
||||||
|
|
||||||
However, some resources must be processed after other specific resources;
|
|
||||||
sometimes this is because of how the resource works, and sometimes the
|
|
||||||
resource's configuration just requires information generated by another
|
|
||||||
resource.
|
|
||||||
|
|
||||||
Most resource dependencies are handled automatically. Terraform analyses any
|
|
||||||
[expressions](./expressions.html) within a `resource` block to find references
|
|
||||||
to other objects, and treats those references as implicit ordering requirements
|
|
||||||
when creating, updating, or destroying resources. Since most resources with
|
|
||||||
behavioral dependencies on other resources also refer to those resources' data,
|
|
||||||
it's usually not necessary to manually specify dependencies between resources.
|
|
||||||
|
|
||||||
However, some dependencies cannot be recognized implicitly in configuration. For
|
|
||||||
example, if Terraform must manage access control policies _and_ take actions
|
|
||||||
that require those policies to be present, there is a hidden dependency between
|
|
||||||
the access policy and a resource whose creation depends on it. In these rare
|
|
||||||
cases, [the `depends_on` meta-argument][inpage-depend] can explicitly specify a
|
|
||||||
dependency.
|
|
||||||
|
|
||||||
## Meta-Arguments
|
|
||||||
|
|
||||||
Terraform CLI defines the following meta-arguments, which can be used with
|
|
||||||
any resource type to change the behavior of resources:
|
|
||||||
|
|
||||||
- [`depends_on`, for specifying hidden dependencies][inpage-depend]
|
|
||||||
- [`count`, for creating multiple resource instances according to a count][inpage-count]
|
|
||||||
- [`for_each`, to create multiple instances according to a map, or set of strings][inpage-for_each]
|
|
||||||
- [`provider`, for selecting a non-default provider configuration][inpage-provider]
|
|
||||||
- [`lifecycle`, for lifecycle customizations][inpage-lifecycle]
|
|
||||||
- [`provisioner` and `connection`, for taking extra actions after resource creation][inpage-provisioner]
|
|
||||||
|
|
||||||
These arguments often have additional restrictions on what language features can
|
|
||||||
be used with them, which are described in each
|
|
||||||
|
|
||||||
### `depends_on`: Explicit Resource Dependencies
|
|
||||||
|
|
||||||
[inpage-depend]: #depends_on-explicit-resource-dependencies
|
|
||||||
|
|
||||||
Use the `depends_on` meta-argument to handle hidden resource dependencies that
|
|
||||||
Terraform can't automatically infer.
|
|
||||||
|
|
||||||
Explicitly specifying a dependency is only necessary when a resource relies on
|
|
||||||
some other resource's behavior but _doesn't_ access any of that resource's data
|
|
||||||
in its arguments.
|
|
||||||
|
|
||||||
This argument is available in all `resource` blocks, regardless of resource
|
|
||||||
type. For example:
|
|
||||||
|
|
||||||
```hcl
|
|
||||||
resource "aws_iam_role" "example" {
|
|
||||||
name = "example"
|
|
||||||
|
|
||||||
# assume_role_policy is omitted for brevity in this example. See the
|
|
||||||
# documentation for aws_iam_role for a complete example.
|
|
||||||
assume_role_policy = "..."
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "aws_iam_instance_profile" "example" {
|
|
||||||
# Because this expression refers to the role, Terraform can infer
|
|
||||||
# automatically that the role must be created first.
|
|
||||||
role = aws_iam_role.example.name
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "aws_iam_role_policy" "example" {
|
|
||||||
name = "example"
|
|
||||||
role = aws_iam_role.example.name
|
|
||||||
policy = jsonencode({
|
|
||||||
"Statement" = [{
|
|
||||||
# This policy allows software running on the EC2 instance to
|
|
||||||
# access the S3 API.
|
|
||||||
"Action" = "s3:*",
|
|
||||||
"Effect" = "Allow",
|
|
||||||
}],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "aws_instance" "example" {
|
|
||||||
ami = "ami-a1b2c3d4"
|
|
||||||
instance_type = "t2.micro"
|
|
||||||
|
|
||||||
# Terraform can infer from this that the instance profile must
|
|
||||||
# be created before the EC2 instance.
|
|
||||||
iam_instance_profile = aws_iam_instance_profile.example
|
|
||||||
|
|
||||||
# However, if software running in this EC2 instance needs access
|
|
||||||
# to the S3 API in order to boot properly, there is also a "hidden"
|
|
||||||
# dependency on the aws_iam_role_policy that Terraform cannot
|
|
||||||
# automatically infer, so it must be declared explicitly:
|
|
||||||
depends_on = [
|
|
||||||
aws_iam_role_policy.example,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The `depends_on` meta-argument, if present, must be a list of references
|
|
||||||
to other resources in the same module. Arbitrary expressions are not allowed
|
|
||||||
in the `depends_on` argument value, because its value must be known before
|
|
||||||
Terraform knows resource relationships and thus before it can safely
|
|
||||||
evaluate expressions.
|
|
||||||
|
|
||||||
The `depends_on` argument should be used only as a last resort. When using it,
|
|
||||||
always include a comment explaining why it is being used, to help future
|
|
||||||
maintainers understand the purpose of the additional dependency.
|
|
||||||
|
|
||||||
### `count`: Multiple Resource Instances By Count
|
|
||||||
|
|
||||||
[inpage-count]: #count-multiple-resource-instances-by-count
|
|
||||||
|
|
||||||
-> **Note:** A given resource block cannot use both `count` and `for_each`.
|
|
||||||
|
|
||||||
By default, a `resource` block configures one real infrastructure object.
|
|
||||||
However, sometimes you want to manage several similar objects, such as a fixed
|
|
||||||
pool of compute instances. Terraform has two ways to do this:
|
|
||||||
`count` and [`for_each`][inpage-for_each].
|
|
||||||
|
|
||||||
> **Hands-on:** Try the [Manage Similar Resources With Count](https://learn.hashicorp.com/tutorials/terraform/count?in=terraform/0-13&utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) tutorial on HashiCorp Learn.
|
|
||||||
|
|
||||||
The `count` meta-argument accepts a whole number, and creates that many
|
|
||||||
instances of the resource. Each instance has a distinct infrastructure object
|
|
||||||
associated with it (as described above in
|
|
||||||
[Resource Behavior](#resource-behavior)), and each is separately created,
|
|
||||||
updated, or destroyed when the configuration is applied.
|
|
||||||
|
|
||||||
```hcl
|
|
||||||
resource "aws_instance" "server" {
|
|
||||||
count = 4 # create four similar EC2 instances
|
|
||||||
|
|
||||||
ami = "ami-a1b2c3d4"
|
|
||||||
instance_type = "t2.micro"
|
|
||||||
|
|
||||||
tags = {
|
|
||||||
Name = "Server ${count.index}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
#### The `count` Object
|
|
||||||
|
|
||||||
In resource blocks where `count` is set, an additional `count` object is
|
|
||||||
available in expressions, so you can modify the configuration of each instance.
|
|
||||||
This object has one attribute:
|
|
||||||
|
|
||||||
- `count.index` — The distinct index number (starting with `0`) corresponding
|
|
||||||
to this instance.
|
|
||||||
|
|
||||||
#### Referring to Instances
|
|
||||||
|
|
||||||
When `count` is set, Terraform distinguishes between the resource block itself
|
|
||||||
and the multiple _resource instances_ associated with it. Instances are
|
|
||||||
identified by an index number, starting with `0`.
|
|
||||||
|
|
||||||
- `<TYPE>.<NAME>` (for example, `aws_instance.server`) refers to the resource block.
|
|
||||||
- `<TYPE>.<NAME>[<INDEX>]` (for example, `aws_instance.server[0]`,
|
|
||||||
`aws_instance.server[1]`, etc.) refers to individual instances.
|
|
||||||
|
|
||||||
This is different from resources without `count` or `for_each`, which can be
|
|
||||||
referenced without an index or key.
|
|
||||||
|
|
||||||
-> **Note:** Within nested `provisioner` or `connection` blocks, the special
|
|
||||||
`self` object refers to the current _resource instance,_ not the resource block
|
|
||||||
as a whole.
|
|
||||||
|
|
||||||
#### Using Expressions in `count`
|
|
||||||
|
|
||||||
The `count` meta-argument accepts numeric [expressions](./expressions.html).
|
|
||||||
However, unlike most resource arguments, the `count` value must be known
|
|
||||||
_before_ Terraform performs any remote resource actions. This means `count`
|
|
||||||
can't refer to any resource attributes that aren't known until after a
|
|
||||||
configuration is applied (such as a unique ID generated by the remote API when
|
|
||||||
an object is created).
|
|
||||||
|
|
||||||
#### When to Use `for_each` Instead of `count`
|
|
||||||
|
|
||||||
If your resource instances are almost identical, `count` is appropriate. If some
|
|
||||||
of their arguments need distinct values that can't be directly derived from an
|
|
||||||
integer, it's safer to use `for_each`.
|
|
||||||
|
|
||||||
Before `for_each` was available, it was common to derive `count` from the
|
|
||||||
length of a list and use `count.index` to look up the original list value:
|
|
||||||
|
|
||||||
```hcl
|
|
||||||
variable "subnet_ids" {
|
|
||||||
type = list(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "aws_instance" "server" {
|
|
||||||
# Create one instance for each subnet
|
|
||||||
count = length(var.subnet_ids)
|
|
||||||
|
|
||||||
ami = "ami-a1b2c3d4"
|
|
||||||
instance_type = "t2.micro"
|
|
||||||
subnet_id = var.subnet_ids[count.index]
|
|
||||||
|
|
||||||
tags = {
|
|
||||||
Name = "Server ${count.index}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
This was fragile, because the resource instances were still identified by their
|
|
||||||
_index_ instead of the string values in the list. If an element was removed from
|
|
||||||
the middle of the list, every instance _after_ that element would see its
|
|
||||||
`subnet_id` value change, resulting in more remote object changes than intended.
|
|
||||||
Using `for_each` gives the same flexibility without the extra churn.
|
|
||||||
|
|
||||||
### `for_each`: Multiple Resource Instances Defined By a Map, or Set of Strings
|
|
||||||
|
|
||||||
[inpage-for_each]: #for_each-multiple-resource-instances-defined-by-a-map-or-set-of-strings
|
|
||||||
|
|
||||||
-> **Version note:** `for_each` was added in Terraform 0.12.6.
|
|
||||||
|
|
||||||
-> **Note:** A given resource block cannot use both `count` and `for_each`.
|
|
||||||
|
|
||||||
By default, a `resource` block configures one real infrastructure object.
|
|
||||||
However, sometimes you want to manage several similar objects, such as a fixed
|
|
||||||
pool of compute instances. Terraform has two ways to do this:
|
|
||||||
[`count`][inpage-count] and `for_each`.
|
|
||||||
|
|
||||||
> **Hands-on:** Try the [Manage Similar Resources With For Each](https://learn.hashicorp.com/tutorials/terraform/for-each?in=terraform/0-13&utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) tutorial on HashiCorp Learn.
|
|
||||||
|
|
||||||
The `for_each` meta-argument accepts a map or a set of strings, and creates an
|
|
||||||
instance for each item in that map or set. Each instance has a distinct
|
|
||||||
infrastructure object associated with it (as described above in
|
|
||||||
[Resource Behavior](#resource-behavior)), and each is separately created,
|
|
||||||
updated, or destroyed when the configuration is applied.
|
|
||||||
|
|
||||||
-> **Note:** The keys of the map (or all the values in the case of a set of strings) must
|
|
||||||
be _known values_, or you will get an error message that `for_each` has dependencies
|
|
||||||
that cannot be determined before apply, and a `-target` may be needed. `for_each` keys
|
|
||||||
cannot be the result (or rely on the result of) of impure functions, including `uuid`, `bcrypt`,
|
|
||||||
or `timestamp`, as their evaluation is deferred resource during evaluation.
|
|
||||||
|
|
||||||
Map:
|
|
||||||
|
|
||||||
```hcl
|
|
||||||
resource "azurerm_resource_group" "rg" {
|
|
||||||
for_each = {
|
|
||||||
a_group = "eastus"
|
|
||||||
another_group = "westus2"
|
|
||||||
}
|
|
||||||
name = each.key
|
|
||||||
location = each.value
|
|
||||||
}
|
|
||||||
```
|
|
||||||
Set of strings:
|
|
||||||
|
|
||||||
```hcl
|
|
||||||
resource "aws_iam_user" "the-accounts" {
|
|
||||||
for_each = toset( ["Todd", "James", "Alice", "Dottie"] )
|
|
||||||
name = each.key
|
|
||||||
}
|
|
||||||
```
|
|
||||||
#### The `each` Object
|
|
||||||
|
|
||||||
In resource blocks where `for_each` is set, an additional `each` object is
|
|
||||||
available in expressions, so you can modify the configuration of each instance.
|
|
||||||
This object has two attributes:
|
|
||||||
|
|
||||||
- `each.key` — The map key (or set member) corresponding to this instance.
|
|
||||||
- `each.value` — The map value corresponding to this instance. (If a set was
|
|
||||||
provided, this is the same as `each.key`.)
|
|
||||||
|
|
||||||
#### Using Expressions in `for_each`
|
|
||||||
|
|
||||||
The `for_each` meta-argument accepts map or set [expressions](./expressions.html).
|
|
||||||
However, unlike most resource arguments, the `for_each` value must be known
|
|
||||||
_before_ Terraform performs any remote resource actions. This means `for_each`
|
|
||||||
can't refer to any resource attributes that aren't known until after a
|
|
||||||
configuration is applied (such as a unique ID generated by the remote API when
|
|
||||||
an object is created).
|
|
||||||
|
|
||||||
The `for_each` value must be a map or set with one element per desired
|
|
||||||
resource instance. When providing a set, you must use an expression that
|
|
||||||
explicitly returns a set value, like the [`toset`](/docs/configuration/functions/toset.html)
|
|
||||||
function; to prevent unwanted surprises during conversion, the `for_each`
|
|
||||||
argument does not implicitly convert lists or tuples to sets.
|
|
||||||
If you need to declare resource instances based on a nested
|
|
||||||
data structure or combinations of elements from multiple data structures you
|
|
||||||
can use Terraform expressions and functions to derive a suitable value.
|
|
||||||
For example:
|
|
||||||
|
|
||||||
* Transform a multi-level nested structure into a flat list by
|
|
||||||
[using nested `for` expressions with the `flatten` function](./functions/flatten.html#flattening-nested-structures-for-for_each).
|
|
||||||
* Produce an exhaustive list of combinations of elements from two or more
|
|
||||||
collections by
|
|
||||||
[using the `setproduct` function inside a `for` expression](./functions/setproduct.html#finding-combinations-for-for_each).
|
|
||||||
|
|
||||||
#### Referring to Instances
|
|
||||||
|
|
||||||
When `for_each` is set, Terraform distinguishes between the resource block itself
|
|
||||||
and the multiple _resource instances_ associated with it. Instances are
|
|
||||||
identified by a map key (or set member) from the value provided to `for_each`.
|
|
||||||
|
|
||||||
- `<TYPE>.<NAME>` (for example, `azurerm_resource_group.rg`) refers to the resource block.
|
|
||||||
- `<TYPE>.<NAME>[<KEY>]` (for example, `azurerm_resource_group.rg["a_group"]`,
|
|
||||||
`azurerm_resource_group.rg["another_group"]`, etc.) refers to individual instances.
|
|
||||||
|
|
||||||
This is different from resources without `count` or `for_each`, which can be
|
|
||||||
referenced without an index or key.
|
|
||||||
|
|
||||||
-> **Note:** Within nested `provisioner` or `connection` blocks, the special
|
|
||||||
`self` object refers to the current _resource instance,_ not the resource block
|
|
||||||
as a whole.
|
|
||||||
|
|
||||||
#### Using Sets
|
|
||||||
|
|
||||||
The Terraform language doesn't have a literal syntax for
|
|
||||||
[set values](./types.html#collection-types), but you can use the `toset`
|
|
||||||
function to explicitly convert a list of strings to a set:
|
|
||||||
|
|
||||||
```hcl
|
|
||||||
locals {
|
|
||||||
subnet_ids = toset([
|
|
||||||
"subnet-abcdef",
|
|
||||||
"subnet-012345",
|
|
||||||
])
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "aws_instance" "server" {
|
|
||||||
for_each = local.subnet_ids
|
|
||||||
|
|
||||||
ami = "ami-a1b2c3d4"
|
|
||||||
instance_type = "t2.micro"
|
|
||||||
subnet_id = each.key # note: each.key and each.value are the same for a set
|
|
||||||
|
|
||||||
tags = {
|
|
||||||
Name = "Server ${each.key}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Conversion from list to set discards the ordering of the items in the list and
|
|
||||||
removes any duplicate elements. `toset(["b", "a", "b"])` will produce a set
|
|
||||||
containing only `"a"` and `"b"` in no particular order; the second `"b"` is
|
|
||||||
discarded.
|
|
||||||
|
|
||||||
If you are writing a module with an [input variable](./variables.html) that
|
|
||||||
will be used as a set of strings for `for_each`, you can set its type to
|
|
||||||
`set(string)` to avoid the need for an explicit type conversion:
|
|
||||||
|
|
||||||
```
|
|
||||||
variable "subnet_ids" {
|
|
||||||
type = set(string)
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "aws_instance" "server" {
|
|
||||||
for_each = var.subnet_ids
|
|
||||||
|
|
||||||
# (and the other arguments as above)
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `provider`: Selecting a Non-default Provider Configuration
|
|
||||||
|
|
||||||
[inpage-provider]: #provider-selecting-a-non-default-provider-configuration
|
|
||||||
|
|
||||||
The `provider` meta-argument specifies which provider configuration to use,
|
|
||||||
overriding Terraform's default behavior of selecting one based on the resource
|
|
||||||
type name. Its value should be an unquoted `<PROVIDER>.<ALIAS>` reference.
|
|
||||||
|
|
||||||
As described in [Provider Configuration](./providers.html), you can optionally
|
|
||||||
create multiple configurations for a single provider (usually to manage
|
|
||||||
resources in different regions of multi-region services). Each provider can have
|
|
||||||
one default configuration, and any number of alternate configurations that
|
|
||||||
include an extra name segment (or "alias").
|
|
||||||
|
|
||||||
By default, Terraform interprets the initial word in the resource type name
|
|
||||||
(separated by underscores) as the local name of a provider, and uses that
|
|
||||||
provider's default configuration. For example, the resource type
|
|
||||||
`google_compute_instance` is associated automatically with the default
|
|
||||||
configuration for the provider named `google`.
|
|
||||||
|
|
||||||
By using the `provider` meta-argument, you can select an alternate provider
|
|
||||||
configuration for a resource:
|
|
||||||
|
|
||||||
```hcl
|
|
||||||
# default configuration
|
|
||||||
provider "google" {
|
|
||||||
region = "us-central1"
|
|
||||||
}
|
|
||||||
|
|
||||||
# alternate configuration, whose alias is "europe"
|
|
||||||
provider "google" {
|
|
||||||
alias = "europe"
|
|
||||||
region = "europe-west1"
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "google_compute_instance" "example" {
|
|
||||||
# This "provider" meta-argument selects the google provider
|
|
||||||
# configuration whose alias is "europe", rather than the
|
|
||||||
# default configuration.
|
|
||||||
provider = google.europe
|
|
||||||
|
|
||||||
# ...
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
A resource always has an implicit dependency on its associated provider, to
|
|
||||||
ensure that the provider is fully configured before any resource actions
|
|
||||||
are taken.
|
|
||||||
|
|
||||||
The `provider` meta-argument expects
|
|
||||||
[a `<PROVIDER>.<ALIAS>` reference](./providers.html#referring-to-alternate-providers),
|
|
||||||
which does not need to be quoted. Arbitrary expressions are not permitted for
|
|
||||||
`provider` because it must be resolved while Terraform is constructing the
|
|
||||||
dependency graph, before it is safe to evaluate expressions.
|
|
||||||
|
|
||||||
### `lifecycle`: Lifecycle Customizations
|
|
||||||
|
|
||||||
[inpage-lifecycle]: #lifecycle-lifecycle-customizations
|
|
||||||
|
|
||||||
The general lifecycle for resources is described above in the
|
|
||||||
[Resource Behavior](#resource-behavior) section. Some details of that behavior
|
|
||||||
can be customized using the special nested `lifecycle` block within a resource
|
|
||||||
block body:
|
|
||||||
|
|
||||||
```
|
|
||||||
resource "azurerm_resource_group" "example" {
|
|
||||||
# ...
|
|
||||||
|
|
||||||
lifecycle {
|
|
||||||
create_before_destroy = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The `lifecycle` block and its contents are meta-arguments, available
|
|
||||||
for all `resource` blocks regardless of type. The following lifecycle
|
|
||||||
meta-arguments are supported:
|
|
||||||
|
|
||||||
* `create_before_destroy` (bool) - By default, when Terraform must make a
|
|
||||||
change to a resource argument that cannot be updated in-place due to
|
|
||||||
remote API limitations, Terraform will instead destroy the existing object
|
|
||||||
and then create a new replacement object with the new configured arguments.
|
|
||||||
|
|
||||||
The `create_before_destroy` meta-argument changes this behavior so that
|
|
||||||
the new replacement object is created _first,_ and then the prior object
|
|
||||||
is destroyed only once the replacement is created.
|
|
||||||
|
|
||||||
This is an opt-in behavior because many remote object types have unique
|
|
||||||
name requirements or other constraints that must be accommodated for
|
|
||||||
both a new and an old object to exist concurrently. Some resource types
|
|
||||||
offer special options to append a random suffix onto each object name to
|
|
||||||
avoid collisions, for example. Terraform CLI cannot automatically activate
|
|
||||||
such features, so you must understand the constraints for each resource
|
|
||||||
type before using `create_before_destroy` with it.
|
|
||||||
|
|
||||||
* `prevent_destroy` (bool) - This meta-argument, when set to `true`, will
|
|
||||||
cause Terraform to reject with an error any plan that would destroy the
|
|
||||||
infrastructure object associated with the resource, as long as the argument
|
|
||||||
remains present in the configuration.
|
|
||||||
|
|
||||||
This can be used as a measure of safety against the accidental replacement
|
|
||||||
of objects that may be costly to reproduce, such as database instances.
|
|
||||||
However, it will make certain configuration changes impossible to apply,
|
|
||||||
and will prevent the use of the `terraform destroy` command once such
|
|
||||||
objects are created, and so this option should be used sparingly.
|
|
||||||
|
|
||||||
Since this argument must be present in configuration for the protection to
|
|
||||||
apply, note that this setting does not prevent the remote object from
|
|
||||||
being destroyed if the `resource` block were removed from configuration
|
|
||||||
entirely: in that case, the `prevent_destroy` setting is removed along
|
|
||||||
with it, and so Terraform will allow the destroy operation to succeed.
|
|
||||||
|
|
||||||
* `ignore_changes` (list of attribute names) - By default, Terraform detects
|
|
||||||
any difference in the current settings of a real infrastructure object
|
|
||||||
and plans to update the remote object to match configuration.
|
|
||||||
|
|
||||||
The `ignore_changes` feature is intended to be used when a resource is
|
|
||||||
created with references to data that may change in the future, but should
|
|
||||||
not effect said resource after its creation. In some rare cases, settings
|
|
||||||
of a remote object are modified by processes outside of Terraform, which
|
|
||||||
Terraform would then attempt to "fix" on the next run. In order to make
|
|
||||||
Terraform share management responsibilities of a single object with a
|
|
||||||
separate process, the `ignore_changes` meta-argument specifies resource
|
|
||||||
attributes that Terraform should ignore when planning updates to the
|
|
||||||
associated remote object.
|
|
||||||
|
|
||||||
The arguments corresponding to the given attribute names are considered
|
|
||||||
when planning a _create_ operation, but are ignored when planning an
|
|
||||||
_update_. The arguments are the relative address of the attributes in the
|
|
||||||
resource. Map and list elements can be referenced using index notation,
|
|
||||||
like `tags["Name"]` and `list[0]` respectively.
|
|
||||||
|
|
||||||
|
|
||||||
```hcl
|
|
||||||
resource "aws_instance" "example" {
|
|
||||||
# ...
|
|
||||||
|
|
||||||
lifecycle {
|
|
||||||
ignore_changes = [
|
|
||||||
# Ignore changes to tags, e.g. because a management agent
|
|
||||||
# updates these based on some ruleset managed elsewhere.
|
|
||||||
tags,
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Instead of a list, the special keyword `all` may be used to instruct
|
|
||||||
Terraform to ignore _all_ attributes, which means that Terraform can
|
|
||||||
create and destroy the remote object but will never propose updates to it.
|
|
||||||
|
|
||||||
Only attributes defined by the resource type can be ignored.
|
|
||||||
`ignore_changes` cannot be applied to itself or to any other meta-arguments.
|
|
||||||
|
|
||||||
The `lifecycle` settings all effect how Terraform constructs and traverses
|
|
||||||
the dependency graph. As a result, only literal values can be used because
|
|
||||||
the processing happens too early for arbitrary expression evaluation.
|
|
||||||
|
|
||||||
### `provisioner` and `connection`: Resource Provisioners
|
|
||||||
|
|
||||||
[inpage-provisioner]: #provisioner-and-connection-resource-provisioners
|
|
||||||
|
|
||||||
> **Hands-on:** To learn about more declarative ways to handle provisioning actions, try the [Provision Infrastructure Deployed with Terraform](https://learn.hashicorp.com/collections/terraform/provision?utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) collection on HashiCorp Learn.
|
|
||||||
|
|
||||||
Some infrastructure objects require some special actions to be taken after they
|
|
||||||
are created before they can become fully functional. For example, compute
|
|
||||||
instances may require configuration to be uploaded or a configuration management
|
|
||||||
program to be run before they can begin their intended operation.
|
|
||||||
|
|
||||||
Create-time actions like these can be described using _resource provisioners_.
|
|
||||||
A provisioner is another type of plugin supported by Terraform, and each
|
|
||||||
provisioner takes a different kind of action in the context of a resource
|
|
||||||
being created.
|
|
||||||
|
|
||||||
Provisioning steps should be used sparingly, since they represent
|
|
||||||
non-declarative actions taken during the creation of a resource and so
|
|
||||||
Terraform is not able to model changes to them as it can for the declarative
|
|
||||||
portions of the Terraform language.
|
|
||||||
|
|
||||||
Provisioners can also be defined to run when a resource is _destroyed_, with
|
|
||||||
certain limitations.
|
|
||||||
|
|
||||||
The `provisioner` and `connection` block types within `resource` blocks are
|
|
||||||
meta-arguments available across all resource types. Provisioners and their
|
|
||||||
usage are described in more detail in
|
|
||||||
[the Provisioners section](/docs/provisioners/index.html).
|
|
||||||
|
|
||||||
## Local-only Resources
|
|
||||||
|
|
||||||
While most resource types correspond to an infrastructure object type that
|
|
||||||
is managed via a remote network API, there are certain specialized resource
|
|
||||||
types that operate only within Terraform itself, calculating some results and
|
|
||||||
saving those results in the state for future use.
|
|
||||||
|
|
||||||
For example, local-only resource types exist for
|
|
||||||
[generating private keys](/docs/providers/tls/r/private_key.html),
|
|
||||||
[issuing self-signed TLS certificates](/docs/providers/tls/r/self_signed_cert.html),
|
|
||||||
and even [generating random ids](/docs/providers/random/r/id.html).
|
|
||||||
While these resource types often have a more marginal purpose than those
|
|
||||||
managing "real" infrastructure objects, they can be useful as glue to help
|
|
||||||
connect together other resources.
|
|
||||||
|
|
||||||
The behavior of local-only resources is the same as all other resources, but
|
|
||||||
their result data exists only within the Terraform state. "Destroying" such
|
|
||||||
a resource means only to remove it from the state, discarding its data.
|
|
||||||
|
|
||||||
## Operation Timeouts
|
|
||||||
|
|
||||||
Some resource types provide a special `timeouts` nested block argument that
|
|
||||||
allows you to customize how long certain operations are allowed to take
|
|
||||||
before being considered to have failed.
|
|
||||||
For example, [`aws_db_instance`](/docs/providers/aws/r/db_instance.html)
|
|
||||||
allows configurable timeouts for `create`, `update` and `delete` operations.
|
|
||||||
|
|
||||||
Timeouts are handled entirely by the resource type implementation in the
|
|
||||||
provider, but resource types offering these features follow the convention
|
|
||||||
of defining a child block called `timeouts` that has a nested argument
|
|
||||||
named after each operation that has a configurable timeout value.
|
|
||||||
Each of these arguments takes a string representation of a duration, such
|
|
||||||
as `"60m"` for 60 minutes, `"10s"` for ten seconds, or `"2h"` for two hours.
|
|
||||||
|
|
||||||
```hcl
|
|
||||||
resource "aws_db_instance" "example" {
|
|
||||||
# ...
|
|
||||||
|
|
||||||
timeouts {
|
|
||||||
create = "60m"
|
|
||||||
delete = "2h"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The set of configurable operations is chosen by each resource type. Most
|
|
||||||
resource types do not support the `timeouts` block at all. Consult the
|
|
||||||
documentation for each resource type to see which operations it offers
|
|
||||||
for configuration, if any.
|
|
||||||
|
|
|
@ -50,7 +50,36 @@
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="/docs/configuration/resources.html">Resource Blocks</a>
|
<a href="/docs/configuration/blocks/resources/syntax.html">Resource Blocks</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a href="/docs/configuration/blocks/resources/behavior.html">Resource Behavior</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a href="#">Meta-Arguments</a>
|
||||||
|
<ul class="nav nav-auto-expand">
|
||||||
|
<li>
|
||||||
|
<a href="/docs/configuration/meta-arguments/depends_on.html"><code>depends_on</code></a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a href="/docs/configuration/meta-arguments/count.html"><code>count</code></a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a href="/docs/configuration/meta-arguments/for_each.html"><code>for_each</code></a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a href="/docs/configuration/meta-arguments/resource-provider.html"><code>provider</code></a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a href="/docs/configuration/meta-arguments/lifecycle.html"><code>lifecycle</code></a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
|
|
Loading…
Reference in New Issue