website: Structural edit of configuration language docs

This commit is a wide-ranging set of edits to the pages under
/docs/configuration. Among other things, it

- Separates style conventions out into their own page.
- Separates type constraints and conversion info into their own page.
- Conflates similar complex types a little more freely, since the distinction is
  only relevant when restricting inputs for a reusable module or resource.
- Clarifies several concepts that confused me during edits.
This commit is contained in:
Nick Fagerlund 2018-12-10 16:14:33 -08:00 committed by Nick Fagerlund
parent e39c69750c
commit d2abdc23ac
22 changed files with 1141 additions and 723 deletions

View File

@ -13,8 +13,8 @@ in Terraform configuration. Use of data sources allows a Terraform
configuration to make use of information defined outside of Terraform, configuration to make use of information defined outside of Terraform,
or defined by another separate Terraform configuration. or defined by another separate Terraform configuration.
Each [provider](/docs/configuration/providers.html) make offer data sources Each [provider](./providers.html) may offer data sources
alongside its set of [resource types](/docs/configuration/resources.html#resource-types-and-arguments). alongside its set of [resource types](./resources.html#resource-types-and-arguments).
## Using Data Sources ## Using Data Sources
@ -60,14 +60,14 @@ Each data resource is associated with a single data source, which determines
the kind of object (or objects) it reads and what query constraint arguments the kind of object (or objects) it reads and what query constraint arguments
are available. are available.
Each data source in turn belongs to a [provider](/docs/configuration/providers.html), Each data source in turn belongs to a [provider](./providers.html),
which is a plugin for Terraform that offers a collection of resource types and which is a plugin for Terraform that offers a collection of resource types and
data sources that most often belong to a single cloud or on-premises data sources that most often belong to a single cloud or on-premises
infrastructure platform. infrastructure platform.
Most of the items within the body of a `data` block are defined by and Most of the items within the body of a `data` block are defined by and
specific to the selected data source, and these arguments can make full specific to the selected data source, and these arguments can make full
use of [expressions](/docs/configuration/expressions.html) and other dynamic use of [expressions](./expressions.html) and other dynamic
Terraform language features. Terraform language features.
However, there are some "meta-arguments" that are defined by Terraform itself However, there are some "meta-arguments" that are defined by Terraform itself
@ -109,7 +109,7 @@ operation, and is re-calulated each time a new plan is created.
## Data Resource Dependencies ## Data Resource Dependencies
Data resources have the same dependency resolution behavior Data resources have the same dependency resolution behavior
[as defined for managed resources](/docs/configuration/resources.html#resource-dependencies). [as defined for managed resources](./resources.html#resource-dependencies).
In particular, the `depends_on` meta-argument is also available within `data` In particular, the `depends_on` meta-argument is also available within `data`
blocks, with the same meaning and syntax as in `resource` blocks. blocks, with the same meaning and syntax as in `resource` blocks.
@ -125,7 +125,7 @@ resources.
## Multiple Resource Instances ## Multiple Resource Instances
Data resources support [the `count` meta-argument](/docs/configuration/resources.html#multiple-resource-instances) Data resources support [the `count` meta-argument](./resources.html#count-multiple-resource-instances)
as defined for managed resources, with the same syntax and behavior. as defined for managed resources, with the same syntax and behavior.
As with managed resources, when `count` is present it is important to As with managed resources, when `count` is present it is important to
@ -135,7 +135,7 @@ own variant of the constraint arguments, producing an indexed result.
## Selecting a Non-default Provider Configuration ## Selecting a Non-default Provider Configuration
Data resources support [the `providers` meta-argument](/docs/configuration/resources.html#selecting-a-non-default-provider-configuration) Data resources support [the `providers` meta-argument](./resources.html#provider-selecting-a-non-default-provider-configuration)
as defined for managed resources, with the same syntax and behavior. as defined for managed resources, with the same syntax and behavior.
## Lifecycle Customizations ## Lifecycle Customizations
@ -167,8 +167,8 @@ data "aws_ami" "web" {
## Description ## Description
The `data` block creates a data instance of the given `TYPE` (first The `data` block creates a data instance of the given _type_ (first
parameter) and `NAME` (second parameter). The combination of the type block label) and _name_ (second block label). The combination of the type
and name must be unique. and name must be unique.
Within the block (the `{ }`) is configuration for the data instance. The Within the block (the `{ }`) is configuration for the data instance. The
@ -176,24 +176,27 @@ configuration is dependent on the type, and is documented for each
data source in the [providers section](/docs/providers/index.html). data source in the [providers section](/docs/providers/index.html).
Each data instance will export one or more attributes, which can be Each data instance will export one or more attributes, which can be
interpolated into other resources using variables of the form used in other resources as reference expressions of the form
`data.TYPE.NAME.ATTR`. For example: `data.<TYPE>.<NAME>.<ATTRIBUTE>`. For example:
```hcl ```hcl
resource "aws_instance" "web" { resource "aws_instance" "web" {
ami = "${data.aws_ami.web.id}" ami = data.aws_ami.web.id
instance_type = "t1.micro" instance_type = "t1.micro"
} }
``` ```
### Meta-parameters ## Meta-Arguments
As data sources are essentially a read only subset of resources they also support the same [meta-parameters](https://www.terraform.io/docs/configuration/resources.html#meta-parameters) of resources except for the [`lifecycle` configuration block](https://www.terraform.io/docs/configuration/resources.html#lifecycle). As data sources are essentially a read only subset of resources, they also
support the same [meta-arguments](./resources.html#meta-arguments) of resources
with the exception of the
[`lifecycle` configuration block](./resources.html#lifecycle-lifecycle-customizations).
## Multiple Provider Instances ### Multiple Provider Instances
Similarly to [resources](/docs/configuration/resources.html), the Similarly to [resources](./resources.html), the
`provider` meta-parameter can be used where a configuration has `provider` meta-argument can be used where a configuration has
multiple aliased instances of the same provider: multiple aliased instances of the same provider:
```hcl ```hcl
@ -204,10 +207,10 @@ data "aws_ami" "web" {
} }
``` ```
See the ["Multiple Provider Instances"](/docs/configuration/resources.html#multiple-provider-instances) documentation for resources See [Resources: Multiple Provider Instances](./resources.html#provider-selecting-a-non-default-provider-configuration)
for more information. for more information.
## Data Source Lifecycle ### Data Source Lifecycle
If the arguments of a data instance contain no references to computed values, If the arguments of a data instance contain no references to computed values,
such as attributes of resources that have not yet been created, then the such as attributes of resources that have not yet been created, then the

View File

@ -16,14 +16,17 @@ references to data exported by resources, arithmetic, conditional evaluation,
and a number of built-in functions. and a number of built-in functions.
Expressions can be used in a number of places in the Terraform language, Expressions can be used in a number of places in the Terraform language,
but some contexts place restrictions on which expression constructs are allowed, but some contexts limit which expression constructs are allowed,
such as requiring a literal value of a particular type, or forbidding such as requiring a literal value of a particular type or forbidding
references to resource attributes. The other pages in this section describe references to resource attributes. Each language feature's documentation
the contexts where expressions may be used and which expression features describes any restrictions it places on expressions.
are allowed in each case.
The following sections describe all of the features of the configuration You can experiment with the behavior of Terraform's expressions from
syntax. the Terraform expression console, by running
[the `terraform console` command](/docs/commands/console.html).
The rest of this page describes all of the features of Terraform's
expression syntax.
## Types and Values ## Types and Values
@ -31,180 +34,186 @@ The result of an expression is a _value_. All values have a _type_, which
dictates where that value can be used and what transformations can be dictates where that value can be used and what transformations can be
applied to it. applied to it.
A _literal expression_ is an expression that directly represents a particular The Terraform language uses the following types for its values:
constant value.
Expressions are most commonly used to set the values of arguments to resources
and to child modules. In these cases, the argument itself has an expected
type and so the given expression must produce a value of that type. Where
possible, Terraform will automatically convert values from one type to another
in order to produce the expected type. If this isn't possible, Terraform will
produce a type mismatch error and you must update the configuration with
a more suitable expression.
This section describes all of the value types in the Terraform language, and
the literal expression syntax that can be used to create values of each
type.
### Primitive Types
A _primitive_ type is a simple type that isn't made from any other types.
The available primitive types in the Terraform language are:
* `string`: a sequence of Unicode characters representing some text, such
as `"hello"`.
* `string`: a sequence of Unicode characters representing some text, like
`"hello"`.
* `number`: a numeric value. The `number` type can represent both whole * `number`: a numeric value. The `number` type can represent both whole
numbers like `15` and fractional values such as `6.283185`. numbers like `15` and fractional values like `6.283185`.
* `bool`: either `true` or `false`. `bool` values can be used in conditional * `bool`: either `true` or `false`. `bool` values can be used in conditional
logic. logic.
* `list` (or `tuple`): a sequence of values, like
`["us-west-1a", "us-west-1c"]`. Elements in a list or tuple are identified by
consecutive whole numbers, starting with zero.
* `map` (or `object`): a group of values identified by named labels, like
`{name = "Mabel", age = 52}`.
The Terraform language will automatically convert `number` and `bool` values Strings, numbers, and bools are sometimes called _primitive types._ Lists/tuples and maps/objects are sometimes called _complex types,_ _structural types,_ or _collection types._
to `string` values when needed, and vice-versa as long as the string contains
a valid representation of a number of boolean value. Finally, there is one special value that has _no_ type:
* `null`: a value that represents _absence_ or _omission._ If you set an
argument of a resource or module to `null`, Terraform behaves as though you
had completely omitted it — it will use the argument's default value if it has
one, or raise an error if the argument is mandatory. `null` is most useful in
conditional expressions, so you can dynamically omit an argument if a
condition isn't met.
### Advanced Type Details
In most situations, lists and tuples behave identically, as do maps and objects.
Whenever the distinction isn't relevant, the Terraform documentation uses each
pair of terms interchangeably (with a historical preference for "list" and
"map").
However, module authors and provider developers should understand the
differences between these similar types (and the related `set` type), since they
offer different ways to restrict the allowed values for input variables and
resource arguments.
For complete details about these types (and an explanation of why the difference
usually doesn't matter), see [Type Constraints](./types.html).
### Type Conversion
Expressions are most often used to set values for the arguments of resources and
child modules. In these cases, the argument has an expected type and the given
expression must produce a value of that type.
Where possible, Terraform automatically converts values from one type to
another in order to produce the expected type. If this isn't possible, Terraform
will produce a type mismatch error and you must update the configuration with a
more suitable expression.
Terraform automatically converts number and bool values to strings when needed.
It also converts strings to numbers or bools, as long as the string contains a
valid representation of a number or bool value.
* `true` converts to `"true"`, and vice-versa * `true` converts to `"true"`, and vice-versa
* `false` converts to `"false"`, and vice-versa * `false` converts to `"false"`, and vice-versa
* `15` converts to `"15"`, and vice-versa * `15` converts to `"15"`, and vice-versa
### Collection Types ## Literal Expressions
A _collection_ type allows multiple values of another type to be grouped A _literal expression_ is an expression that directly represents a particular
together as a single value. The type of value _within_ a collection is called constant value. Terraform has a literal expression syntax for each of the value
its _element type_, and all collection types must have an element type. types described above:
For example, the type `list(string)` means "list of strings", which is a * Strings are usually represented by a double-quoted sequence of Unicode
different type than `list(number)`, a list of numbers. All elements of a characters, `"like this"`. There is also a "heredoc" syntax for more complex
collection must always be of the same type. strings. String literals are the most complex kind of literal expression in
Terraform, and have additional documentation on this page:
* See [String Literals](#string-literals) below for information about escape
sequences and the heredoc syntax.
* See [String Templates](#string-templates) below for information about
interpolation and template directives.
* Numbers are represented by unquoted sequences of digits with or without a
decimal point, like `15` or `6.283185`.
* Bools are represented by the unquoted symbols `true` and `false`.
* The null value is represented by the unquoted symbol `null`.
* Lists/tuples are represented by a pair of square brackets containing a
comma-separated sequence of values, like `["a", 15, true]`.
The three _collection type kinds_ in the Terraform language are: List literals can be split into multiple lines for readability, but always
require a comma between values. A comma after the final value is allowed,
but not required. Values in a list can be arbitrary expressions.
* Maps/objects are represented by a pair of curly braces containing a series of
`<KEY> = <VALUE>` pairs:
* `list(...)`: a sequence of values identified by consecutive whole numbers ```hcl
starting with zero. {
* `map(...)`: a collection of values where each is identified by a string label. name = "John"
* `set(...)`: a collection of unique values that do not have any secondary age = 52
identifiers or ordering. }
```
There is no direct syntax for creating collection type values, but the Key/value pairs can be separated by either a comma or a line break. Values
Terraform language can automatically convert a structural type value (as can be arbitrary expressions. Keys are strings; they can be left unquoted if
defined in the next section) to a similar collection type as long as all they are a valid [identifier](./syntax.html#identifiers), but must be quoted
of its elements can be converted to the required element type. otherwise. You can use a non-literal expression as a key by wrapping it in
parentheses, like `(var.business_unit_tag_name) = "SRE"`.
### Structural Types ## Indices and Attributes
A _structural_ type is another way to combine multiple values into a single [inpage-index]: #indices-and-attributes
value, but structural types allow each value to be of a distinct type.
The two _structural type kinds_ in the Terraform language are: Elements of list/tuple and map/object values can be accessed using
the square-bracket index notation, like `local.list[3]`. The expression within
the brackets must be a whole number for list and tuple values or a string
for map and object values.
* `object(...)`: has named attributes that each have their own type. Map/object attributes with names that are valid identifiers can also be accessed
* `tuple(...)`: has a sequence of elements identified by consecutive whole using the dot-separated attribute notation, like `local.object.attrname`.
numbers starting with zero, where each element has its own type. In cases where a map might contain arbitrary user-specified keys, we recommend
using only the square-bracket index notation (`local.map["keyname"]`).
An object type value can be created using an object expression: ## References to Named Values
```hcl Terraform makes several kinds of named values available. Each of these names is
{ an expression that references the associated value; you can use them as
name = "John" standalone expressions, or combine them with other expressions to compute new
age = 52 values.
}
```
The type of the object value created by this expression is The following named values are available:
`object({name=string,age=number})`. In most cases it is not important to know
the exact type of an object value, since the Terraform language automatically
checks and converts object types when needed.
Similarly, a tuple type value can be created using a tuple expression: * `<RESOURCE TYPE>.<NAME>` is an object representing a
[managed resource](./resources.html) of the given type
and name. The attributes of the resource can be accessed using
[dot or square bracket notation][inpage-index].
```hcl Any named value that does not match another pattern listed below
["a", 15, true] will be interpreted by Terraform as a reference to a managed resource.
```
The type of the tuple value created by this expression is
`tuple([string, number, bool])`. Tuple values are rarely used directly in
the Terraform language, and are instead usually converted immediately to
list values by converting all of the elements to the same type.
Terraform will automatically convert object values to map values when required,
so usually object and map values can be used interchangably as long as their
contained values are of suitable types.
Likewise, Terraform will automatically convert tuple values to list values
when required, and so tuple and list values can be used interchangably in
most cases too.
Because of these automatic conversions, it is common to not make a strong
distinction between object and map or tuple and list in everyday discussion
of the Terraform language. The Terraform documentation usually discusses the
object and tuple types only in rare cases where it is important to distinguish
them from the map and list types.
## References to Named Objects
A number of different named objects can be accessed from Terraform expressions.
For example, resources are available in expressions as named objects that have
an object value corresponding to the schema of their resource type, accessed by
a dot-separated sequence of names like `aws_instance.example`.
The following named objects are available:
* `TYPE.NAME` is an object representing a
[managed resource](/docs/configuration/resources.html) of the given type
and name. If the resource has the `count` argument set, the value is
a list of objects representing its instances. Any named object that does
not match one of the other patterns listed below will be interpreted by
Terraform as a reference to a managed resource.
* `var.NAME` is the value of the
[input variable](/docs/configuration/variables.html) of the given name.
* `local.NAME` is the value of the
[local value](/docs/configuration/locals.html) of the given name.
* `module.MOD_NAME.OUTPUT_NAME` is the value of the
[output value](/docs/configuration/outputs.html) of the given name from the
[child module call](/docs/configuration/modules.html) of the given name.
* `data.SOURCE.NAME` is an object representing a
[data resource](/docs/configuration/data-sources.html) of the given data
source and name. If the resource has the `count` argument set, the value is
a list of objects representing its instances.
* `path.` is the prefix of a set of named objects that are filesystem
paths of various kinds:
* `path.module` is the filesystem path of the module where the expression
is placed.
* `path.root` is the filesystem path of the root module of the configuration.
* `path.cwd` is the filesystem path of the current working directory. In
normal use of Terraform this is the same as `path.root`, but some advanced
uses of Terraform run it from a directory other than the root module
directory, causing these paths to be different.
If the resource has the `count` argument set, the value of this expression
is a _list_ of objects representing its instances.
* `var.<NAME>` is the value of the
[input variable](./variables.html) of the given name.
* `local.<NAME>` is the value of the
[local value](./locals.html) of the given name.
* `module.<MODULE NAME>.<OUTPUT NAME>` is the value of the specified
[output value](./outputs.html) from a
[child module](./modules.html) called by the current module.
* `data.<DATA TYPE>.<NAME>` is an object representing a
[data resource](./data-sources.html) of the given data
source type and name. If the resource has the `count` argument set, the value
is a list of objects representing its instances.
* `path.module` is the filesystem path of the module where the expression
is placed.
* `path.root` is the filesystem path of the root module of the configuration.
* `path.cwd` is the filesystem path of the current working directory. In
normal use of Terraform this is the same as `path.root`, but some advanced
uses of Terraform run it from a directory other than the root module
directory, causing these paths to be different.
* `terraform.workspace` is the name of the currently selected * `terraform.workspace` is the name of the currently selected
[workspace](/docs/state/workspaces.html). [workspace](/docs/state/workspaces.html).
Terraform analyses the block bodies of constructs such as resources and module Although many of these names use dot-separated paths that resemble
calls to automatically infer dependencies between objects from the use of [attribute notation][inpage-index] for elements of object values, they are not
some of these reference types in expressions. For example, an object with an implemented as real objects. This means you must use them exactly as written:
argument expression that refers to a managed resource creates and implicit you cannot use square-bracket notation to replace the dot-separated paths, and
dependency between that object and the resource. you cannot iterate over the "parent object" of a named entity (for example, you
cannot use `aws_instance` in a `for` expression).
The first name in each of these dot-separated sequence is called a ### Named Values and Dependencies
_variable_, but do not confuse this with the idea of an
[input variable](/docs/configuration/variables.html), which acts as a
customization parameter for a module. Input variables are often referred
to as just "variables" for brevity when the meaning is clear from context,
but due to this other meaning of "variable" in the context of expressions
this documentation page will always refer to input variables by their full
name.
Additional expression variables are available in specific contexts. These are Constructs like resources and module calls often use references to named values
described in other documentation sections describing those specific features. in their block bodies, and Terraform analyzes these expressions to automatically
infer dependencies between objects. For example, an expression in a resource
argument that refers to another managed resource creates an implicit dependency
between the two resources.
### Local Named Values
Within the bodies of certain expressions, or in some other specific contexts,
there are other named values available beyond the global values listed above.
(For example, the body of a resource block where `count` is set can use a
special `count.index` value.) These local names are described in the
documentation for the specific contexts where they appear.
-> **Note:** Local named values are often referred to as _variables_ or
_temporary variables_ in their documentation. These are not [input
variables](./variables.html); they are just arbitrary names
that temporarily represent a value.
### Values Not Yet Known ### Values Not Yet Known
@ -247,25 +256,11 @@ effect:
Unknown values appear in the `terraform plan` output as `(not yet known)`. Unknown values appear in the `terraform plan` output as `(not yet known)`.
## Indices and Attributes
Elements of list-, tuple-, map-, and object-typed values can be accessed using
the square-bracket index notation, like `local.list[3]`. The expression within
the brackets must be a whole number for list and tuple values or a string
for map and object values.
Object attributes with names that are valid identifiers can also be accessed
using the dot-separated attribute notation, like `local.object.attrname`. This
syntax is also allowed for accessing map elements with keys that are valid
identifiers, but we recommend using the square-bracket index notation
(`local.map["keyname"]`) when a map contains arbitrary user-specified keys, as
opposed to an object with a fixed set of attributes defined by a schema.
## Arithmetic and Logical Operators ## Arithmetic and Logical Operators
An _operator_ is a type of expression that transforms or combines one or more An _operator_ is a type of expression that transforms or combines one or more
other expressions. Operators either combine two values in some way to other expressions. Operators either combine two values in some way to
produce a third result value, or simply transform a single given value to produce a third result value, or transform a single given value to
produce a single result. produce a single result.
Operators that work on two values place an operator symbol between the two Operators that work on two values place an operator symbol between the two
@ -278,16 +273,15 @@ which are similar to operators in programming languages such as JavaScript
or Ruby. or Ruby.
When multiple operators are used together in an expression, they are evaluated When multiple operators are used together in an expression, they are evaluated
according to a default order of operations: in the following order of operations:
| Level | Operators | 1. `!`, `-` (multiplication by `-1`)
| ----- | -------------------- | 1. `*`, `/`, `%`
| 6 | `*`, `/`, `%` | 1. `+`, `-` (subtraction)
| 5 | `+`, `-` | 1. `>`, `>=`, `<`, `<=`
| 4 | `>`, `>=`, `<`, `<=` | 1. `==`, `!=`
| 3 | `==`, `!=` | 1. `&&`
| 2 | `&&` | 1. `||`
| 1 | `||` |
Parentheses can be used to override the default order of operations. Without Parentheses can be used to override the default order of operations. Without
parentheses, higher levels are evaluated first, so `1 + 2 * 3` is interpreted parentheses, higher levels are evaluated first, so `1 + 2 * 3` is interpreted
@ -342,8 +336,8 @@ The logical operators all expect bool values and produce bool values as results.
## Conditional Expressions ## Conditional Expressions
A _conditional expression_ allows the selection of one of two values based A _conditional expression_ uses the value of a bool expression to select one of
on whether another bool expression is `true` or `false`. two values.
The syntax of a conditional expression is as follows: The syntax of a conditional expression is as follows:
@ -372,18 +366,17 @@ conditional expression will return without knowing the condition value.
## Function Calls ## Function Calls
The Terraform language has a number of The Terraform language has a number of
[built-in functions](/docs/configuration/functions.html) that can be used [built-in functions](./functions.html) that can be used
within expressions as another way to transform and combine values. These within expressions as another way to transform and combine values. These
are similar to the operators but all follow a common syntax: are similar to the operators but all follow a common syntax:
```hcl ```hcl
function_name(argument1, argument2) <FUNCTION NAME>(<ARGUMENT 1>, <ARGUMENT 2>)
``` ```
The `function_name` specifies which function to call. Each defined function has The function name specifies which function to call. Each defined function
a _signature_, which defines how many arguments it expects and what value types expects a specific number of arguments with specific value types, and returns a
those arguments must have. The signature also defines the type of the result specific value type as a result.
value for any given set of argument types.
Some functions take an arbitrary number of arguments. For example, the `min` Some functions take an arbitrary number of arguments. For example, the `min`
function takes any amount of number arguments and returns the one that is function takes any amount of number arguments and returns the one that is
@ -393,26 +386,33 @@ numerically smallest:
min(55, 3453, 2) min(55, 3453, 2)
``` ```
If the arguments to pass are available in a list or tuple value, that value ### Expanding Function Arguments
can be _expanded_ into separate arguments using the `...` symbol after that
argument: If the arguments to pass to a function are available in a list or tuple value,
that value can be _expanded_ into separate arguments. Provide the list value as
an argument and follow it with the `...` symbol:
```hcl ```hcl
min([55, 2453, 2]...) min([55, 2453, 2]...)
``` ```
The expansion symbol is three periods (`...`), not a Unicode ellipsis character
(`…`). Expansion is a special syntax that is only available in function calls.
### Available Functions
For a full list of available functions, see For a full list of available functions, see
[the function reference](/docs/configuration/functions.html). [the function reference](./functions.html).
## `for` Expressions ## `for` Expressions
A _`for` expression_ allows you create a structural type value by transforming A _`for` expression_ creates a complex type value by transforming
another structural or collection type value. Each element in the input value another complex type value. Each element in the input value
can correspond to either one or zero values in the result, and an arbitrary can correspond to either one or zero values in the result, and an arbitrary
expression can be used to transform each input element into an output element. expression can be used to transform each input element into an output element.
For example, if `var.list` is a list of strings then it can be converted to For example, if `var.list` is a list of strings, then the following expression
a list of strings with all-uppercase letters with the following: produces a list of strings with all-uppercase letters:
```hcl ```hcl
[for s in var.list: upper(s)] [for s in var.list: upper(s)]
@ -436,7 +436,8 @@ This expression produces an object whose attributes are the original elements
from `var.list` and their corresponding values are the uppercase versions. from `var.list` and their corresponding values are the uppercase versions.
A `for` expression can also include an optional `if` clause to filter elements A `for` expression can also include an optional `if` clause to filter elements
from the source collection: from the source collection, which can produce a value with fewer elements than
the source:
``` ```
[for s in var.list: upper(s) if s != ""] [for s in var.list: upper(s) if s != ""]
@ -460,19 +461,19 @@ together results that have a common key:
## Splat Expressions ## Splat Expressions
A _splat expressions_ provides a more concise way to express a common A _splat expression_ provides a more concise way to express a common
operation that could otherwise be performed with a `for` expression. operation that could otherwise be performed with a `for` expression.
If `var.list` is a list of objects that all have an attribute `id`, then If `var.list` is a list of objects that all have an attribute `id`, then
a list of the ids could be obtained using the following `for` expression: a list of the ids could be produced with the following `for` expression:
``` ```hcl
[for o in var.list: o.id] [for o in var.list: o.id]
``` ```
This is equivalent to the following _splat expression_: This is equivalent to the following _splat expression:_
``` ```hcl
var.list[*].id var.list[*].id
``` ```
@ -482,39 +483,16 @@ right. A splat expression can also be used to access attributes and indexes
from lists of complex types by extending the sequence of operations to the from lists of complex types by extending the sequence of operations to the
right of the symbol: right of the symbol:
``` ```hcl
var.list[*].interfaces[0].name var.list[*].interfaces[0].name
``` ```
The above expression is equivalent to the following `for` expression: The above expression is equivalent to the following `for` expression:
``` ```hcl
[for o in var.list: o.interfaces[0].name] [for o in var.list: o.interfaces[0].name]
``` ```
A second variant of the _splat expression_ is the "attribute-only" splat
expression, indicated by the sequence `.*`:
```
var.list.*.interfaces[0].name
```
This form has a subtly different behavior, equivalent to the following
`for` expression:
```
[for o in var.list: o.interfaces][0].name
```
Notice that with the attribute-only splat expression the index operation
`[0]` is applied to the result of the iteration, rather than as part of
the iteration itself.
The standard splat expression `[*]` should be used in most cases, because its
behavior is less surprising. The attribute-only splat expression is supported
only for compatibility with earlier versions of Terraform, and should not be
used in new configurations.
Splat expressions also have another useful effect: if they are applied to Splat expressions also have another useful effect: if they are applied to
a value that is _not_ a list or tuple then the value is automatically wrapped a value that is _not_ a list or tuple then the value is automatically wrapped
in a single-element list before processing. That is, `var.single_object[*].id` in a single-element list before processing. That is, `var.single_object[*].id`
@ -532,12 +510,36 @@ The above will produce a list of ids whether `aws_instance.example` has
in the configuration when a particular resource switches to and from in the configuration when a particular resource switches to and from
having `count` set. having `count` set.
### Legacy (Attribute-only) Splat Expressions
An older variant of the splat expression is available for compatibility with
code written in older versions of the Terraform language. This is a less useful
version of the splat expression, and should be avoided in new configurations.
An "attribute-only" splat expression is indicated by the sequence `.*` (instead
of `[*]`):
```
var.list.*.interfaces[0].name
```
This form has a subtly different behavior, equivalent to the following
`for` expression:
```
[for o in var.list: o.interfaces][0].name
```
Notice that with the attribute-only splat expression the index operation
`[0]` is applied to the result of the iteration, rather than as part of
the iteration itself.
## `dynamic` blocks ## `dynamic` blocks
Expressions can usually be used only when assigning a value to an attribute Within top-level block constructs like resources, expressions can usually be
argument using the `name = expression` form. This covers many uses, but used only when assigning a value to an argument using the `name = expression`
some resource types include in their arguments _nested blocks_, which form. This covers many uses, but some resource types include repeatable _nested
do not accept expressions: blocks_ in their arguments, which do not accept expressions:
```hcl ```hcl
resource "aws_security_group" "example" { resource "aws_security_group" "example" {
@ -549,9 +551,9 @@ resource "aws_security_group" "example" {
} }
``` ```
To allow nested blocks like `ingress` to be constructed dynamically, a special You can dynamically construct repeatable nested blocks like `ingress` using a
block type `dynamic` is supported inside `resource`, `data`, `provider`, special `dynamic` block type, which is supported inside `resource`, `data`,
and `provisioner` blocks: `provider`, and `provisioner` blocks:
```hcl ```hcl
resource "aws_security_group" "example" { resource "aws_security_group" "example" {
@ -568,29 +570,40 @@ resource "aws_security_group" "example" {
} }
``` ```
A `dynamic` block iterates over a collection or structural value given in its A `dynamic` block acts much like a `for` expression, but produces nested blocks
`for_each` argument, generating a nested block for each element by evaluating instead of a complex typed value. It iterates over a given complex value, and
the nested `content` block. When evaluating the block, a temporary variable generates a nested block for each element of that complex value.
is defined that is by default named after the block type being generated,
or `ingress` in this example. An optional additional argument `iterator` can be - The label of the dynamic block (`"ingress"` in the example above) specifies
used to override the name of the iterator variable. what kind of nested block to generate.
- The `for_each` argument provides the complex value to iterate over.
- The `iterator` argument (optional) sets the name of a temporary variable
that represents the current element of the complex value. If omitted, the name
of the variable defaults to the label of the `dynamic` block (`"ingress"` in
the example above).
- The `labels` argument (optional) is a list of strings that specifies the block
labels, in order, to use for each generated block. You can use the temporary
iterator variable in this value.
- The nested `content` block defines the body of each generated block. You can
use the temporary iterator variable inside this block.
Since the `for_each` argument accepts any collection or structural value, Since the `for_each` argument accepts any collection or structural value,
you can use a `for` expression or splat expression to transform an existing you can use a `for` expression or splat expression to transform an existing
collection. collection.
Overuse of `dynamic` blocks can make configuration hard to read and maintain,
so we recommend using this only when a re-usable module is hiding some details.
Avoid creating modules that are just thin wrappers around single resources,
passing through all of the input variables directly to resource arguments.
Always write nested blocks out literally where possible.
A `dynamic` block can only generate arguments that belong to the resource type, A `dynamic` block can only generate arguments that belong to the resource type,
data source, provider or provisioner being configured. It is _not_ possible data source, provider or provisioner being configured. It is _not_ possible
to generate meta-argument blocks such as `lifecycle` and `provisioner` to generate meta-argument blocks such as `lifecycle` and `provisioner`
blocks, since Terraform must process these before it is safe to evaluate blocks, since Terraform must process these before it is safe to evaluate
expressions. expressions.
### Best Practices for `dynamic` Blocks
Overuse of `dynamic` blocks can make configuration hard to read and maintain, so
we recommend using them only when you need to hide details in order to build a
clean user interface for a re-usable module. Always write nested blocks out
literally where possible.
## String Literals ## String Literals
The Terraform language has two different syntaxes for string literals. The The Terraform language has two different syntaxes for string literals. The
@ -665,18 +678,19 @@ Backslash sequences are not interpreted in a heredoc string expression.
Instead, the backslash character is interpreted literally. Instead, the backslash character is interpreted literally.
In both quoted and heredoc string expressions, Terraform supports template In both quoted and heredoc string expressions, Terraform supports template
sequences introduced by `${` and `%{`. These are described in more detail sequences that begin with `${` and `%{`. These are described in more detail
in the following section. To include these sequences _literally_ without in the following section. To include these sequences _literally_ without
beginning a template sequence, double the leading character: `$${` or `%%{`. beginning a template sequence, double the leading character: `$${` or `%%{`.
## String Templates ## String Templates
Within quoted and heredoc string expressions, the sequences `${` and `%{` Within quoted and heredoc string expressions, the sequences `${` and `%{` begin
begin _template sequences_. Templates allow expressions to be embedded directly _template sequences_. Templates let you directly embed expressions into a string
into the string sequence, and thus allow strings to be dynamically constructed literal, to dynamically construct strings from other values.
from other values in a concise way.
A `${ ... }` sequence is an _interpolation_, which evaluates the expression ### Interpolation
A `${ ... }` sequence is an _interpolation,_ which evaluates the expression
given between the markers, converts the result to a string if necessary, and given between the markers, converts the result to a string if necessary, and
then inserts it into the final string: then inserts it into the final string:
@ -687,43 +701,46 @@ then inserts it into the final string:
In the above example, the named object `var.name` is accessed and its value In the above example, the named object `var.name` is accessed and its value
inserted into the string, producing a result like "Hello, Juan!". inserted into the string, producing a result like "Hello, Juan!".
### Directives
A `%{ ... }` sequence is a _directive_, which allows for conditional A `%{ ... }` sequence is a _directive_, which allows for conditional
results and iteration over collections, similar to conditional and results and iteration over collections, similar to conditional
and `for` expressions. and `for` expressions.
The following directives are supported: The following directives are supported:
* The `if` directive chooses between two templates based on a conditional * The `if <BOOL>`/`else`/`endif` directive chooses between two templates based
expression: on the value of a bool expression:
```hcl ```hcl
"Hello, %{ if var.name != "" }${var.name}%{ else }unnamed%{ endif }!" "Hello, %{ if var.name != "" }${var.name}%{ else }unnamed%{ endif }!"
``` ```
The "else" portion may be omitted, in which case the result is an empty The `else` portion may be omitted, in which case the result is an empty
string if the condition expression returns `false`. string if the condition expression returns `false`.
* The `for` directive iterates over each of the elements of a given collection * The `for <NAME> in <COLLECTION>` / `endfor` directive iterates over the
or structural value and evaluates a given template once for each element, elements of a given collection or structural value and evaluates a given
concatenating the results together: template once for each element, concatenating the results together:
```hcl ```hcl
<<EOT <<EOT
%{ for ip in aws_instance.example.*.private_ip } %{ for ip in aws_instance.example.*.private_ip }
server ${ip} server ${ip}
%{ endfor } %{ endfor }
EOT EOT
``` ```
The name given immediately after the `for` keyword is used as a temporary The name given immediately after the `for` keyword is used as a temporary
variable name which can then be referenced from the nested template. variable name which can then be referenced from the nested template.
To allow for template directives to be formatted for readability without To allow template directives to be formatted for readability without adding
introducing unwanted additional spaces and newlines in the result, all unwanted spaces and newlines to the result, all template sequences can include
template sequences can include optional _strip markers_ `~` either immediately optional _strip markers_ (`~`), immediately after the opening characters or
after the introducer or immediately before the end. When present, the sequence immediately before the end. When a strip marker is present, the template
consumes all of the literal whitespace (spaces and newlines) either before sequence consumes all of the literal whitespace (spaces and newlines) either
or after the sequence: before the sequence (if the marker appears at the beginning) or after (if the
marker appears at the end):
```hcl ```hcl
<<EOT <<EOT
@ -744,6 +761,6 @@ server 10.1.16.34
``` ```
When using template directives, we recommend always using the "heredoc" string When using template directives, we recommend always using the "heredoc" string
expression form and then formatting the template over multiple lines for literal form and then formatting the template over multiple lines for
readability. Quoted string literals should usually include only interpolation readability. Quoted string literals should usually include only interpolation
sequences. sequences.

View File

@ -19,12 +19,12 @@ max(5, 12, 9)
``` ```
For more details on syntax, see For more details on syntax, see
[_Function Calls_](/docs/configuration/expressions.html#function-calls) [_Function Calls_](./expressions.html#function-calls)
on the Expressions page. on the Expressions page.
The Terraform language does not support user-defined functions, and so only The Terraform language does not support user-defined functions, and so only
the functions built in to the language are available for use. The navigation the functions built in to the language are available for use. The navigation
includes a list of all of the available built-in functions. for this section includes a list of all of the available built-in functions.
You can experiment with the behavior of Terraform's built-in functions from You can experiment with the behavior of Terraform's built-in functions from
the Terraform expression console, by running the Terraform expression console, by running

View File

@ -15,7 +15,7 @@ of the result of decoding that string.
The JSON encoding is defined in [RFC 7159](https://tools.ietf.org/html/rfc7159). The JSON encoding is defined in [RFC 7159](https://tools.ietf.org/html/rfc7159).
This function maps JSON values to This function maps JSON values to
[Terraform language values](/docs/configuration/expressions.html#types-and-values) [Terraform language values](./expressions.html#types-and-values)
in the following way: in the following way:
| JSON type | Terraform type | | JSON type | Terraform type |

View File

@ -13,7 +13,7 @@ description: |-
The JSON encoding is defined in [RFC 7159](https://tools.ietf.org/html/rfc7159). The JSON encoding is defined in [RFC 7159](https://tools.ietf.org/html/rfc7159).
This fucntion maps This fucntion maps
[Terraform language values](/docs/configuration/expressions.html#types-and-values) [Terraform language values](./expressions.html#types-and-values)
to JSON values in the following way: to JSON values in the following way:
| Terraform type | JSON type | | Terraform type | JSON type |

View File

@ -8,7 +8,7 @@ description: |-
# `pow` Function # `pow` Function
`pow` raises a number to a given power. That is, it calcluates the exponent. `pow` calculates an exponent, by raising its first argument to the power of the second argument.
## Examples ## Examples

View File

@ -20,7 +20,7 @@ The result of this function will change every second, so using this function
directly with resource attributes will cause a diff to be detected on every directly with resource attributes will cause a diff to be detected on every
Terraform run. We do not recommend using this function in resource attributes, Terraform run. We do not recommend using this function in resource attributes,
but in rare cases it can be used in conjunction with but in rare cases it can be used in conjunction with
[the `ignore_changes` lifecycle meta-argument](/docs/configuration/resources.html#ignore_changes) [the `ignore_changes` lifecycle meta-argument](./resources.html#ignore_changes)
to take the timestamp only on initial creation of the resource. to take the timestamp only on initial creation of the resource.
Due to the constantly changing return value, the result of this function cannot Due to the constantly changing return value, the result of this function cannot

View File

@ -19,7 +19,7 @@ This function produces a new value each time it is called, and so using it
directly in resource arguments will result in spurious diffs. We do not directly in resource arguments will result in spurious diffs. We do not
recommend using the `uuid` function in resource configurations, but it can recommend using the `uuid` function in resource configurations, but it can
be used with care in conjunction with be used with care in conjunction with
[the `ignore_changes` lifecycle meta-argument](/docs/configuration/resources.html#ignore_changes). [the `ignore_changes` lifecycle meta-argument](./resources.html#ignore_changes).
In most cases we recommend using [the `random` provider](/docs/providers/random/index.html) In most cases we recommend using [the `random` provider](/docs/providers/random/index.html)
instead, since it allows the one-time generation of random values that are instead, since it allows the one-time generation of random values that are

View File

@ -16,23 +16,53 @@ describing an intended goal rather than the steps to reach that goal.
## Resources and Modules ## Resources and Modules
The main purpose of the Terraform language is declaring [resources](/docs/configuration/resources.html). The main purpose of the Terraform language is declaring [resources](./resources.html).
All other language features exist only to make the definition of resources All other language features exist only to make the definition of resources
more flexible and convenient. more flexible and convenient.
A group of resources can be gathered into a [module](/docs/configuration/modules.html), A group of resources can be gathered into a [module](./modules.html),
which creates a larger unit of configuration. A resource describes a single which creates a larger unit of configuration. A resource describes a single
infrastructure object, while a module might describe a set of objects and the infrastructure object, while a module might describe a set of objects and the
necessary relationships between them in order to create a higher-level system. necessary relationships between them in order to create a higher-level system.
A _Terraform configuration_ consists of a _root module_, where evaluation A _Terraform configuration_ consists of a _root module_, where evaluation
begins, along with a tree of child modules created when one module references begins, along with a tree of child modules created when one module calls
another. another.
## Arguments, Blocks, and Expressions
The syntax of the Terraform language consists of only a few basic elements:
```hcl
resource "aws_vpc" "main" {
cidr_block = var.base_cidr_block
}
<BLOCK TYPE> "<BLOCK LABEL>" "<BLOCK LABEL>" {
# Block body
<IDENTIFIER> = <EXPRESSION> # Argument
}
```
- _Blocks_ are containers for other content and usually represent the
configuration of some kind of object, like a resource. Blocks have a
_block type,_ can have zero or more _labels,_ and have a _body_ that contains
any number of arguments and nested blocks. Most of Terraform's features are
controlled by top-level blocks in a configuration file.
- _Arguments_ assign a value to a name. They appear within blocks.
- _Expressions_ represent a value, either literally or by referencing and
combining other values. They appear as values for arguments, or within other
expressions.
For full details about Terraform's syntax, see:
- [Configuration Syntax](./syntax.html)
- [Expressions](./expressions.html)
## Code Organization ## Code Organization
The Terraform language uses configuration files that are named with the `.tf` The Terraform language uses configuration files that are named with the `.tf`
file extension. There is also [a JSON-based variant of the language](/docs/configuration/syntax-json.html) file extension. There is also [a JSON-based variant of the language](./syntax-json.html)
that is named with the `.tf.json` file extension. that is named with the `.tf.json` file extension.
Configuration files must always use UTF-8 encoding, and by convention are Configuration files must always use UTF-8 encoding, and by convention are
@ -53,31 +83,33 @@ or by organizing sets of resources into child modules.
## Configuration Ordering ## Configuration Ordering
Because Terraform's configuration language is declarative, the ordering of Because Terraform's configuration language is declarative, the ordering of
blocks is generally not significant, except in some specific situations which blocks is generally not significant. (The order of `provisioner` blocks within a
are described explicitly elsewhere. resource is the only major feature where block order matters.)
Terraform automatically processes resources in the correct order based on Terraform automatically processes resources in the correct order based on
relationships defined between them in configuration, and so you can organize relationships defined between them in configuration, and so you can organize
resources into source files in whatever way makes sense for your infrastructure. resources into source files in whatever way makes sense for your infrastructure.
## Terraform Core vs. Providers ## Terraform CLI vs. Providers
Terraform Core is a general engine for evaluating and applying Terraform The Terraform command line interface (CLI) is a general engine for evaluating
configuations. It defines the Terraform language syntax and overall structure, and applying Terraform configuations. It defines the Terraform language syntax
and coordinates sequences of changes that must be made to make remote and overall structure, and coordinates sequences of changes that must be made to
infrastructure match the given configuration. make remote infrastructure match the given configuration.
Terraform Core has no knowledge of specific infrastructure object types, though. This general engine has no knowledge about specific types of infrastructure
Instead, Terraform uses plugins called [providers](/docs/configuration/providers.html) objects. Instead, Terraform uses plugins called
that each define and know how to manage a set of resource types. Most providers [providers](./providers.html) that each define and manage a
are associated with a particular cloud or on-premises infrastructure service, set of resource types. Most providers are associated with a particular cloud or
allowing Terraform to manage infrastructure objects within that service. on-premises infrastructure service, allowing Terraform to manage infrastructure
objects within that service.
Since each provider has its own resource types with different features, the Terraform doesn't have a concept of platform-independent resource types
exact details of resources can vary between services, but Terraform Core  resources are always tied to a provider, since the features of similar
ensures that the same language constructs and syntax are available across resources can vary greatly from provider to provider. But Terraform CLI's shared
all services and allows resource types from different services to be combined configuration engine ensures that the same language constructs and syntax are
as needed. available across all services and allows resource types from different services
to be combined as needed.
## Example ## Example
@ -98,6 +130,7 @@ variable "base_cidr_block" {
variable "availability_zones" { variable "availability_zones" {
description = "A list of availability zones in which to create subnets" description = "A list of availability zones in which to create subnets"
type = list(string)
} }
provider "aws" { provider "aws" {

View File

@ -9,15 +9,18 @@ description: |-
# Local Values # Local Values
A local value assigns a name to an [expression](/docs/configuration/expressions.html), A local value assigns a name to an [expression](./expressions.html),
allowing it to then be used multiple times within a module without repeating allowing it to be used multiple times within a module without repeating
it. it.
Comparing modules to functions in a traditional programming language, Comparing modules to functions in a traditional programming language:
if [input variables](./variables.html) are analogous to function arguments and if [input variables](./variables.html) are analogous to function arguments and
[outputs values](./outputs.html) are analogous to function return values then [outputs values](./outputs.html) are analogous to function return values, then
_local values_ are comparable to a function's local temporary symbols. _local values_ are comparable to a function's local temporary symbols.
-> **Note:** For brevity, local values are often referred to as just "locals"
when the meaning is clear from context.
## Declaring a Local Value ## Declaring a Local Value
A set of related local values can be delared together in a single `locals` A set of related local values can be delared together in a single `locals`
@ -30,9 +33,6 @@ locals {
} }
``` ```
For brevity, local values are often referred to just as "locals", when the
meaning is clear from context.
The expressions assigned to local value names can either be simple constants The expressions assigned to local value names can either be simple constants
like the above, allowing these values to be defined only once but used many like the above, allowing these values to be defined only once but used many
times, or they can be more complex expressions that transform or combine times, or they can be more complex expressions that transform or combine
@ -54,7 +54,7 @@ locals {
``` ```
As shown above, local values can be referenced from elsewhere in the module As shown above, local values can be referenced from elsewhere in the module
with an expression like `local.common_tags`, and output values can reference with an expression like `local.common_tags`, and locals can reference
each other in order to build more complex values from simpler ones. each other in order to build more complex values from simpler ones.
``` ```
@ -67,12 +67,12 @@ resource "aws_instance" "example" {
## When To Use Local Values ## When To Use Local Values
Local Values can be helpful to avoid repeating the same values or expressions Local values can be helpful to avoid repeating the same values or expressions
multiple times in a configuration, but if overused they can also make a multiple times in a configuration, but if overused they can also make a
configuration hard to read by future maintainers by hiding the actual values configuration hard to read by future maintainers by hiding the actual values
used. used.
Use Local Values only in moderation, in situations where a single value or Use local values only in moderation, in situations where a single value or
result is used in many places _and_ that value is likely to be changed in result is used in many places _and_ that value is likely to be changed in
future. The ability to easily change the value in a central place is the key future. The ability to easily change the value in a central place is the key
advantage of local values. advantage of local values.

View File

@ -9,12 +9,13 @@ description: |-
# Modules # Modules
A _module_ is a container for multiple resources that are used together. A _module_ is a container for multiple resources that are used together.
Every Terraform configuration has at least one module, known as its Every Terraform configuration has at least one module, known as its
_root module_, which consists of the resources defined in the `.tf` files in _root module_, which consists of the resources defined in the `.tf` files in
the main working directory. the main working directory.
A module can call other modules, allowing the suite of resources within the A module can call other modules, which lets you include the child module's
child module to be included into the configuration in a concise way. Modules resources into the configuration in a concise way. Modules
can also be called multiple times, either within the same configuration or can also be called multiple times, either within the same configuration or
in separate configurations, allowing resource configurations to be packaged in separate configurations, allowing resource configurations to be packaged
and re-used. and re-used.
@ -28,7 +29,7 @@ created, and published in [the dedicated _Modules_ section](/docs/modules/index.
To _call_ a module means to include the contents of that module into the To _call_ a module means to include the contents of that module into the
configuration with specific values for its configuration with specific values for its
[input variables](/docs/configuration/variables.html). Modules are called [input variables](./variables.html). Modules are called
from within other modules using `module` blocks: from within other modules using `module` blocks:
```hcl ```hcl
@ -39,19 +40,22 @@ module "servers" {
} }
``` ```
The label immediately after the `module` keyword is a name that will be used A module that includes a `module` block like this is the _calling module_ of the
to refer to this instance of the module within the calling module. The child module.
_calling module_ is the one that includes the `module` block shown above.
The label immediately after the `module` keyword is a local name, which the
calling module can use to refer to this instance of the module.
Within the block body (between `{` and `}`) are the arguments for the module. Within the block body (between `{` and `}`) are the arguments for the module.
Most of the arguments correspond to [input variables](/docs/configuration/variables.html) Most of the arguments correspond to [input variables](./variables.html)
defined by the module, including the `servers` argument in the above example. defined by the module, including the `servers` argument in the above example.
The `source` argument is a meta-argument defined and processed by Terraform All modules require a `source` argument, which is a meta-argument defined by
itself. Its value is the path to a local directory containing the module's Terraform CLI. Its value is either the path to a local directory of the
configuration files, or optionally a remote module source that Terraform should module's configuration files, or a remote module source that Terraform should
download and use. For more information on possible values for this argument, download and use. This value must be a literal string with no template
see [_Module Sources_](/docs/modules/sources.html). sequences; arbitrary expressions are not allowed. For more information on
possible values for this argument, see [Module Sources](/docs/modules/sources.html).
The same source address can be specified in multiple `module` blocks to create The same source address can be specified in multiple `module` blocks to create
multiple copies of the resources defined within, possibly with different multiple copies of the resources defined within, possibly with different
@ -61,7 +65,7 @@ variable values.
The resources defined in a module are encapsulated, so the calling module The resources defined in a module are encapsulated, so the calling module
cannot access their attributes directly. However, the child module can cannot access their attributes directly. However, the child module can
declare [output values](/docs/configuration/outputs.html) to selectively declare [output values](./outputs.html) to selectively
export certain values to be accessed by the calling module. export certain values to be accessed by the calling module.
For example, if the `./app-cluster` module referenced in the example above For example, if the `./app-cluster` module referenced in the example above
@ -76,6 +80,9 @@ resource "aws_elb" "example" {
} }
``` ```
For more information about referring to named values, see
[Expressions](./expressions.html).
## Other Meta-arguments ## Other Meta-arguments
Along with the `source` meta-argument described above, module blocks have Along with the `source` meta-argument described above, module blocks have

View File

@ -8,15 +8,24 @@ description: |-
# Output Values # Output Values
Output values are like the return values of a Terraform module, allowing Output values are like the return values of a Terraform module, and have several
a subset of the resource attributes within a child module to be exposed to uses:
a parent module, or making certain values from a root module visible in the
CLI output after running `terraform apply`. - A child module can use outputs to expose a subset of its resource attributes
to a parent module.
- A root module can use outputs to print certain values in the CLI output after
running `terraform apply`.
- When using [remote state](/docs/state/remote.html), root module outputs can be
accessed by other configurations via a
[`terraform_remote_state` data source](/docs/providers/terraform/d/remote_state.html).
Resource instances managed by Terraform each export attributes whose values Resource instances managed by Terraform each export attributes whose values
can be used elsewhere in configuration. Output values are a way to expose some can be used elsewhere in configuration. Output values are a way to expose some
of that information to the user of your module. of that information to the user of your module.
-> **Note:** For brevity, output values are often referred to as just "outputs"
when the meaning is clear from context.
## Declaring an Output Value ## Declaring an Output Value
Each output value exported by a module must be declared using an `output` Each output value exported by a module must be declared using an `output`
@ -32,10 +41,7 @@ The label immediately after the `output` keyword is the name that can be used
to access this output in the parent module, if any, or the name that will be to access this output in the parent module, if any, or the name that will be
displayed to the user for output values in the root module. displayed to the user for output values in the root module.
For brevity, output values are often referred to simply as "outputs", where The `value` argument takes an [expression](./expressions.html)
the meaning is clear from context.
The `value` argument takes an [expression](/docs/configuration/expressions.html)
whose result is to be returned to the user. In this example, the expression whose result is to be returned to the user. In this example, the expression
refers to the `private_ip` attribute exposed by an `aws_instance` resource refers to the `private_ip` attribute exposed by an `aws_instance` resource
defined elsewhere in this module (not shown). Any valid expression is allowed defined elsewhere in this module (not shown). Any valid expression is allowed
@ -46,9 +52,9 @@ will be described in the following sections.
## Output Value Documentation ## Output Value Documentation
Because the output values of a module are part of the user interface of Because the output values of a module are part of its user interface, you can
the module, you may specify a short description of the purpose of each briefly describe the purpose of each value using the optional `description`
value using the optional `description` argument: argument:
```hcl ```hcl
output "instance_ip_addr" { output "instance_ip_addr" {
@ -57,9 +63,9 @@ output "instance_ip_addr" {
} }
``` ```
The description for an output value should be a concise description of the The description should concisely explain the
purpose of the variable and what kind of value is expected. This description purpose of the output and what kind of value is expected. This description
string may be included in documentation about the module, and so it should be string might be included in documentation about the module, and so it should be
written from the perspective of the user of the module rather than its written from the perspective of the user of the module rather than its
maintainer. For commentary for module maintainers, use comments. maintainer. For commentary for module maintainers, use comments.
@ -77,9 +83,9 @@ output "db_password" {
``` ```
Setting an output value in the root module as sensitive prevents Terraform Setting an output value in the root module as sensitive prevents Terraform
from showing its value at the end of `terraform apply`. It may still be shown from showing its value in the list of outputs at the end of `terraform apply`.
in the CLI output for other reasons, such as if the value is referenced in It might still be shown in the CLI output for other reasons, like if the
an expression for a resource argument. value is referenced in an expression for a resource argument.
Sensitive output values are still recorded in the Sensitive output values are still recorded in the
[state](/docs/state/index.html), and so will be visible to anyone who is able [state](/docs/state/index.html), and so will be visible to anyone who is able
@ -98,7 +104,7 @@ correctly determine the dependencies between resources defined in different
modules. modules.
Just as with Just as with
[resource dependencies](/docs/configuration/resources.html#resource-dependencies), [resource dependencies](./resources.html#resource-dependencies),
Terraform analyzes the `value` expression for an output value and autmatically Terraform analyzes the `value` expression for an output value and autmatically
determines a set of dependencies, but in less-common cases there are determines a set of dependencies, but in less-common cases there are
dependencies that cannot be recognized implicitly. In these rare cases, the dependencies that cannot be recognized implicitly. In these rare cases, the

View File

@ -8,7 +8,7 @@ description: |-
# Providers # Providers
While [resources](/docs/configuration/resources.html) are the primary construct While [resources](./resources.html) are the primary construct
in the Terraform language, the _behaviors_ of resources rely on their in the Terraform language, the _behaviors_ of resources rely on their
associated resource types, and these types are defined by _providers_. associated resource types, and these types are defined by _providers_.
@ -45,11 +45,11 @@ the resource type name `google_compute_instance`.
The body of the block (between `{` and `}`) contains configuration arguments The body of the block (between `{` and `}`) contains configuration arguments
for the provider itself. Most arguments in this section are specified by for the provider itself. Most arguments in this section are specified by
the provider itself, and indeed in this example both `project` and `region` the provider itself; in this example both `project` and `region`
are specific to the `google` provider. are specific to the `google` provider.
The configuration arguments defined by the provider may be assigned using The configuration arguments defined by the provider may be assigned using
[expressions](/docs/configuration/expressions.html), which can for example [expressions](./expressions.html), which can for example
allow them to be parameterized by input variables. However, since provider allow them to be parameterized by input variables. However, since provider
configurations must be evaluated in order to perform any resource type action, configurations must be evaluated in order to perform any resource type action,
provider configurations may refer only to values that are known before provider configurations may refer only to values that are known before
@ -57,9 +57,11 @@ the configuration is applied. In particular, avoid referring to attributes
exported by other resources unless their values are specified directly in the exported by other resources unless their values are specified directly in the
configuration. configuration.
A small number of "meta-arguments" are defined by Terraform Core itself and There are also two "meta-arguments" that are defined by Terraform itself
available for all `provider` blocks. These will be described in the following and available for all `provider` blocks:
sections.
- [`version`, for constraining the allowed provider versions][inpage-versions]
- [`alias`, for using the same provider with different configurations for different resources][inpage-alias]
Unlike many other objects in the Terraform language, a `provider` block may Unlike many other objects in the Terraform language, a `provider` block may
be omitted if its contents would otherwise be empty. Terraform assumes an be omitted if its contents would otherwise be empty. Terraform assumes an
@ -87,7 +89,9 @@ for installation instructions.
For more information, see For more information, see
[the `terraform init` command](/docs/commands/init.html). [the `terraform init` command](/docs/commands/init.html).
## Provider Versions ## `version`: Provider Versions
[inpage-versions]: #version-provider-versions
Providers are plugins released on a separate rhythm from Terraform itself, and Providers are plugins released on a separate rhythm from Terraform itself, and
so they have their own version numbers. For production use, you should so they have their own version numbers. For production use, you should
@ -142,12 +146,14 @@ to downloading a new version. To upgrade to the latest acceptable version
of each provider, run `terraform init -upgrade`. This command also upgrades of each provider, run `terraform init -upgrade`. This command also upgrades
to the latest versions of all Terraform modules. to the latest versions of all Terraform modules.
## Multiple Provider Instances ## `alias`: Multiple Provider Instances
You can optionally define multiple configurations for the same provider [inpage-alias]: #alias-multiple-provider-instances
to allow managing objects in multiple regions, on multiple hosts, etc. The
primary reason is multiple regions for a cloud platform. Other examples include You can optionally define multiple configurations for the same provider, and
targeting multiple Docker hosts, multiple Consul hosts, etc. select which one to use on a per-resource or per-module basis. The primary
reason for this is to support multiple regions for a cloud platform; other
examples include targeting multiple Docker hosts, multiple Consul hosts, etc.
To include multiple configurations for a given provider, include multiple To include multiple configurations for a given provider, include multiple
`provider` blocks with the same provider name, but set the `alias` meta-argument `provider` blocks with the same provider name, but set the `alias` meta-argument
@ -172,14 +178,26 @@ configuration. For providers that have no required configuration arguments, the
implied _empty_ configuration is considered to be the _default_ provider implied _empty_ configuration is considered to be the _default_ provider
configuration. configuration.
Resources are normally associated with the default provider configuration ### Referring to Alternate Providers
inferred from the resource type name. For example, a resource of type
`aws_instance` uses the _default_ (un-aliased) `aws` provider configuration
unless otherwise stated.
The `provider` meta-argument within any `resource` or `data` block overrides When Terraform needs the name of a provider configuration, it always expects a
this default behavior and allows an additional provider configuration to be reference of the form `<PROVIDER NAME>.<ALIAS>`. In the example above,
selected using its alias: `aws.west` would refer to the provider with the `us-west-2` region.
These references are special expressions. Like references to other named
entities (for example, `var.image_id`), they aren't strings and don't need to be
quoted. But they are only valid in specific meta-arguments of `resource`,
`data`, and `module` blocks, and can't be used in arbitrary expressions.
### Selecting Alternate Providers
By default, resources use a default provider configuration inferred from the
first word of the resource type name. For example, a resource of type
`aws_instance` uses the default (un-aliased) `aws` provider configuration unless
otherwise stated.
To select an aliased provider for a resource or data source, set its `provider`
meta-argument to a `<PROVIDER NAME>.<ALIAS>` reference:
```hcl ```hcl
resource "aws_instance" "foo" { resource "aws_instance" "foo" {
@ -189,14 +207,24 @@ resource "aws_instance" "foo" {
} }
``` ```
The value of the `provider` meta-argument is always the provider name and an To select aliased providers for a child module, use its `providers`
alias separated by a period, such as `aws.west` above. meta-argument to specify which aliased providers should be mapped to which local
provider names inside the module:
Provider configurations may also be passed from a parent module into a ```hcl
child module, as described in module "aws_vpc" {
[_Providers within Modules_](/docs/modules/usage.html#providers-within-modules). source = "./aws_vpc"
In most cases, only _root modules_ should define provider configurations, with providers = {
all child modules obtaining their provider configurations from their parents. aws = aws.west
}
}
```
Modules have some special requirements when passing in providers; see
[Providers within Modules](/docs/modules/usage.html#providers-within-modules)
for more details. In most cases, only _root modules_ should define provider
configurations, with all child modules obtaining their provider configurations
from their parents.
## Third-party Plugins ## Third-party Plugins
@ -276,7 +304,7 @@ use of a local directory as a shared plugin cache, which then allows each
distinct plugin binary to be downloaded only once. distinct plugin binary to be downloaded only once.
To enable the plugin cache, use the `plugin_cache_dir` setting in To enable the plugin cache, use the `plugin_cache_dir` setting in
[the CLI configuration file](https://www.terraform.io/docs/commands/cli-config.html). [the CLI configuration file](/docs/commands/cli-config.html).
For example: For example:
```hcl ```hcl

View File

@ -11,7 +11,7 @@ description: |-
# Resources # Resources
_Resources_ are the most important element in the Terraform language. _Resources_ are the most important element in the Terraform language.
Each resource block describes one ore more infrastructure objects, such 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.
@ -46,21 +46,37 @@ arguments defined specifically for [the `aws_instance` resource type](/docs/prov
Each resource is associated with a single _resource type_, which determines Each resource is associated with a single _resource type_, which determines
the kind of infrastructure object it manages and what arguments and other the kind of infrastructure object it manages and what arguments and other
attributes are supported for each resource. attributes the resource supports.
Each resource type in turn belongs to a [provider](/docs/configuration/providers.html), Each resource type in turn belongs to a [provider](./providers.html),
which is a plugin for Terraform that offers a collection of resource types that which is a plugin for Terraform that offers a collection of resource types. A
most often belong to a single cloud or on-premises infrastructure platform. provider usually provides resources to manage a single cloud or on-premises
infrastructure platform.
Most of the items within the body of a `resource` block are defined by and Most of the items within the body of a `resource` block are specific to the
specific to the selected resource type, and these arguments can make full selected resource type. These arguments can make full use of
use of [expressions](/docs/configuration/expressions.html) and other dynamic [expressions](./expressions.html) and other dynamic Terraform
Terraform language features. language features.
However, there are some "meta-arguments" that are defined by Terraform itself There are also some _meta-arguments_ that are defined by Terraform itself
and apply across all resource types. These arguments often have additional and apply across all resource types. (See [Meta-Arguments](#meta-arguments) below.)
restrictions on what language features can be used with them, and are described
in more detail in the following sections. ### Documentation for Resource Types
[Terraform's provider documentation][providers] is the primary place to
learn which resource types are available and which arguments to use for each
resource type. Once you understand Terraform's basic syntax, the provider
documentation will be where you spend the majority of your time on this website.
The "[Providers][]" link at the top level of the navigation sidebar will take
you to an alphabetical list of all of the providers distributed by HashiCorp.
You can find a specific provider in this master list, or choose a category from
the navigation sidebar to browse a more focused list of providers.
You can also search GitHub or other sources for third-party providers, which can
be installed as plugins to enable an even broader selection of resource types.
[providers]: /docs/providers/index.html
## Resource Behavior ## Resource Behavior
@ -86,29 +102,59 @@ 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 for each resource type, but this standard set of verbs is common across them
all. all.
The "meta-arguments" within `resource` blocks, defined in the following The meta-arguments within `resource` blocks, documented in the
sections, allow some details of this standard resource behavior to be sections below, allow some details of this standard resource behavior to be
customized on a per-resource basis. customized on a per-resource basis.
## Resource Dependencies ### Resource Dependencies
As with other elements in the Terraform language, Terraform analyses any Most resources in a configuration don't have any particular relationship, and
[expressions](/docs/configuration/expressions.html) within a `resource` Terraform can make changes to several unrelated resources in parallel.
block to find references to other objects, and infers from this a correct
dependency ordering for creating, updating, or destroying each resource.
Because of this, in most cases it is not necessary to mention explicitly
any dependencies between resources.
However, in some less-common situations there are dependencies between However, some resources must be processed after other specific resources;
resources that cannot be recognized implicitly in configuration. For example, sometimes this is because of how the resource works, and sometimes the
if Terraform is being used to both manage access control policies _and_ take resource's configuration just requires information generated by another
actions that require those policies to be present, there may be a hidden resource.
dependency between the access policy and a resource whose creation depends
on it.
In these rare cases, the `depends_on` meta-argument can be used to explicitly Most resource dependencies are handled automatically. Terraform analyses any
specify a dependency. This argument is available in all `resource` blocks, [expressions](./expressions.html) within a `resource` block to find references
regardless of resource type. For example: 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-hidden-resource-dependencies)
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][inpage-count]
- [`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`: Hidden Resource Dependencies
[inpage-depend]: #depends_on-hidden-resource-dependencies
Use the `depends_on` meta-argument to handle hidden resource dependencies that
Terraform can't automatically infer. Hidden dependencies happen 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 ```hcl
resource "aws_iam_role" "example" { resource "aws_iam_role" "example" {
@ -166,7 +212,9 @@ 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 always include a comment explaining why it is being used, to help future
maintainers understand the purpose of the additional dependency. maintainers understand the purpose of the additional dependency.
## Multiple Resource Instances ### `count`: Multiple Resource Instances
[inpage-count]: #count-multiple-resource-instances
By default, a single `resource` block corresponds to only one real By default, a single `resource` block corresponds to only one real
infrastructure object. Sometimes it is desirable to instead manage a set infrastructure object. Sometimes it is desirable to instead manage a set
@ -188,24 +236,22 @@ resource "aws_instance" "server" {
``` ```
When the `count` meta-argument is present, a distinction exists between When the `count` meta-argument is present, a distinction exists between
the resource block itself -- identified as `aws_instance.server` -- the resource block itself — identified as `aws_instance.server`
and the multiple _resource instances_ associated with it, identified and the multiple _resource instances_ associated with it, identified as
as `aws_instance.server[0]`, `aws_instance.server[1]`, etc. When `count` `aws_instance.server[0]`, `aws_instance.server[1]`, etc. Each instance has a
is _not_ present, a resource block has only a single resource instance, distinct infrastructure object associated with it (as described above in
which has no associated index. [Resource Behavior](#resource-behavior)), and each is separtely created,
updated, or destroyed when the configuration is applied.
For resource blocks where `count` is set, an additional `count` object When `count` is _not_ present, a resource block has only a single resource
is available for use in expressions, which has an attribute `count.index` instance, which has no associated index.
that provides the distinct index for each instance.
The _Resource Behavior_ section above described how each resource corresponds Within resource blocks where `count` is set, an additional `count` object is
to a real infrastructure object. It is in fact resource _instances_ that available for use in expressions so you can modify the configuration of each
correspond to infrastructure objects, and so when `count` is used a particular instance. This object has one attribute, `count.index`, which provides the
resource block has a distinct infrastructure object associated with each of its distinct index number (starting with `0`) for each instance.
instances, and each is separtely created, updated, or destroyed when the
configuration is applied.
The `count` meta argument accepts [expressions](/docs/configuration/expressions.html) The `count` meta-argument accepts [expressions](./expressions.html)
in its value, similar to the resource-type-specific arguments for a resource. in its value, similar to the resource-type-specific arguments for a resource.
However, Terraform must interpret the `count` argument _before_ any actions However, Terraform must interpret the `count` argument _before_ any actions
are taken from remote resources, and so (unlike the resource-type-specifc arguments) are taken from remote resources, and so (unlike the resource-type-specifc arguments)
@ -244,9 +290,11 @@ intended. The practice of generating multiple instances from lists should
be used sparingly, and with due care given to what will happen if the list is be used sparingly, and with due care given to what will happen if the list is
changed later. changed later.
## Selecting a Non-default Provider Configuration ### `provider`: Selecting a Non-default Provider Configuration
As described in [the _providers_ guide](/docs/configuration/providers.html), [inpage-provider]: #provider-selecting-a-non-default-provider-configuration
As described in [the Providers page](./providers.html),
Terraform optionally allows the definition of multiple alternative ("aliased") Terraform optionally allows the definition of multiple alternative ("aliased")
configurations for a single provider, to allow management of resources configurations for a single provider, to allow management of resources
in different regions in multi-region services, etc. in different regions in multi-region services, etc.
@ -288,17 +336,19 @@ A resource always has an implicit dependency on its associated provider, to
ensure that the provider is fully configured before any resource actions ensure that the provider is fully configured before any resource actions
are taken. are taken.
The `provider` meta-argument value must always be a literal provider name The `provider` meta-argument expects [a `<PROVIDER>.<ALIAS>` reference](./providers.html#referring-to-alternate-providers), which
followed by an alias name separated by a dot. Arbitrary expressions are does not need to be quoted. Arbitrary expressions are not permitted for
not permitted for `provider` because it must be resolved while Terraform `provider` because it must be resolved while Terraform is constructing the
is constructing the dependency graph, before it is safe to evaluate dependency graph, before it is safe to evaluate expressions.
expressions.
## Lifecycle Customizations ### `lifecycle`: Lifecycle Customizations
The general lifecycle for resources is described above in the section [inpage-lifecycle]: #lifecycle-lifecycle-customizations
_Resource Behavior_. Some details of that behavior can be customized
using the special nested block `lifecycle` within a resource block body: 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" { resource "azurerm_resource_group" "example" {
@ -316,54 +366,54 @@ meta-arguments are supported:
* `create_before_destroy` (bool) - By default, when Terraform must make a * `create_before_destroy` (bool) - By default, when Terraform must make a
change to a resource argument that cannot be updated in-place due to change to a resource argument that cannot be updated in-place due to
remote API limitations Terraform will instead destroy the existing object remote API limitations, Terraform will instead destroy the existing object
and then create a new replacement object with the new configured arguments. and then create a new replacement object with the new configured arguments.
The `create_before_destroy` meta-argument changes this behavior so that The `create_before_destroy` meta-argument changes this behavior so that
the new, replacement object is created _first_, and then the prior object the new replacement object is created _first,_ and then the prior object
is destroyed only once the replacement is created. is destroyed only once the replacement is created.
This is an opt-in behavior because many remote object types have unique This is an opt-in behavior because many remote object types have unique
name requirements or other constraints that must be accommodated for name requirements or other constraints that must be accommodated for
both a new and an old object to exist concurrently. Some resource types 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 offer special options to append a random suffix onto each object name to
avoid collisions, for example. Terraform Core cannot automatically activate avoid collisions, for example. Terraform CLI cannot automatically activate
such features, so you must understand the constrants for each resource such features, so you must understand the constrants for each resource
type before using `create_before_destroy` with it. type before using `create_before_destroy` with it.
* `prevent_destroy` (bool) - This meta-argument, when set to `true`, will * `prevent_destroy` (bool) - This meta-argument, when set to `true`, will
cause Terraform to reject with an error any plan that would destroy the cause Terraform to reject with an error any plan that would destroy the
infrastructure object associated with the resource, as long as the argument infrastructure object associated with the resource, as long as the argument
remains present in the configuration. remains present in the configuration.
This can be used as a measure of safety against the accidental replacement 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. of objects that may be costly to reproduce, such as database instances.
However, it will make certain configuration changes impossible to apply, However, it will make certain configuration changes impossible to apply,
and will prevent the use of the `terraform destroy` command once such and will prevent the use of the `terraform destroy` command once such
objects are created, and so this option should be used sparingly. objects are created, and so this option should be used sparingly.
Since this argument must be present in configuration for the protection to Since this argument must be present in configuration for the protection to
apply, note that this setting does not prevent the remote object from apply, note that this setting does not prevent the remote object from
being destroyed if the `resource` block were removed from configuration being destroyed if the `resource` block were removed from configuration
entirely: in that case, the `prevent_destroy` setting is removed along entirely: in that case, the `prevent_destroy` setting is removed along
with it, and so Terraform will allow the destroy operation to succeed. with it, and so Terraform will allow the destroy operation to succeed.
* `ignore_changes` (list of attribute names) - By default, Terraform detects * `ignore_changes` (list of attribute names) - By default, Terraform detects
any difference between the current settings of a real infrastructure object any difference in the current settings of a real infrastructure object
and plans to update the remote object to match configuration. and plans to update the remote object to match configuration.
In some rare cases, settings of a remote object are modified by processes 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 outside of Terraform, which Terraform would then attempt to "fix" on the
next run. In order to make Terraform share management responsibilities next run. In order to make Terraform share management responsibilities
of a single object with a separate process, the `ignore_changes` of a single object with a separate process, the `ignore_changes`
meta-argument specifies resource attributes that Terraform should ignore meta-argument specifies resource attributes that Terraform should ignore
when planning updates to the associated remote object. when planning updates to the associated remote object.
The arguments corresponding to the given attribute names are considered The arguments corresponding to the given attribute names are considered
when planning a _create_ operation, but are ignored when planning an when planning a _create_ operation, but are ignored when planning an
_update_. _update_.
```hcl ```hcl
resource "aws_instance" "example" { resource "aws_instance" "example" {
# ... # ...
@ -375,19 +425,46 @@ meta-arguments are supported:
] ]
} }
} }
``` ```
Instead of a list, the special keyword `all` may be used to instruct Instead of a list, the special keyword `all` may be used to instruct
Terraform to ignore _all_ attributes, which means that Terraform can Terraform to ignore _all_ attributes, which means that Terraform can
create and destroy the remote object but will never propose updates to it. create and destroy the remote object but will never propose updates to it.
Only attributes defined by the resource type can be ignored. Only attributes defined by the resource type can be ignored.
`ignore_changes` cannot be applied to itself or to any other meta-arguments. `ignore_changes` cannot be applied to itself or to any other meta-arguments.
The `lifecycle` settings all effect how Terraform constructs and traverses The `lifecycle` settings all effect how Terraform constructs and traverses
the dependency graph. As a result, only literal values can be used because the dependency graph. As a result, only literal values can be used because
the processing happens to early for arbitrary expression evaluation. the processing happens to early for arbitrary expression evaluation.
### `provisioner` and `connection`: Resource Provisioners
[inpage-provisioner]: #provisioner-and-connection-resource-provisioners
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 ## Local-only Resources
While most resource types correspond to an infrastructure object type that While most resource types correspond to an infrastructure object type that
@ -398,7 +475,7 @@ saving those results in the state for future use.
For example, local-only resource types exist for For example, local-only resource types exist for
[generating private keys](/docs/providers/tls/r/private_key.html), [generating private keys](/docs/providers/tls/r/private_key.html),
[issuing self-signed TLS certificates](/docs/providers/tls/r/self_signed_cert.html), [issuing self-signed TLS certificates](/docs/providers/tls/r/self_signed_cert.html),
and even [generating random ids](https://www.terraform.io/docs/providers/random/r/id.html). and even [generating random ids](/docs/providers/random/r/id.html).
While these resource types often have a more marginal purpose than those While these resource types often have a more marginal purpose than those
managing "real" infrastructure objects, they can be useful as glue to help managing "real" infrastructure objects, they can be useful as glue to help
connect together other resources. connect together other resources.
@ -438,27 +515,3 @@ resource types do not support the `timeouts` block at all. Consult the
documentation for each resource type to see which operations it offers documentation for each resource type to see which operations it offers
for configuration, if any. for configuration, if any.
## Resource Provisioners
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).

View File

@ -0,0 +1,72 @@
---
layout: "docs"
page_title: "Style Conventions"
sidebar_current: "docs-config-style"
description: |-
The Terraform language has some idiomatic style conventions, which we
recommend users always follow for consistency between files and modules
written by different teams.
---
# Style Conventions
The Terraform parser allows you some flexibility in how you lay out the
elements in your configuration files, but the Terraform language also has some
idiomatic style conventions which we recommend users always follow
for consistency between files and modules written by different teams.
Automatic source code formatting tools may apply these conventions
automatically.
* Indent two spaces for each nesting level.
* When multiple arguments with single-line values appear on consecutive lines
at the same nesting level, align their equals signs:
```hcl
ami = "abc123"
instance_type = "t2.micro"
```
* When both arguments and blocks appear together inside a block body,
place all of the arguments together at the top and then place nested
blocks below them. Use one blank line to separate the arguments from
the blocks.
* Use empty lines to separate logical groups of arguments within a block.
* For blocks that contain both arguments and "meta-arguments" (as defined by
the Terraform language semantics), list meta-arguments first
and separate them from other arguments with one blank line. Place
meta-argument blocks _last_ and separate them from other blocks with
one blank line.
```hcl
resource "aws_instance" "example" {
count = 2 # meta-argument first
ami = "abc123"
instance_type = "t2.micro"
network_interface {
# ...
}
lifecycle { # meta-argument block last
create_before_destroy = true
}
}
```
* Top-level blocks should always be separated from one another by one
blank line. Nested blocks should also be separated by blank lines, except
when grouping together related blocks of the same type (like multiple
`provisioner` blocks in a resource).
* Avoid separating multiple blocks of the same type with other blocks of
a different type, unless the block types are defined by semantics to
form a family.
(For example: `root_block_device`, `ebs_block_device` and
`ephemeral_block_device` on `aws_instance` form a family of block types
describing AWS block devices, and can therefore be grouped together and
mixed.)

View File

@ -88,17 +88,18 @@ resource "aws_instance" "example" {
``` ```
Within each top-level block type the rules for mapping to JSON are slightly Within each top-level block type the rules for mapping to JSON are slightly
different, but the following general rules apply in most cases: different (see [Block-type-specific Exceptions][inpage-exceptions] below), but the following general rules apply in most cases:
* The JSON object representing the block body contains properties that * The JSON object representing the block body contains properties that
correspond either to attribute arguments names or to nested block type names. correspond either to argument names or to nested block type names.
* Where a property corresponds to an attribute argument that accepts * Where a property corresponds to an argument that accepts
[arbitrary expressions](./expressions.html) in the native syntax, the [arbitrary expressions](./expressions.html) in the native syntax, the
property value is mapped to an expression as described under property value is mapped to an expression as described under
[_Expression Mapping_](#expression-mapping) below. For arguments that [_Expression Mapping_](#expression-mapping) below. For arguments that
do _not_ accept arbitrary expressions, the interpretation of the property do _not_ accept arbitrary expressions, the interpretation of the property
value depends on the argument, as described in [the block-type-specific exceptions](#block-type-specific-exceptions) value depends on the argument, as described in the
[block-type-specific exceptions](#block-type-specific-exceptions)
given later in this page. given later in this page.
* Where a property name corresponds to an expected nested block type name, * Where a property name corresponds to an expected nested block type name,
@ -181,7 +182,7 @@ resource "aws_instance" "example" {
``` ```
When the nested block type requires one or more labels, or when multiple When the nested block type requires one or more labels, or when multiple
blocks of the same type must be given, the mapping gets a little more blocks of the same type can be given, the mapping gets a little more
complicated. For example, the `provisioner` nested block type used complicated. For example, the `provisioner` nested block type used
within `resource` blocks expects a label giving the provisioner to use, within `resource` blocks expects a label giving the provisioner to use,
and the ordering of provisioner blocks is significant to decide the order and the ordering of provisioner blocks is significant to decide the order
@ -299,6 +300,8 @@ configuration file. This can be useful to note which program created the file.
## Block-type-specific Exceptions ## Block-type-specific Exceptions
[inpage-block]: #block-type-specific-exceptions
Certain arguments within specific block types are processed in a special way Certain arguments within specific block types are processed in a special way
by Terraform, and so their mapping to the JSON syntax does not follow the by Terraform, and so their mapping to the JSON syntax does not follow the
general rules described above. The following sub-sections describe the special general rules described above. The following sub-sections describe the special
@ -311,9 +314,9 @@ references to objects, or literal keywords. When represented in JSON, the
reference or keyword is given as a JSON string with no additonal surrounding reference or keyword is given as a JSON string with no additonal surrounding
spaces or symbols. spaces or symbols.
For example, the `provider` meta-argument takes a special compact provider For example, the `provider` meta-argument takes a `<PROVIDER>.<ALIAS>` reference
configuration reference, which appears directly in the native syntax but must to a provider configuration, which appears unquoted in the native syntax but
be presented as a string in the JSON syntax: must be presented as a string in the JSON syntax:
```json ```json
{ {
@ -330,8 +333,8 @@ be presented as a string in the JSON syntax:
This special processing applies to the following meta-arguments: This special processing applies to the following meta-arguments:
* `provider`: a single string, as shown above * `provider`: a single string, as shown above
* `depends_on`: an array of strings containing object references, like * `depends_on`: an array of strings containing references to named entities,
`["aws_instance.example"]`. like `["aws_instance.example"]`.
* `ignore_changes` within the `lifecycle` block: if set to `all`, a single * `ignore_changes` within the `lifecycle` block: if set to `all`, a single
string `"all"` must be given. Otherwise, an array of JSON strings containing string `"all"` must be given. Otherwise, an array of JSON strings containing
property references must be used, like `["ami"]`. property references must be used, like `["ami"]`.

View File

@ -18,7 +18,7 @@ those constructs are built from.
This page describes the _native syntax_ of the Terraform language, which is This page describes the _native syntax_ of the Terraform language, which is
a rich language designed to be easy for humans to read and write. The a rich language designed to be easy for humans to read and write. The
constructs in the Terraform language can also be expressed in constructs in the Terraform language can also be expressed in
[JSON syntax](/docs/configuration/syntax-json.html), which is harder for humans [JSON syntax](./syntax-json.html), which is harder for humans
to read and edit but easier to generate and parse programmatically. to read and edit but easier to generate and parse programmatically.
This low-level syntax of the Terraform language is defined in terms of a This low-level syntax of the Terraform language is defined in terms of a
@ -30,23 +30,39 @@ details. If you are interested, you can find a full definition of HCL
syntax in syntax in
[the HCL native syntax specification](https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md). [the HCL native syntax specification](https://github.com/hashicorp/hcl2/blob/master/hcl/hclsyntax/spec.md).
## Attributes and Blocks ## Arguments and Blocks
The Terraform language syntax is built around two key syntax constructs: The Terraform language syntax is built around two key syntax constructs:
attributes and blocks. arguments and blocks.
An _attribute_ assigns a value to a particular name: ### Arguments
An _argument_ assigns a value to a particular name:
```hcl ```hcl
image_id = "abc123" image_id = "abc123"
``` ```
The identifier before the equals sign is the _attribute name_, and after The identifier before the equals sign is the _argument name_, and the expression
the equals sign is the attribute's value. The semantics applied to each after the equals sign is the argument's value.
attribute name define what value types are valid, but many attributes
accept arbitrary [expressions](/docs/configuration/expressions.html), The context where the argument appears determines what value types are valid
which allow the value to either be specified literally or generated from (for example, each resource type has a schema that defines the types of its
other values programmatically. arguments), but many arguments accept arbitrary
[expressions](./expressions.html), which allow the value to
either be specified literally or generated from other values programmatically.
-> **Note:** Terraform's configuration language is based on a more general
language called HCL, and HCL's documentation usually uses the word "attribute"
instead of "argument." These words are similar enough to be interchangeable in
this context, and experienced Terraform users might use either term in casual
conversation. But because Terraform also interacts with several _other_ things
called "attributes" (in particular, Terraform resources have attributes like
`id` that can be referenced from expressions but can't be assigned values in
configuration), we've chosen to use "argument" in the Terraform documentation
when referring to this syntax construct.
### Blocks
A _block_ is a container for other content: A _block_ is a container for other content:
@ -60,106 +76,41 @@ resource "aws_instance" "example" {
} }
``` ```
A block has a _type_ ("resource" in this example). Each block type defines A block has a _type_ (`resource` in this example). Each block type defines
how many _labels_ must follow the type keyword. The "resource" block type how many _labels_ must follow the type keyword. The `resource` block type
shown here expects two labels, which are "aws_instance" and "example" expects two labels, which are `aws_instance` and `example` in the example above.
in this case. A particular block type may have any number of required labels, A particular block type may have any number of required labels, or it may
or it may require none as with the nested "network_interface" block type. require none as with the nested `network_interface` block type.
After the block type keyword and any labels, the block _body_ is delimited After the block type keyword and any labels, the block _body_ is delimited
by the `{` and `}` characters. Within the block body, further attributes by the `{` and `}` characters. Within the block body, further arguments
and blocks may be nested, creating a heirarchy of blocks and their associated and blocks may be nested, creating a heirarchy of blocks and their associated
attributes. arguments.
Unfortunately, the low-level syntax described here uses the noun "attribute" The Terraform language uses a limited number of _top-level block types,_ which
to mean something slightly different to how it is used by the main are blocks that can appear outside of any other block in a configuration file.
Terraform language. Elsewhere in this documentation, "attribute" usually Most of Terraform's features (including resources, input variables, output
refers to a named value exported by an object that can be accessed in an values, data sources, etc.) are implemented as top-level blocks.
expression, such as the "id" portion of the expression
`aws_instance.example.id`. To reduce confusion, other documentation uses the
term "argument" to refer to the syntax-level idea of an attribute.
### Style Conventions
The Terraform parser allows you some flexibility in how you lay out the
elements in your configuration files, but the Terraform language also has some
idiomatic style conventions which we recommend users should always follow
for consistency between files and modules written by different teams.
Automatic source code formatting tools may apply these conventions
automatically.
* Indent two spaces for each nesting level.
* When multiple attributes with single-line values appear on consecutive lines
at the same nesting level, align their equals signs:
```hcl
ami = "abc123"
instance_type = "t2.micro"
```
* When both attributes and blocks appear together inside a block body,
place all of the attributes together at the top and then place nested
blocks below them. Use one blank line to separate the attributes from
the blocks.
* Use empty lines to separate logical groups of attributes within a block.
* For blocks that contain both arguments and "meta-arguments" (as defined by
the Terraform language semantics), list meta-argument attributes first
and separate them from other attributes with one blank line. Place
meta-argument blocks _last_ and separate them from other blocks with
one blank line.
```hcl
resource "aws_instance" "example" {
count = 2 # meta-argument attribute first
ami = "abc123"
instance_type = "t2.micro"
network_interface {
# ...
}
lifecycle { # meta-argument block last
create_before_destroy = true
}
}
```
* Top-level blocks should always be separated from one another by one
blank line. Nested blocks should also be separated by blank lines, except
when grouping together related blocks of the same type.
* Avoid separating multiple blocks of the same type with other blocks of
a different type, unless the block types are defined by semantics to
form a family.
(For example: `root_block_device`, `ebs_block_device` and
`ephemeral_block_device` on `aws_instance` form a family of block types
describing AWS block devices, and can therefore be grouped together and
mixed.)
## Identifiers ## Identifiers
Attribute names, block type names, and the names of most Terraform-specific Argument names, block type names, and the names of most Terraform-specific
constructs like resources, input variables, etc. are all _identifiers_. constructs like resources, input variables, etc. are all _identifiers_.
The Terraform language implements
[the Unicode identifier syntax](http://unicode.org/reports/tr31/), extended
to also include the ASCII hyphen character `-`.
In practice, this means that identifiers can contain letters, digits, Identifiers can contain letters, digits, underscores (`_`), and hyphens (`-`).
underscores, and hyphens. To avoid ambiguity with literal numbers, the The first character of an identifier must not be a digit, to avoid ambiguity
first character of an identifier must not be a digit. with literal numbers.
For complete identifier rules, Terraform implements
[the Unicode identifier syntax](http://unicode.org/reports/tr31/), extended to
include the ASCII hyphen character `-`.
## Comments ## Comments
The Terraform language supports three different syntaxes for comments: The Terraform language supports three different syntaxes for comments:
* `#` begins a single-line comment, ending at the end of the line * `#` begins a single-line comment, ending at the end of the line.
* `//` also begins a single-line comment, as an alternative to `#`. * `//` also begins a single-line comment, as an alternative to `#`.
* `/*` and `*/` are start and end delimiters for a comment that might span * `/*` and `*/` are start and end delimiters for a comment that might span
over multiple lines. over multiple lines.

View File

@ -56,22 +56,22 @@ More information on backend configuration can be found in
## Specifying a Required Terraform Version ## Specifying a Required Terraform Version
The `required_version` setting can be used to constrain which versions of The `required_version` setting can be used to constrain which versions of
Terraform Core can be used with your configuration. If the running version of the Terraform CLI can be used with your configuration. If the running version of
Terraform doesn't match the constraints specified, Terraform will produce Terraform doesn't match the constraints specified, Terraform will produce
an error and exit without taking any further actions. an error and exit without taking any further actions.
When you use [child modules](/docs/configuration/modules.html), each module When you use [child modules](./modules.html), each module
can specify its own version requirements. The requirements of all modules can specify its own version requirements. The requirements of all modules
in the tree must be satisfied. in the tree must be satisfied.
Use Terraform Core version constraints in a collaborative environment to Use Terraform version constraints in a collaborative environment to
ensure that everyone is using a spceific Terraform version, or using at least ensure that everyone is using a spceific Terraform version, or using at least
a minimum Terraform version that has behavior expected by the configuration. a minimum Terraform version that has behavior expected by the configuration.
The `required_version` setting applies only to the version of Terraform Core. The `required_version` setting applies only to the version of Terraform CLI.
Various behaviors of Terraform are actually implemented by Terraform Providers, Various behaviors of Terraform are actually implemented by Terraform Providers,
which are released on a cycle independent to Terraform Core and to each other. which are released on a cycle independent of Terraform CLI and of each other.
Use [provider version constraints](/docs/configuration/providers.html#provider-versions) Use [provider version constraints](./providers.html#provider-versions)
to make similar constraints on which provider versions may be used. to make similar constraints on which provider versions may be used.
The value for `required_version` is a string containing a comma-separated The value for `required_version` is a string containing a comma-separated
@ -100,7 +100,7 @@ The `required_providers` setting is a map specifying a version constraint for
each provider required by your configuration. each provider required by your configuration.
This is one of several ways to define This is one of several ways to define
[provider version constraints](/docs/configuration/providers.html#provider-versions), [provider version constraints](./providers.html#provider-versions),
and is particularly suited to re-usable modules that expect a provider and is particularly suited to re-usable modules that expect a provider
configuration to be provided by their caller but still need to impose a configuration to be provided by their caller but still need to impose a
minimum version for that provider. minimum version for that provider.

View File

@ -0,0 +1,203 @@
---
layout: "docs"
page_title: "Type Constraints"
sidebar_current: "docs-config-types"
description: |-
Terraform module authors and provider developers can use detailed type
constraints to validate the inputs of their modules and resources.
---
# Type Constraints
Terraform module authors and provider developers can use detailed type
constraints to validate user-provided values for their input variables and
resource arguments. This requires some additional knowledge about Terraform's
type system, but allows you to build a more resilient user interface for your
modules and resources.
## Type Keywords and Constructors
Type constraints are expressed using a mixture of _type keywords_ and
function-like constructs called _type constructors._
* Type keywords are unquoted symbols that represent a static type.
* Type constructors are unquoted symbols followed by a pair of
parentheses, which contain an argument that specifies more information about
the type. Without its argument, a type constructor does not fully
represent a type; instead, it represents a _kind_ of similar types.
Type constraints look like other kinds of Terraform
[expressions](./expressions.html), but are a special syntax. Within the
Terraform language, they are only valid in the `type` argument of an
[input variable](./variables.html).
## Primitive Types
A _primitive_ type is a simple type that isn't made from any other types. All
primitive types in Terraform are represented by a type keyword. The available
primitive types are:
* `string`: a sequence of Unicode characters representing some text, such
as `"hello"`.
* `number`: a numeric value. The `number` type can represent both whole
numbers like `15` and fractional values such as `6.283185`.
* `bool`: either `true` or `false`. `bool` values can be used in conditional
logic.
### Conversion of Primitive Types
The Terraform language will automatically convert `number` and `bool` values
to `string` values when needed, and vice-versa as long as the string contains
a valid representation of a number or boolean value.
* `true` converts to `"true"`, and vice-versa
* `false` converts to `"false"`, and vice-versa
* `15` converts to `"15"`, and vice-versa
## The "Any" Type
The type keyword `any` is a special type constraint that accepts any value.
## Complex Types
A _complex_ type is a type that groups multiple values into a single value.
Complex types are represented by type constructors, but several of them
also have shorthand keyword versions.
There are two categories of complex types: collection types (for grouping
similar values), and structural types (for grouping potentially dissimilar
values).
### Collection Types
A _collection_ type allows multiple values of _one_ other type to be grouped
together as a single value. The type of value _within_ a collection is called
its _element type._ All collection types must have an element type, which is
provided as the argument to their constructor.
For example, the type `list(string)` means "list of strings", which is a
different type than `list(number)`, a list of numbers. All elements of a
collection must always be of the same type.
The three kinds of collection type in the Terraform language are:
* `list(...)`: a sequence of values identified by consecutive whole numbers
starting with zero.
The keyword `list` is a shorthand for `list(any)`, which accepts any
element type as long as every element is the same type. This is for
compatibility with older configurations; for new code, we recommend using
the full form.
* `map(...)`: a collection of values where each is identified by a string label.
The keyword `map` is a shorthand for `map(any)`, which accepts any
element type as long as every element is the same type. This is for
compatibility with older configurations; for new code, we recommend using
the full form.
* `set(...)`: a collection of unique values that do not have any secondary
identifiers or ordering.
### Structural Types
A _structural_ type allows multiple values of _several distinct types_ to be
grouped together as a single value. Structural types require a _schema_ as an
argument, to specify which types are allowed for which elements.
The two kinds of structural type in the Terraform language are:
* `object(...)`: a collection of named attributes that each have their own type.
The schema for object types is `{ <KEY> = <TYPE>, <KEY> = <TYPE>, ... }` a
pair of curly braces containing a comma-separated series of `<KEY> = <TYPE>`
pairs. Values that match the object type must contain _all_ of the specified
keys, and the value for each key must match its specified type. (Values with
_additional_ keys can still match an object type, but the extra attributes
are discarded during type conversion.)
* `tuple(...)`: a sequence of elements identified by consecutive whole
numbers starting with zero, where each element has its own type.
The schema for tuple types is `[<TYPE>, <TYPE>, ...]` a pair of square
brackets containing a comma-separated series of types. Values that match the
tuple type must have _exactly_ the same number of elements (no more and no
fewer), and the value in each position must match the specified type for
that position.
For example: an object type of `object({ name=string, age=number })` would match
a value like the following:
```hcl
{
name = "John"
age = 52
}
```
Also, an object type of `object({ id=string, cidr_block=string })` would match
the object produced by a reference to an `aws_vpc` resource, like
`aws_vpc.example_vpc`; although the resource has additional attributes, they
would be discarded during type conversion.
Finally, a tuple type of `tuple([string, number, bool])` would match a value
like the following:
```hcl
["a", 15, true]
```
### Complex Type Literals
The Terraform language has literal expressions for creating tuple and object
values, which are described in
[Expressions: Literal Expressions](./expressions.html#literal-expressions) as
"list/tuple" literals and "map/object" literals, respectively.
Terraform does _not_ provide any way to directly represent lists, maps, or sets.
However, due to the automatic conversion of complex types (described below), the
difference between similar complex types is almost never relevant to a normal
user, and most of the Terraform documentation conflates lists with tuples and
maps with objects. The distinctions are only useful when restricting input
values for a module or resource.
### Conversion of Complex Types
Similar kinds of complex types (list/tuple/set and map/object) can usually be
used interchangeably within the Terraform language, and most of Terraform's
documentation glosses over the differences between the kinds of complex type.
This is due to two conversion behaviors:
* Whenever possible, Terraform converts values between similar kinds of complex
types if the provided value is not the exact type requested. "Similar kinds"
is defined as follows:
* Objects and maps are similar.
* A map (or a larger object) can be converted to an object if it has
_at least_ the keys required by the object schema. Any additional
attributes are discarded during conversion, which means map -> object
-> map conversions can be lossy.
* Tuples and lists are similar.
* A list can only be converted to a tuple if it has _exactly_ the
required number of elements.
* Sets are _almost_ similar to both tuples and lists:
* When a list or tuple is converted to a set, duplicate values are
discarded and the ordering of elements is lost.
* When a `set` is converted to a list or tuple, the elements will be
in an arbitrary order. If the set's elements were strings, they will
be in lexicographical order; sets of other element types do not
guarantee any particular order of elements.
* Whenever possible, Terraform converts _element values_ within a complex type,
either by converting complex-typed elements recursively or as described above
in [Conversion of Primitive Types](#conversion-of-primitive-types).
For example: if a module argument requires a value of type `list(string)` and a
user provides the tuple `["a", 15, true]`, Terraform will internally transform
the value to `["a", "15", "true"]` by converting the elements to the required
`string` element type. Later, if the module uses those elements to set different
resource arguments that require a string, a number, and a bool (respectively),
Terraform will automatically convert the second and third strings back to the
required types at that time, since they contain valid representations of a
number and a bool.
On the other hand, automatic conversion will fail if the provided value
(including any of its element values) is incompatible with the required type. If
an argument requires a type of `map(string)` and a user provides the object
`{name = ["Kristy", "Claudia", "Mary Anne", "Stacey"], age = 12}`, Terraform
will raise a type mismatch error, since a tuple cannot be converted to a string.

View File

@ -10,17 +10,24 @@ description: |-
# Input Variables # Input Variables
Input variables serve as parameters for a Terraform module, allowing aspects Input variables serve as parameters for a Terraform module, allowing aspects
of the a module to be customized without altering the module's own source code, of the module to be customized without altering the module's own source code,
and allowing modules to be shared between different configurations. and allowing modules to be shared between different configurations.
When you declare variables in the root module of your configuration, you can When you declare variables in the root module of your configuration, you can
set their values using CLI arguments and environment variables. set their values using CLI options and environment variables.
When you declare them in [_child_ modules](/docs/configuration/modules.html), When you declare them in [child modules](./modules.html),
you can use the to pass values from parent to child. the calling module should pass values in the `module` block.
Input variable usage is introduced in the Getting Started guide section Input variable usage is introduced in the Getting Started guide section
[_Input Variables_](/intro/getting-started/variables.html). [_Input Variables_](/intro/getting-started/variables.html).
-> **Note:** For brevity, input variables are often referred to as just
"variables" or "Terraform variables" when it is clear from context what sort of
variable is being discussed. Other kinds of variables in Terraform include
_environment variables_ (set by the shell where Terraform runs) and _expression
variables_ (used to indirectly represent a value in an
[expression](./expressions.html)).
## Declaring an Input Variable ## Declaring an Input Variable
Each input variable accepted by a module must be declared using a `variable` Each input variable accepted by a module must be declared using a `variable`
@ -37,35 +44,40 @@ variable "availability_zone_names" {
} }
``` ```
For brevity, input variables are often referred to as just "variables" for
short, where it is clear from context what sort of variable is being discussed.
The label after the `variable` keyword is a name for the variable, which must The label after the `variable` keyword is a name for the variable, which must
be unique between all variables in the same module. This name is used to be unique among all variables in the same module. This name is used to
assign a value to the variable from outside and to reference the variable's assign a value to the variable from outside and to reference the variable's
value from within the module. value from within the module.
The name of a variable can be any valid identifier. However, due to the The name of a variable can be any valid [identifier](./syntax.html#identifiers)
interpretation of [module configuration blocks](/docs/configuration/modules.html), _except_ the following:
the names `source`, `version`, `providers`, `count`, `for_each`, and `lifecycle`
are reserved for Terraform's own use and may not be declared as variable names.
The variable declaration may optionally include a `type` argument, which - `source`
describes what value types are accepted for the variable, as described - `version`
- `providers`
- `count`
- `for_each`
- `lifecycle`
These names are reserved for meta-arguments in
[module configuration blocks](./modules.html), and cannot be
declared as variable names.
The variable declaration can optionally include a `type` argument to
specify what value types are accepted for the variable, as described
in the following section. in the following section.
The variable declaration may also include a `default` argument. If present, The variable declaration can also include a `default` argument. If present,
the variable is considered to be _optional_ and the default value will be used the variable is considered to be _optional_ and the default value will be used
if no overridden value is set when calling the module. The `default` argument if no value is set when calling the module or running Terraform. The `default`
requires a literal value and cannot reference other objects in the argument requires a literal value and cannot reference other objects in the
configuration. configuration.
## Using Input Variable Values ## Using Input Variable Values
Within the module that declared a variable, its value can be accessed from Within the module that declared a variable, its value can be accessed from
within [expressions](/docs/configuration/expressions.html) using an expression within [expressions](./expressions.html) as `var.<NAME>`,
like `var.image_id`, where the name after the period corresponds to the label where `<NAME>` matches the label given in the declaration block:
given in the declaration block:
```hcl ```hcl
resource "aws_instance" "example" { resource "aws_instance" "example" {
@ -79,42 +91,44 @@ the module where it was declared.
## Type Constraints ## Type Constraints
The `type` argument in a `variable` block allows you to restrict the type of The `type` argument in a `variable` block allows you to restrict the
value that will be accepted as the value for a variable. If no type constraint [type of value](./expressions.html#types-and-values) that will be accepted as
is set then a value of any type is accepted. the value for a variable. If no type constraint is set then a value of any type
is accepted.
While type constraints are optional, we recommend specifying them because it While type constraints are optional, we recommend specifying them; they
serves as helpful additional documentation for users of the module and it serve as easy reminders for users of the module, and
allows Terraform to return a helpful error message if the wrong type is used. allow Terraform to return a helpful error message if the wrong type is used.
Type constraints are created from a mixture of type keywords and type Type constraints are created from a mixture of type keywords and type
construction functions. The supported type keywords are: constructors. The supported type keywords are:
* `string` * `string`
* `number` * `number`
* `bool` * `bool`
The type construction functions allow you to specify complex types such as The type constructors allow you to specify complex types such as
collections: collections:
* `list(<type>)` * `list(<TYPE>)`
* `set(<type>)` * `set(<TYPE>)`
* `map(<type>)` * `map(<TYPE>)`
* `object({attr_name = <type>, ... })` * `object({<ATTR NAME> = <TYPE>, ... })`
* `tuple([<type>, ...])` * `tuple([<TYPE>, ...])`
The keyword `any` may be used to indicate that any type is acceptable. For The keyword `any` may be used to indicate that any type is acceptable. For
more information on the meaning and behavior of these different types, more information on the meaning and behavior of these different types, as well
see [the _Expressions_ section](/docs/configuration/expressions.html). as detailed information about automatic conversion of complex types, see
[Type Constraints](./types.html).
If both the `type` and `default` arguments are specified, the given default If both the `type` and `default` arguments are specified, the given default
valuable must be convertible to the specified type. value must be convertible to the specified type.
## Input Variable Documentation ## Input Variable Documentation
Because the input variables of a module are part of the user interface of Because the input variables of a module are part of its user interface, you can
the module, you may specify a short description of the purpose of each briefly describe the purpose of each variable using the optional
variable using the optional `description` argument: `description` argument:
```hcl ```hcl
variable "image_id" { variable "image_id" {
@ -123,9 +137,9 @@ variable "image_id" {
} }
``` ```
The description for a variable should be a concise description of the purpose The description should concisely explain the purpose
of the variable and what kind of value is expected. This description string of the variable and what kind of value is expected. This description string
may be included in documentation about the module, and so it should be written might be included in documentation about the module, and so it should be written
from the perspective of the user of the module rather than its maintainer. For from the perspective of the user of the module rather than its maintainer. For
commentary for module maintainers, use comments. commentary for module maintainers, use comments.
@ -134,35 +148,42 @@ commentary for module maintainers, use comments.
When variables are declared in the root module of your configuration, they When variables are declared in the root module of your configuration, they
can be set in a number of ways: can be set in a number of ways:
* Individual assignments made on the command line. * [In a Terraform Enterprise workspace](/docs/enterprise/workspaces/variables.html).
* Variable definitions files, either specified on the command line or * Individually, with the `-var` command line option.
automatically loaded. * In variable definitions (`.tfvars`) files, either specified on the command line
* Environment variables. or automatically loaded.
* As environment variables.
The following sections describe these options in more detail. This section does The following sections describe these options in more detail. This section does
not apply to _child_ modules, where values for input variables are instead not apply to _child_ modules, where values for input variables are instead
assigned in the configuration of their parent module, as described in assigned in the configuration of their parent module, as described in
[_Modules_](/docs/configuration/modules.html). [_Modules_](./modules.html).
### Variables on the Command Line ### Variables on the Command Line
To specify individual modules on the command line, use the `-var` argument To specify individual modules on the command line, use the `-var` option
that is accepted by the `terraform plan` and `terraform apply` commands: when running the `terraform plan` and `terraform apply` commands:
``` ```
terraform apply -var="image_id=ami-abc123" terraform apply -var="image_id=ami-abc123"
``` ```
### Variable Definitions Files The `-var` option can be used any number of times in a single command.
### Variable Definitions (`.tfvars`) Files
To set lots of variables, it is more convenient to specify their values in To set lots of variables, it is more convenient to specify their values in
a _variable definitions file_, with a filename ending in either `.tfvars` a _variable definitions file_ (with a filename ending in either `.tfvars`
or `.tfvars.json`, and then specify that filename on the command line: or `.tfvars.json`) and then specify that file on the command line with
`-var-file`:
``` ```
terraform apply -var-file="testing.tfvars" terraform apply -var-file="testing.tfvars"
``` ```
-> **Note:** This is how Terraform Enterprise passes
[workspace variables](/docs/enterprise/workspaces/variables.html) to Terraform.
A variable definitions file uses the same basic syntax as Terraform language A variable definitions file uses the same basic syntax as Terraform language
files, but consists only of variable name assignments: files, but consists only of variable name assignments:
@ -175,10 +196,10 @@ availability_zone_names = [
``` ```
Terraform also automatically loads a number of variable definitions files Terraform also automatically loads a number of variable definitions files
automatically if they are present: if they are present:
* Files named exactly `terraform.tfvars` or `terraform.tfvars.json`. * Files named exactly `terraform.tfvars` or `terraform.tfvars.json`.
* Any files with names ending in either `.auto.tfvars` or `.auto.tfvars.json`. * Any files with names ending in `.auto.tfvars` or `.auto.tfvars.json`.
Files whose names end with `.json` are parsed instead as JSON objects, with Files whose names end with `.json` are parsed instead as JSON objects, with
the root object properties corresponding to variable names: the root object properties corresponding to variable names:
@ -213,23 +234,23 @@ and lower case letters as in the above example.
### Complex-typed Values ### Complex-typed Values
When variable values are provided in a variable definitions file, the usual When variable values are provided in a variable definitions file, Terraform's
syntax can be used to assign complex-typed values, like lists and maps. [usual syntax](./expressions.html#structural-types) can be used to assign
complex-typed values, like lists and maps.
Some special rules apply to the `-var` command line option and to environment Some special rules apply to the `-var` command line option and to environment
variables: to allow string values to be set conveniently, by default values variables. For convenience, Terraform defaults to interpreting `-var` and
assigned in these ways are interpreted as literal strings, and thus do not environment variable values as literal strings, which do not need to be quoted:
need to be themselves quoted:
``` ```
$ export TF_VAR_image_id=ami-abc123 $ export TF_VAR_image_id=ami-abc123
``` ```
However, if a variable in the root module is declared as being of a complex However, if a root module variable uses a [type constraint](#type-constraints)
type (list, set, map, object, or tuple), Terraform will instead attempt to to require a complex value (list, set, map, object, or tuple), Terraform will
parse it using the same syntax used within variable definitions files, instead attempt to parse its value using the same syntax used within variable
which requires cafeful attention to the string escaping rules in your definitions files, which requires cafeful attention to the string escaping rules
shell: in your shell:
``` ```
$ export TF_VAR_availability_zone_names='["us-west-1b","us-west-1d"]' $ export TF_VAR_availability_zone_names='["us-west-1b","us-west-1d"]'
@ -240,13 +261,23 @@ recommend always setting complex variable values via varable definitions files.
### Variable Definition Precedence ### Variable Definition Precedence
The above mechanisms for defining variable values can be used together in The above mechanisms for setting variables can be used together in any
any combination. If the same variable is assigned multiple values, the combination. If the same variable is assigned multiple values, Terraform uses
processing order is as follows, with the later items in this list taking the _last_ value it finds, overriding any previous values.
precedence over the earlier:
* Environment Variables Terraform loads variables in the following order, with later sources taking
precedence over earlier ones:
* Environment variables
* The `terraform.tfvars` file, if present. * The `terraform.tfvars` file, if present.
* The `terraform.tfvars.json` file, if present. * The `terraform.tfvars.json` file, if present.
* Any `-var` and `-var-file` arguments on the command line, in the order they * Any `*.auto.tfvars` or `*.auto.tfvars.json` files, processed in lexical order
are provided. of their filenames.
* Any `-var` and `-var-file` options on the command line, in the order they
are provided. (This includes variables set by a Terraform Enterprise
workspace.)
~> **Important:** In Terraform 0.12 and later, variables with map and object
values behave the same way as other variables: the last value found overrides
the previous values. This is a change from previous versions of Terraform, which
would _merge_ map values instead of overriding them.

View File

@ -2,7 +2,7 @@
<% content_for :sidebar do %> <% content_for :sidebar do %>
<ul class="nav docs-sidenav"> <ul class="nav docs-sidenav">
<li<%= sidebar_current("docs-config") %>> <li<%= sidebar_current("docs-config") %>>
<a href="/docs/configuration/index.html">Configuration</a> <a href="/docs/configuration/index.html">Configuration Language</a>
<ul class="nav"> <ul class="nav">
<li<%= sidebar_current("docs-config-resources") %>> <li<%= sidebar_current("docs-config-resources") %>>
<a href="/docs/configuration/resources.html">Resources</a> <a href="/docs/configuration/resources.html">Resources</a>
@ -51,6 +51,18 @@
<li<%= sidebar_current("docs-config-override") %>> <li<%= sidebar_current("docs-config-override") %>>
<a href="/docs/configuration/override.html">Override Files</a> <a href="/docs/configuration/override.html">Override Files</a>
</li> </li>
<li<%= sidebar_current("docs-config-style") %>>
<a href="/docs/configuration/style.html">Style Conventions</a>
</li>
<li<%= sidebar_current("docs-config-types") %>>
<a href="/docs/configuration/types.html">Type Constraints</a>
</li>
<li<%= sidebar_current("docs-config-syntax-json") %>>
<a href="/docs/configuration/syntax-json.html">JSON Configuration Syntax</a>
</li>
</ul> </ul>
</li> </li>
@ -238,36 +250,36 @@
<li<%= sidebar_current("docs-provisioners") %>> <li<%= sidebar_current("docs-provisioners") %>>
<a href="/docs/provisioners/index.html">Provisioners</a> <a href="/docs/provisioners/index.html">Provisioners</a>
<ul class="nav"> <ul class="nav">
<li<%= sidebar_current("docs-provisioners-chef") %>> <li<%= sidebar_current("docs-provisioners-connection") %>>
<a href="/docs/provisioners/chef.html">chef</a> <a href="/docs/provisioners/connection.html">Provisioner Connections</a>
</li> </li>
<li<%= sidebar_current("docs-provisioners-connection") %>> <li<%= sidebar_current("docs-provisioners-chef") %>>
<a href="/docs/provisioners/connection.html">connection</a> <a href="/docs/provisioners/chef.html">chef Provisioner</a>
</li> </li>
<li<%= sidebar_current("docs-provisioners-file") %>> <li<%= sidebar_current("docs-provisioners-file") %>>
<a href="/docs/provisioners/file.html">file</a> <a href="/docs/provisioners/file.html">file Provisioner</a>
</li> </li>
<li<%= sidebar_current("docs-provisioners-habitat") %>> <li<%= sidebar_current("docs-provisioners-habitat") %>>
<a href="/docs/provisioners/habitat.html">habitat</a> <a href="/docs/provisioners/habitat.html">habitat Provisioner</a>
</li> </li>
<li<%= sidebar_current("docs-provisioners-local") %>> <li<%= sidebar_current("docs-provisioners-local") %>>
<a href="/docs/provisioners/local-exec.html">local-exec</a> <a href="/docs/provisioners/local-exec.html">local-exec Provisioner</a>
</li> </li>
<li<%= sidebar_current("docs-provisioners-null-resource") %>> <li<%= sidebar_current("docs-provisioners-null-resource") %>>
<a href="/docs/provisioners/null_resource.html">null_resource</a> <a href="/docs/provisioners/null_resource.html">null_resource Provisioner</a>
</li> </li>
<li<%= sidebar_current("docs-provisioners-remote") %>> <li<%= sidebar_current("docs-provisioners-remote") %>>
<a href="/docs/provisioners/remote-exec.html">remote-exec</a> <a href="/docs/provisioners/remote-exec.html">remote-exec Provisioner</a>
</li> </li>
<li<%= sidebar_current("docs-provisioners-salt-masterless") %>> <li<%= sidebar_current("docs-provisioners-salt-masterless") %>>
<a href="/docs/provisioners/salt-masterless.html">salt-masterless</a> <a href="/docs/provisioners/salt-masterless.html">salt-masterless Provisioner</a>
</li> </li>
</ul> </ul>
</li> </li>

View File

@ -5,14 +5,14 @@
<li<%= sidebar_current("docs-config-index") %>> <li<%= sidebar_current("docs-config-index") %>>
<a class="back" href="/docs/configuration/index.html">Terraform Language</a> <a class="back" href="/docs/configuration/index.html">Terraform Language</a>
</li> </li>
<li<%= sidebar_current("docs-config-functions") %>> <li<%= sidebar_current("docs-config-functions") %>>
<a class="back" href="/docs/configuration/functions.html">Functions</a> <a class="back" href="/docs/configuration/functions.html">Functions</a>
</li> </li>
<li<%= sidebar_current("docs-funcs-numeric") %>> <li<%= sidebar_current("docs-funcs-numeric") %>>
<a href="#">Numeric Functions</a> <a href="#docs-funcs-numeric">Numeric Functions</a>
<ul class="nav nav-visible"> <ul class="nav nav-visible" id="docs-funcs-numeric">
<li<%= sidebar_current("docs-funcs-numeric-abs") %>> <li<%= sidebar_current("docs-funcs-numeric-abs") %>>
<a href="/docs/configuration/functions/abs.html">abs</a> <a href="/docs/configuration/functions/abs.html">abs</a>
@ -50,8 +50,8 @@
</li> </li>
<li<%= sidebar_current("docs-funcs-string") %>> <li<%= sidebar_current("docs-funcs-string") %>>
<a href="#">String Functions</a> <a href="#docs-funcs-string">String Functions</a>
<ul class="nav nav-visible"> <ul class="nav nav-visible" id="docs-funcs-string">
<li<%= sidebar_current("docs-funcs-string-chomp") %>> <li<%= sidebar_current("docs-funcs-string-chomp") %>>
<a href="/docs/configuration/functions/chomp.html">chomp</a> <a href="/docs/configuration/functions/chomp.html">chomp</a>
@ -104,8 +104,8 @@
</ul> </ul>
<li<%= sidebar_current("docs-funcs-collection") %>> <li<%= sidebar_current("docs-funcs-collection") %>>
<a href="#">Collection Functions</a> <a href="#docs-funcs-collection">Collection Functions</a>
<ul class="nav nav-visible"> <ul class="nav nav-visible" id="docs-funcs-collection">
<li<%= sidebar_current("docs-funcs-collection-chunklist") %>> <li<%= sidebar_current("docs-funcs-collection-chunklist") %>>
<a href="/docs/configuration/functions/chunklist.html">chunklist</a> <a href="/docs/configuration/functions/chunklist.html">chunklist</a>
@ -195,8 +195,8 @@
</li> </li>
<li<%= sidebar_current("docs-funcs-encoding") %>> <li<%= sidebar_current("docs-funcs-encoding") %>>
<a href="#">Encoding Functions</a> <a href="#docs-funcs-encoding">Encoding Functions</a>
<ul class="nav nav-visible"> <ul class="nav nav-visible" id="docs-funcs-encoding">
<li<%= sidebar_current("docs-funcs-encoding-base64decode") %>> <li<%= sidebar_current("docs-funcs-encoding-base64decode") %>>
<a href="/docs/configuration/functions/base64decode.html">base64decode</a> <a href="/docs/configuration/functions/base64decode.html">base64decode</a>
@ -230,8 +230,8 @@
</li> </li>
<li<%= sidebar_current("docs-funcs-file") %>> <li<%= sidebar_current("docs-funcs-file") %>>
<a href="#">Filesystem Functions</a> <a href="#docs-funcs-file">Filesystem Functions</a>
<ul class="nav nav-visible"> <ul class="nav nav-visible" id="docs-funcs-file">
<li<%= sidebar_current("docs-funcs-file-dirname") %>> <li<%= sidebar_current("docs-funcs-file-dirname") %>>
<a href="/docs/configuration/functions/dirname.html">dirname</a> <a href="/docs/configuration/functions/dirname.html">dirname</a>
@ -261,8 +261,8 @@
</li> </li>
<li<%= sidebar_current("docs-funcs-datetime") %>> <li<%= sidebar_current("docs-funcs-datetime") %>>
<a href="#">Date and Time Functions</a> <a href="#docs-funcs-datetime">Date and Time Functions</a>
<ul class="nav nav-visible"> <ul class="nav nav-visible" id="docs-funcs-datetime">
<li<%= sidebar_current("docs-funcs-datetime-timeadd") %>> <li<%= sidebar_current("docs-funcs-datetime-timeadd") %>>
<a href="/docs/configuration/functions/timeadd.html">timeadd</a> <a href="/docs/configuration/functions/timeadd.html">timeadd</a>
@ -276,8 +276,8 @@
</li> </li>
<li<%= sidebar_current("docs-funcs-crypto") %>> <li<%= sidebar_current("docs-funcs-crypto") %>>
<a href="#">Hash and Crypto Functions</a> <a href="#docs-funcs-crypto">Hash and Crypto Functions</a>
<ul class="nav nav-visible"> <ul class="nav nav-visible" id="docs-funcs-crypto">
<li<%= sidebar_current("docs-funcs-crypto-base64sha256") %>> <li<%= sidebar_current("docs-funcs-crypto-base64sha256") %>>
<a href="/docs/configuration/functions/base64sha256.html">base64sha256</a> <a href="/docs/configuration/functions/base64sha256.html">base64sha256</a>
@ -319,8 +319,8 @@
</li> </li>
<li<%= sidebar_current("docs-funcs-ipnet") %>> <li<%= sidebar_current("docs-funcs-ipnet") %>>
<a href="#">IP Network Functions</a> <a href="#docs-funcs-ipnet">IP Network Functions</a>
<ul class="nav nav-visible"> <ul class="nav nav-visible" id="docs-funcs-ipnet">
<li<%= sidebar_current("docs-funcs-ipnet-cidrhost") %>> <li<%= sidebar_current("docs-funcs-ipnet-cidrhost") %>>
<a href="/docs/configuration/functions/cidrhost.html">cidrhost</a> <a href="/docs/configuration/functions/cidrhost.html">cidrhost</a>
@ -340,7 +340,6 @@
</ul> </ul>
</div> </div>
<% end %> <% end %>
<%= yield %> <%= yield %>
<% end %> <% end %>