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,
or defined by another separate Terraform configuration.
Each [provider](/docs/configuration/providers.html) make offer data sources
alongside its set of [resource types](/docs/configuration/resources.html#resource-types-and-arguments).
Each [provider](./providers.html) may offer data sources
alongside its set of [resource types](./resources.html#resource-types-and-arguments).
## 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
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
data sources that most often belong to a single cloud or on-premises
infrastructure platform.
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
use of [expressions](/docs/configuration/expressions.html) and other dynamic
use of [expressions](./expressions.html) and other dynamic
Terraform language features.
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 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`
blocks, with the same meaning and syntax as in `resource` blocks.
@ -125,7 +125,7 @@ resources.
## 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 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
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.
## Lifecycle Customizations
@ -167,8 +167,8 @@ data "aws_ami" "web" {
## Description
The `data` block creates a data instance of the given `TYPE` (first
parameter) and `NAME` (second parameter). The combination of the type
The `data` block creates a data instance of the given _type_ (first
block label) and _name_ (second block label). The combination of the type
and name must be unique.
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).
Each data instance will export one or more attributes, which can be
interpolated into other resources using variables of the form
`data.TYPE.NAME.ATTR`. For example:
used in other resources as reference expressions of the form
`data.<TYPE>.<NAME>.<ATTRIBUTE>`. For example:
```hcl
resource "aws_instance" "web" {
ami = "${data.aws_ami.web.id}"
ami = data.aws_ami.web.id
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
`provider` meta-parameter can be used where a configuration has
Similarly to [resources](./resources.html), the
`provider` meta-argument can be used where a configuration has
multiple aliased instances of the same provider:
```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.
## Data Source Lifecycle
### Data Source Lifecycle
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

View File

@ -16,14 +16,17 @@ references to data exported by resources, arithmetic, conditional evaluation,
and a number of built-in functions.
Expressions can be used in a number of places in the Terraform language,
but some contexts place restrictions on which expression constructs are allowed,
such as requiring a literal value of a particular type, or forbidding
references to resource attributes. The other pages in this section describe
the contexts where expressions may be used and which expression features
are allowed in each case.
but some contexts limit which expression constructs are allowed,
such as requiring a literal value of a particular type or forbidding
references to resource attributes. Each language feature's documentation
describes any restrictions it places on expressions.
The following sections describe all of the features of the configuration
syntax.
You can experiment with the behavior of Terraform's expressions from
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
@ -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
applied to it.
A _literal expression_ is an expression that directly represents a particular
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"`.
The Terraform language uses the following types for its values:
* `string`: a sequence of Unicode characters representing some text, like
`"hello"`.
* `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
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
to `string` values when needed, and vice-versa as long as the string contains
a valid representation of a number of boolean value.
Strings, numbers, and bools are sometimes called _primitive types._ Lists/tuples and maps/objects are sometimes called _complex types,_ _structural types,_ or _collection types._
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
* `false` converts to `"false"`, 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
together as a single value. The type of value _within_ a collection is called
its _element type_, and all collection types must have an element type.
A _literal expression_ is an expression that directly represents a particular
constant value. Terraform has a literal expression syntax for each of the value
types described above:
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.
* Strings are usually represented by a double-quoted sequence of Unicode
characters, `"like this"`. There is also a "heredoc" syntax for more complex
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
starting with zero.
* `map(...)`: a collection of values where each is identified by a string label.
* `set(...)`: a collection of unique values that do not have any secondary
identifiers or ordering.
There is no direct syntax for creating collection type values, but the
Terraform language can automatically convert a structural type value (as
defined in the next section) to a similar collection type as long as all
of its elements can be converted to the required element type.
### Structural Types
A _structural_ type is another way to combine multiple values into a single
value, but structural types allow each value to be of a distinct type.
The two _structural type kinds_ in the Terraform language are:
* `object(...)`: has named attributes that each have their own type.
* `tuple(...)`: has a sequence of elements identified by consecutive whole
numbers starting with zero, where each element has its own type.
An object type value can be created using an object expression:
```hcl
{
```hcl
{
name = "John"
age = 52
}
```
}
```
The type of the object value created by this expression is
`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.
Key/value pairs can be separated by either a comma or a line break. Values
can be arbitrary expressions. Keys are strings; they can be left unquoted if
they are a valid [identifier](./syntax.html#identifiers), but must be quoted
otherwise. You can use a non-literal expression as a key by wrapping it in
parentheses, like `(var.business_unit_tag_name) = "SRE"`.
Similarly, a tuple type value can be created using a tuple expression:
## Indices and Attributes
```hcl
["a", 15, true]
```
[inpage-index]: #indices-and-attributes
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.
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.
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.
Map/object attributes with names that are valid identifiers can also be accessed
using the dot-separated attribute notation, like `local.object.attrname`.
In cases where a map might contain arbitrary user-specified keys, we recommend
using only the square-bracket index notation (`local.map["keyname"]`).
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.
## References to Named Values
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.
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
standalone expressions, or combine them with other expressions to compute new
values.
## References to Named Objects
The following named values are available:
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`.
* `<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].
The following named objects are available:
Any named value that does not match another pattern listed below
will be interpreted by Terraform as a reference to a managed resource.
* `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
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
* `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
[workspace](/docs/state/workspaces.html).
Terraform analyses the block bodies of constructs such as resources and module
calls to automatically infer dependencies between objects from the use of
some of these reference types in expressions. For example, an object with an
argument expression that refers to a managed resource creates and implicit
dependency between that object and the resource.
Although many of these names use dot-separated paths that resemble
[attribute notation][inpage-index] for elements of object values, they are not
implemented as real objects. This means you must use them exactly as written:
you cannot use square-bracket notation to replace the dot-separated paths, and
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
_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.
### Named Values and Dependencies
Additional expression variables are available in specific contexts. These are
described in other documentation sections describing those specific features.
Constructs like resources and module calls often use references to named values
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
@ -247,25 +256,11 @@ effect:
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
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
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.
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.
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 |
| ----- | -------------------- |
| 6 | `*`, `/`, `%` |
| 5 | `+`, `-` |
| 4 | `>`, `>=`, `<`, `<=` |
| 3 | `==`, `!=` |
| 2 | `&&` |
| 1 | `||` |
1. `!`, `-` (multiplication by `-1`)
1. `*`, `/`, `%`
1. `+`, `-` (subtraction)
1. `>`, `>=`, `<`, `<=`
1. `==`, `!=`
1. `&&`
1. `||`
Parentheses can be used to override the default order of operations. Without
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
A _conditional expression_ allows the selection of one of two values based
on whether another bool expression is `true` or `false`.
A _conditional expression_ uses the value of a bool expression to select one of
two values.
The syntax of a conditional expression is as follows:
@ -372,18 +366,17 @@ conditional expression will return without knowing the condition value.
## Function Calls
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
are similar to the operators but all follow a common syntax:
```hcl
function_name(argument1, argument2)
<FUNCTION NAME>(<ARGUMENT 1>, <ARGUMENT 2>)
```
The `function_name` specifies which function to call. Each defined function has
a _signature_, which defines how many arguments it expects and what value types
those arguments must have. The signature also defines the type of the result
value for any given set of argument types.
The function name specifies which function to call. Each defined function
expects a specific number of arguments with specific value types, and returns a
specific value type as a result.
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
@ -393,26 +386,33 @@ numerically smallest:
min(55, 3453, 2)
```
If the arguments to pass are available in a list or tuple value, that value
can be _expanded_ into separate arguments using the `...` symbol after that
argument:
### Expanding Function Arguments
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
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
[the function reference](/docs/configuration/functions.html).
[the function reference](./functions.html).
## `for` Expressions
A _`for` expression_ allows you create a structural type value by transforming
another structural or collection type value. Each element in the input value
A _`for` expression_ creates a complex type value by transforming
another complex type value. Each element in the input value
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.
For example, if `var.list` is a list of strings then it can be converted to
a list of strings with all-uppercase letters with the following:
For example, if `var.list` is a list of strings, then the following expression
produces a list of strings with all-uppercase letters:
```hcl
[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.
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 != ""]
@ -460,19 +461,19 @@ together results that have a common key:
## 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.
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]
```
This is equivalent to the following _splat expression_:
This is equivalent to the following _splat expression:_
```
```hcl
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
right of the symbol:
```
```hcl
var.list[*].interfaces[0].name
```
The above expression is equivalent to the following `for` expression:
```
```hcl
[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
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`
@ -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
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
Expressions can usually be used only when assigning a value to an attribute
argument using the `name = expression` form. This covers many uses, but
some resource types include in their arguments _nested blocks_, which
do not accept expressions:
Within top-level block constructs like resources, expressions can usually be
used only when assigning a value to an argument using the `name = expression`
form. This covers many uses, but some resource types include repeatable _nested
blocks_ in their arguments, which do not accept expressions:
```hcl
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
block type `dynamic` is supported inside `resource`, `data`, `provider`,
and `provisioner` blocks:
You can dynamically construct repeatable nested blocks like `ingress` using a
special `dynamic` block type, which is supported inside `resource`, `data`,
`provider`, and `provisioner` blocks:
```hcl
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
`for_each` argument, generating a nested block for each element by evaluating
the nested `content` block. When evaluating the block, a temporary variable
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
used to override the name of the iterator variable.
A `dynamic` block acts much like a `for` expression, but produces nested blocks
instead of a complex typed value. It iterates over a given complex value, and
generates a nested block for each element of that complex value.
- The label of the dynamic block (`"ingress"` in the example above) specifies
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,
you can use a `for` expression or splat expression to transform an existing
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,
data source, provider or provisioner being configured. It is _not_ possible
to generate meta-argument blocks such as `lifecycle` and `provisioner`
blocks, since Terraform must process these before it is safe to evaluate
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
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.
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
beginning a template sequence, double the leading character: `$${` or `%%{`.
## String Templates
Within quoted and heredoc string expressions, the sequences `${` and `%{`
begin _template sequences_. Templates allow expressions to be embedded directly
into the string sequence, and thus allow strings to be dynamically constructed
from other values in a concise way.
Within quoted and heredoc string expressions, the sequences `${` and `%{` begin
_template sequences_. Templates let you directly embed expressions into a string
literal, to dynamically construct strings from other values.
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
then inserts it into the final string:
@ -687,25 +701,27 @@ then inserts it into the final string:
In the above example, the named object `var.name` is accessed and its value
inserted into the string, producing a result like "Hello, Juan!".
### Directives
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.
The following directives are supported:
* The `if` directive chooses between two templates based on a conditional
expression:
* The `if <BOOL>`/`else`/`endif` directive chooses between two templates based
on the value of a bool expression:
```hcl
"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`.
* The `for` directive iterates over each of the elements of a given collection
or structural value and evaluates a given template once for each element,
concatenating the results together:
* The `for <NAME> in <COLLECTION>` / `endfor` directive iterates over the
elements of a given collection or structural value and evaluates a given
template once for each element, concatenating the results together:
```hcl
<<EOT
@ -718,12 +734,13 @@ The following directives are supported:
The name given immediately after the `for` keyword is used as a temporary
variable name which can then be referenced from the nested template.
To allow for template directives to be formatted for readability without
introducing unwanted additional spaces and newlines in the result, all
template sequences can include optional _strip markers_ `~` either immediately
after the introducer or immediately before the end. When present, the sequence
consumes all of the literal whitespace (spaces and newlines) either before
or after the sequence:
To allow template directives to be formatted for readability without adding
unwanted spaces and newlines to the result, all template sequences can include
optional _strip markers_ (`~`), immediately after the opening characters or
immediately before the end. When a strip marker is present, the template
sequence consumes all of the literal whitespace (spaces and newlines) either
before the sequence (if the marker appears at the beginning) or after (if the
marker appears at the end):
```hcl
<<EOT
@ -744,6 +761,6 @@ server 10.1.16.34
```
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
sequences.

View File

@ -19,12 +19,12 @@ max(5, 12, 9)
```
For more details on syntax, see
[_Function Calls_](/docs/configuration/expressions.html#function-calls)
[_Function Calls_](./expressions.html#function-calls)
on the Expressions page.
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
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
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).
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:
| 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).
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:
| Terraform type | JSON type |

View File

@ -8,7 +8,7 @@ description: |-
# `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

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
Terraform run. We do not recommend using this function in resource attributes,
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.
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
recommend using the `uuid` function in resource configurations, but it can
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)
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
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
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
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.
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.
## 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
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.
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
Because Terraform's configuration language is declarative, the ordering of
blocks is generally not significant, except in some specific situations which
are described explicitly elsewhere.
blocks is generally not significant. (The order of `provisioner` blocks within a
resource is the only major feature where block order matters.)
Terraform automatically processes resources in the correct order based on
relationships defined between them in configuration, and so you can organize
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
configuations. It defines the Terraform language syntax and overall structure,
and coordinates sequences of changes that must be made to make remote
infrastructure match the given configuration.
The Terraform command line interface (CLI) is a general engine for evaluating
and applying Terraform configuations. It defines the Terraform language syntax
and overall structure, and coordinates sequences of changes that must be made to
make remote infrastructure match the given configuration.
Terraform Core has no knowledge of specific infrastructure object types, though.
Instead, Terraform uses plugins called [providers](/docs/configuration/providers.html)
that each define and know how to manage a set of resource types. Most providers
are associated with a particular cloud or on-premises infrastructure service,
allowing Terraform to manage infrastructure objects within that service.
This general engine has no knowledge about specific types of infrastructure
objects. Instead, Terraform uses plugins called
[providers](./providers.html) that each define and manage a
set of resource types. Most providers are associated with a particular cloud or
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
exact details of resources can vary between services, but Terraform Core
ensures that the same language constructs and syntax are available across
all services and allows resource types from different services to be combined
as needed.
Terraform doesn't have a concept of platform-independent resource types
 resources are always tied to a provider, since the features of similar
resources can vary greatly from provider to provider. But Terraform CLI's shared
configuration engine ensures that the same language constructs and syntax are
available across all services and allows resource types from different services
to be combined as needed.
## Example
@ -98,6 +130,7 @@ variable "base_cidr_block" {
variable "availability_zones" {
description = "A list of availability zones in which to create subnets"
type = list(string)
}
provider "aws" {

View File

@ -9,15 +9,18 @@ description: |-
# Local Values
A local value assigns a name to an [expression](/docs/configuration/expressions.html),
allowing it to then be used multiple times within a module without repeating
A local value assigns a name to an [expression](./expressions.html),
allowing it to be used multiple times within a module without repeating
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
[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.
-> **Note:** For brevity, local values are often referred to as just "locals"
when the meaning is clear from context.
## Declaring a Local Value
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
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
@ -54,7 +54,7 @@ locals {
```
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.
```
@ -67,12 +67,12 @@ resource "aws_instance" "example" {
## 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
configuration hard to read by future maintainers by hiding the actual values
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
future. The ability to easily change the value in a central place is the key
advantage of local values.

View File

@ -9,12 +9,13 @@ description: |-
# Modules
A _module_ is a container for multiple resources that are used together.
Every Terraform configuration has at least one module, known as its
_root module_, which consists of the resources defined in the `.tf` files in
the main working directory.
A module can call other modules, allowing the suite of resources within the
child module to be included into the configuration in a concise way. Modules
A module can call other modules, which lets you include the child module's
resources into the configuration in a concise way. Modules
can also be called multiple times, either within the same configuration or
in separate configurations, allowing resource configurations to be packaged
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
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:
```hcl
@ -39,19 +40,22 @@ module "servers" {
}
```
The label immediately after the `module` keyword is a name that will be used
to refer to this instance of the module within the calling module. The
_calling module_ is the one that includes the `module` block shown above.
A module that includes a `module` block like this is the _calling module_ of the
child module.
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.
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.
The `source` argument is a meta-argument defined and processed by Terraform
itself. Its value is the path to a local directory containing the module's
configuration files, or optionally a remote module source that Terraform should
download and use. For more information on possible values for this argument,
see [_Module Sources_](/docs/modules/sources.html).
All modules require a `source` argument, which is a meta-argument defined by
Terraform CLI. Its value is either the path to a local directory of the
module's configuration files, or a remote module source that Terraform should
download and use. This value must be a literal string with no template
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
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
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.
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
Along with the `source` meta-argument described above, module blocks have

View File

@ -8,15 +8,24 @@ description: |-
# Output Values
Output values are like the return values of a Terraform module, allowing
a subset of the resource attributes within a child module to be exposed to
a parent module, or making certain values from a root module visible in the
CLI output after running `terraform apply`.
Output values are like the return values of a Terraform module, and have several
uses:
- 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
can be used elsewhere in configuration. Output values are a way to expose some
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
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
displayed to the user for output values in the root module.
For brevity, output values are often referred to simply as "outputs", where
the meaning is clear from context.
The `value` argument takes an [expression](/docs/configuration/expressions.html)
The `value` argument takes an [expression](./expressions.html)
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
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
Because the output values of a module are part of the user interface of
the module, you may specify a short description of the purpose of each
value using the optional `description` argument:
Because the output values of a module are part of its user interface, you can
briefly describe the purpose of each value using the optional `description`
argument:
```hcl
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
purpose 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
The description should concisely explain the
purpose of the output and what kind of value is expected. This description
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
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
from showing its value at the end of `terraform apply`. It may still be shown
in the CLI output for other reasons, such as if the value is referenced in
an expression for a resource argument.
from showing its value in the list of outputs at the end of `terraform apply`.
It might still be shown in the CLI output for other reasons, like if the
value is referenced in an expression for a resource argument.
Sensitive output values are still recorded in the
[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.
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
determines a set of dependencies, but in less-common cases there are
dependencies that cannot be recognized implicitly. In these rare cases, the

View File

@ -8,7 +8,7 @@ description: |-
# 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
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
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.
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
configurations must be evaluated in order to perform any resource type action,
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
configuration.
A small number of "meta-arguments" are defined by Terraform Core itself and
available for all `provider` blocks. These will be described in the following
sections.
There are also two "meta-arguments" that are defined by Terraform itself
and available for all `provider` blocks:
- [`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
be omitted if its contents would otherwise be empty. Terraform assumes an
@ -87,7 +89,9 @@ for installation instructions.
For more information, see
[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
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
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
to allow managing objects in multiple regions, on multiple hosts, etc. The
primary reason is multiple regions for a cloud platform. Other examples include
targeting multiple Docker hosts, multiple Consul hosts, etc.
[inpage-alias]: #alias-multiple-provider-instances
You can optionally define multiple configurations for the same provider, and
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
`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
configuration.
Resources are normally associated with the default provider configuration
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.
### Referring to Alternate Providers
The `provider` meta-argument within any `resource` or `data` block overrides
this default behavior and allows an additional provider configuration to be
selected using its alias:
When Terraform needs the name of a provider configuration, it always expects a
reference of the form `<PROVIDER NAME>.<ALIAS>`. In the example above,
`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
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
alias separated by a period, such as `aws.west` above.
To select aliased providers for a child module, use its `providers`
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
child module, as described in
[_Providers within Modules_](/docs/modules/usage.html#providers-within-modules).
In most cases, only _root modules_ should define provider configurations, with
all child modules obtaining their provider configurations from their parents.
```hcl
module "aws_vpc" {
source = "./aws_vpc"
providers = {
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
@ -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.
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:
```hcl

View File

@ -11,7 +11,7 @@ description: |-
# Resources
_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 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
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),
which is a plugin for Terraform that offers a collection of resource types that
most often belong to a single cloud or on-premises infrastructure platform.
Each resource type in turn belongs to a [provider](./providers.html),
which is a plugin for Terraform that offers a collection of resource types. A
provider usually provides resources to manage a single cloud or on-premises
infrastructure platform.
Most of the items within the body of a `resource` block are defined by and
specific to the selected resource type, and these arguments can make full
use of [expressions](/docs/configuration/expressions.html) and other dynamic
Terraform language features.
Most of the items within the body of a `resource` block are specific to the
selected resource type. These arguments can make full use of
[expressions](./expressions.html) and other dynamic Terraform
language features.
However, there are some "meta-arguments" that are defined by Terraform itself
and apply across all resource types. These arguments often have additional
restrictions on what language features can be used with them, and are described
in more detail in the following sections.
There are also some _meta-arguments_ that are defined by Terraform itself
and apply across all resource types. (See [Meta-Arguments](#meta-arguments) below.)
### Documentation for Resource Types
[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
@ -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
all.
The "meta-arguments" within `resource` blocks, defined in the following
sections, allow some details of this standard resource behavior to be
The meta-arguments within `resource` blocks, documented in the
sections below, allow some details of this standard resource behavior to be
customized on a per-resource basis.
## Resource Dependencies
### Resource Dependencies
As with other elements in the Terraform language, Terraform analyses any
[expressions](/docs/configuration/expressions.html) within a `resource`
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.
Most resources in a configuration don't have any particular relationship, and
Terraform can make changes to several unrelated resources in parallel.
However, in some less-common situations there are dependencies between
resources that cannot be recognized implicitly in configuration. For example,
if Terraform is being used to both manage access control policies _and_ take
actions that require those policies to be present, there may be a hidden
dependency between the access policy and a resource whose creation depends
on it.
However, some resources must be processed after other specific resources;
sometimes this is because of how the resource works, and sometimes the
resource's configuration just requires information generated by another
resource.
In these rare cases, the `depends_on` meta-argument can be used to explicitly
specify a dependency. This argument is available in all `resource` blocks,
regardless of resource type. For example:
Most resource dependencies are handled automatically. Terraform analyses any
[expressions](./expressions.html) within a `resource` block to find references
to other objects, and treats those references as implicit ordering requirements
when creating, updating, or destroying resources. Since most resources with
behavioral dependencies on other resources also refer to those resources' data,
it's usually not necessary to manually specify dependencies between resources.
However, some dependencies cannot be recognized implicitly in configuration. For
example, if Terraform must manage access control policies _and_ take actions
that require those policies to be present, there is a hidden dependency between
the access policy and a resource whose creation depends on it. In these rare
cases, [the `depends_on` meta-argument](#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
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
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
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
the resource block itself -- identified as `aws_instance.server` --
and the multiple _resource instances_ associated with it, identified
as `aws_instance.server[0]`, `aws_instance.server[1]`, etc. When `count`
is _not_ present, a resource block has only a single resource instance,
which has no associated index.
the resource block itself — identified as `aws_instance.server`
and the multiple _resource instances_ associated with it, identified as
`aws_instance.server[0]`, `aws_instance.server[1]`, etc. Each instance has a
distinct infrastructure object associated with it (as described above in
[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
is available for use in expressions, which has an attribute `count.index`
that provides the distinct index for each instance.
When `count` is _not_ present, a resource block has only a single resource
instance, which has no associated index.
The _Resource Behavior_ section above described how each resource corresponds
to a real infrastructure object. It is in fact resource _instances_ that
correspond to infrastructure objects, and so when `count` is used a particular
resource block has a distinct infrastructure object associated with each of its
instances, and each is separtely created, updated, or destroyed when the
configuration is applied.
Within resource blocks where `count` is set, an additional `count` object is
available for use in expressions so you can modify the configuration of each
instance. This object has one attribute, `count.index`, which provides the
distinct index number (starting with `0`) for each instance.
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.
However, Terraform must interpret the `count` argument _before_ any actions
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
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")
configurations for a single provider, to allow management of resources
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
are taken.
The `provider` meta-argument value must always be a literal provider name
followed by an alias name separated by a dot. Arbitrary expressions are
not permitted for `provider` because it must be resolved while Terraform
is constructing the dependency graph, before it is safe to evaluate
expressions.
The `provider` meta-argument expects [a `<PROVIDER>.<ALIAS>` reference](./providers.html#referring-to-alternate-providers), which
does not need to be quoted. Arbitrary expressions are not permitted for
`provider` because it must be resolved while Terraform is constructing the
dependency graph, before it is safe to evaluate expressions.
## Lifecycle Customizations
### `lifecycle`: Lifecycle Customizations
The general lifecycle for resources is described above in the section
_Resource Behavior_. Some details of that behavior can be customized
using the special nested block `lifecycle` within a resource block body:
[inpage-lifecycle]: #lifecycle-lifecycle-customizations
The general lifecycle for resources is described above in the
[Resource Behavior](#resource-behavior) section. Some details of that behavior
can be customized using the special nested `lifecycle` block within a resource
block body:
```
resource "azurerm_resource_group" "example" {
@ -316,18 +366,18 @@ meta-arguments are supported:
* `create_before_destroy` (bool) - By default, when Terraform must make a
change to a resource argument that cannot be updated in-place due to
remote API limitations Terraform will instead destroy the existing object
remote API limitations, Terraform will instead destroy the existing object
and then create a new replacement object with the new configured arguments.
The `create_before_destroy` meta-argument changes this behavior so that
the new, replacement object is created _first_, and then the prior object
the new replacement object is created _first,_ and then the prior object
is destroyed only once the replacement is created.
This is an opt-in behavior because many remote object types have unique
name requirements or other constraints that must be accommodated for
both a new and an old object to exist concurrently. Some resource types
offer special options to append a random suffix onto each object name to
avoid collisions, for example. Terraform Core cannot automatically activate
avoid collisions, for example. Terraform CLI cannot automatically activate
such features, so you must understand the constrants for each resource
type before using `create_before_destroy` with it.
@ -349,7 +399,7 @@ meta-arguments are supported:
with it, and so Terraform will allow the destroy operation to succeed.
* `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.
In some rare cases, settings of a remote object are modified by processes
@ -388,6 +438,33 @@ The `lifecycle` settings all effect how Terraform constructs and traverses
the dependency graph. As a result, only literal values can be used because
the processing happens 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
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
[generating private keys](/docs/providers/tls/r/private_key.html),
[issuing self-signed TLS certificates](/docs/providers/tls/r/self_signed_cert.html),
and even [generating random ids](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
managing "real" infrastructure objects, they can be useful as glue to help
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
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
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
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
property value is mapped to an expression as described under
[_Expression Mapping_](#expression-mapping) below. For arguments that
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.
* 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
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
within `resource` blocks expects a label giving the provisioner to use,
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
[inpage-block]: #block-type-specific-exceptions
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
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
spaces or symbols.
For example, the `provider` meta-argument takes a special compact provider
configuration reference, which appears directly in the native syntax but must
be presented as a string in the JSON syntax:
For example, the `provider` meta-argument takes a `<PROVIDER>.<ALIAS>` reference
to a provider configuration, which appears unquoted in the native syntax but
must be presented as a string in the JSON syntax:
```json
{
@ -330,8 +333,8 @@ be presented as a string in the JSON syntax:
This special processing applies to the following meta-arguments:
* `provider`: a single string, as shown above
* `depends_on`: an array of strings containing object references, like
`["aws_instance.example"]`.
* `depends_on`: an array of strings containing references to named entities,
like `["aws_instance.example"]`.
* `ignore_changes` within the `lifecycle` block: if set to `all`, a single
string `"all"` must be given. Otherwise, an array of JSON strings containing
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
a rich language designed to be easy for humans to read and write. The
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.
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
[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:
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
image_id = "abc123"
```
The identifier before the equals sign is the _attribute name_, and after
the equals sign is the attribute's value. The semantics applied to each
attribute name define what value types are valid, but many attributes
accept arbitrary [expressions](/docs/configuration/expressions.html),
which allow the value to either be specified literally or generated from
other values programmatically.
The identifier before the equals sign is the _argument name_, and the expression
after the equals sign is the argument's value.
The context where the argument appears determines what value types are valid
(for example, each resource type has a schema that defines the types of its
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:
@ -60,106 +76,41 @@ resource "aws_instance" "example" {
}
```
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
shown here expects two labels, which are "aws_instance" and "example"
in this case. A particular block type may have any number of required labels,
or it may require none as with the nested "network_interface" block type.
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
expects two labels, which are `aws_instance` and `example` in the example above.
A particular block type may have any number of required labels, or it may
require none as with the nested `network_interface` block type.
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
attributes.
arguments.
Unfortunately, the low-level syntax described here uses the noun "attribute"
to mean something slightly different to how it is used by the main
Terraform language. Elsewhere in this documentation, "attribute" usually
refers to a named value exported by an object that can be accessed in an
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.)
The Terraform language uses a limited number of _top-level block types,_ which
are blocks that can appear outside of any other block in a configuration file.
Most of Terraform's features (including resources, input variables, output
values, data sources, etc.) are implemented as top-level blocks.
## 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_.
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,
underscores, and hyphens. To avoid ambiguity with literal numbers, the
first character of an identifier must not be a digit.
Identifiers can contain letters, digits, underscores (`_`), and hyphens (`-`).
The first character of an identifier must not be a digit, to avoid ambiguity
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
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 `#`.
* `/*` and `*/` are start and end delimiters for a comment that might span
over multiple lines.

View File

@ -56,22 +56,22 @@ More information on backend configuration can be found in
## Specifying a Required Terraform Version
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
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
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
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,
which are released on a cycle independent to Terraform Core and to each other.
Use [provider version constraints](/docs/configuration/providers.html#provider-versions)
which are released on a cycle independent of Terraform CLI and of each other.
Use [provider version constraints](./providers.html#provider-versions)
to make similar constraints on which provider versions may be used.
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.
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
configuration to be provided by their caller but still need to impose a
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 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.
When you declare variables in the root module of your configuration, you can
set their values using CLI arguments and environment variables.
When you declare them in [_child_ modules](/docs/configuration/modules.html),
you can use the to pass values from parent to child.
set their values using CLI options and environment variables.
When you declare them in [child modules](./modules.html),
the calling module should pass values in the `module` block.
Input variable usage is introduced in the Getting Started guide section
[_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
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
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
value from within the module.
The name of a variable can be any valid identifier. However, due to the
interpretation of [module configuration blocks](/docs/configuration/modules.html),
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 name of a variable can be any valid [identifier](./syntax.html#identifiers)
_except_ the following:
The variable declaration may optionally include a `type` argument, which
describes what value types are accepted for the variable, as described
- `source`
- `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.
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
if no overridden value is set when calling the module. The `default` argument
requires a literal value and cannot reference other objects in the
if no value is set when calling the module or running Terraform. The `default`
argument requires a literal value and cannot reference other objects in the
configuration.
## Using Input Variable Values
Within the module that declared a variable, its value can be accessed from
within [expressions](/docs/configuration/expressions.html) using an expression
like `var.image_id`, where the name after the period corresponds to the label
given in the declaration block:
within [expressions](./expressions.html) as `var.<NAME>`,
where `<NAME>` matches the label given in the declaration block:
```hcl
resource "aws_instance" "example" {
@ -79,42 +91,44 @@ the module where it was declared.
## Type Constraints
The `type` argument in a `variable` block allows you to restrict the type of
value that will be accepted as the value for a variable. If no type constraint
is set then a value of any type is accepted.
The `type` argument in a `variable` block allows you to restrict the
[type of value](./expressions.html#types-and-values) that will be accepted as
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
serves as helpful additional documentation for users of the module and it
allows Terraform to return a helpful error message if the wrong type is used.
While type constraints are optional, we recommend specifying them; they
serve as easy reminders for users of the module, and
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
construction functions. The supported type keywords are:
constructors. The supported type keywords are:
* `string`
* `number`
* `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:
* `list(<type>)`
* `set(<type>)`
* `map(<type>)`
* `object({attr_name = <type>, ... })`
* `tuple([<type>, ...])`
* `list(<TYPE>)`
* `set(<TYPE>)`
* `map(<TYPE>)`
* `object({<ATTR NAME> = <TYPE>, ... })`
* `tuple([<TYPE>, ...])`
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,
see [the _Expressions_ section](/docs/configuration/expressions.html).
more information on the meaning and behavior of these different types, as well
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
valuable must be convertible to the specified type.
value must be convertible to the specified type.
## Input Variable Documentation
Because the input variables of a module are part of the user interface of
the module, you may specify a short description of the purpose of each
variable using the optional `description` argument:
Because the input variables of a module are part of its user interface, you can
briefly describe the purpose of each variable using the optional
`description` argument:
```hcl
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
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
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
can be set in a number of ways:
* Individual assignments made on the command line.
* Variable definitions files, either specified on the command line or
automatically loaded.
* Environment variables.
* [In a Terraform Enterprise workspace](/docs/enterprise/workspaces/variables.html).
* Individually, with the `-var` command line option.
* In variable definitions (`.tfvars`) files, either specified on the command line
or automatically loaded.
* As environment variables.
The following sections describe these options in more detail. This section does
not apply to _child_ modules, where values for input variables are instead
assigned in the configuration of their parent module, as described in
[_Modules_](/docs/configuration/modules.html).
[_Modules_](./modules.html).
### Variables on the Command Line
To specify individual modules on the command line, use the `-var` argument
that is accepted by the `terraform plan` and `terraform apply` commands:
To specify individual modules on the command line, use the `-var` option
when running the `terraform plan` and `terraform apply` commands:
```
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
a _variable definitions file_, with a filename ending in either `.tfvars`
or `.tfvars.json`, and then specify that filename on the command line:
a _variable definitions file_ (with a filename ending in either `.tfvars`
or `.tfvars.json`) and then specify that file on the command line with
`-var-file`:
```
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
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
automatically if they are present:
if they are present:
* 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
the root object properties corresponding to variable names:
@ -213,23 +234,23 @@ and lower case letters as in the above example.
### Complex-typed Values
When variable values are provided in a variable definitions file, the usual
syntax can be used to assign complex-typed values, like lists and maps.
When variable values are provided in a variable definitions file, Terraform's
[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
variables: to allow string values to be set conveniently, by default values
assigned in these ways are interpreted as literal strings, and thus do not
need to be themselves quoted:
variables. For convenience, Terraform defaults to interpreting `-var` and
environment variable values as literal strings, which do not need to be quoted:
```
$ export TF_VAR_image_id=ami-abc123
```
However, if a variable in the root module is declared as being of a complex
type (list, set, map, object, or tuple), Terraform will instead attempt to
parse it using the same syntax used within variable definitions files,
which requires cafeful attention to the string escaping rules in your
shell:
However, if a root module variable uses a [type constraint](#type-constraints)
to require a complex value (list, set, map, object, or tuple), Terraform will
instead attempt to parse its value using the same syntax used within variable
definitions files, which requires cafeful attention to the string escaping rules
in your shell:
```
$ 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
The above mechanisms for defining variable values can be used together in
any combination. If the same variable is assigned multiple values, the
processing order is as follows, with the later items in this list taking
precedence over the earlier:
The above mechanisms for setting variables can be used together in any
combination. If the same variable is assigned multiple values, Terraform uses
the _last_ value it finds, overriding any previous values.
* 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.json` file, if present.
* Any `-var` and `-var-file` arguments on the command line, in the order they
are provided.
* Any `*.auto.tfvars` or `*.auto.tfvars.json` files, processed in lexical order
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 %>
<ul class="nav docs-sidenav">
<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">
<li<%= sidebar_current("docs-config-resources") %>>
<a href="/docs/configuration/resources.html">Resources</a>
@ -51,6 +51,18 @@
<li<%= sidebar_current("docs-config-override") %>>
<a href="/docs/configuration/override.html">Override Files</a>
</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>
</li>
@ -238,36 +250,36 @@
<li<%= sidebar_current("docs-provisioners") %>>
<a href="/docs/provisioners/index.html">Provisioners</a>
<ul class="nav">
<li<%= sidebar_current("docs-provisioners-chef") %>>
<a href="/docs/provisioners/chef.html">chef</a>
<li<%= sidebar_current("docs-provisioners-connection") %>>
<a href="/docs/provisioners/connection.html">Provisioner Connections</a>
</li>
<li<%= sidebar_current("docs-provisioners-connection") %>>
<a href="/docs/provisioners/connection.html">connection</a>
<li<%= sidebar_current("docs-provisioners-chef") %>>
<a href="/docs/provisioners/chef.html">chef Provisioner</a>
</li>
<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<%= sidebar_current("docs-provisioners-habitat") %>>
<a href="/docs/provisioners/habitat.html">habitat</a>
<a href="/docs/provisioners/habitat.html">habitat Provisioner</a>
</li>
<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<%= 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<%= 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<%= 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>
</ul>
</li>

View File

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