From f8f2ff2202c8b0ad0d653e60802d0bf3a38c7cb5 Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Sat, 5 May 2018 19:37:47 -0700 Subject: [PATCH] website: Revise the "Input Variables" configuration docs section This adopts a more guide-like writing style, similar to what prior commits have done to the Resources and Providers sections. --- website/docs/configuration/variables.html.md | 403 +++++++------------ 1 file changed, 147 insertions(+), 256 deletions(-) diff --git a/website/docs/configuration/variables.html.md b/website/docs/configuration/variables.html.md index 6d130a6a60..3598360d24 100644 --- a/website/docs/configuration/variables.html.md +++ b/website/docs/configuration/variables.html.md @@ -7,338 +7,229 @@ description: |- This page covers configuration syntax for variables. --- -# Input Variable Configuration +# Input Variables -Input variables serve as parameters for a Terraform module. +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, +and allowing modules to be shared between different configurations. -When used in the root module of a configuration, variables can be set from CLI -arguments and environment variables. For [_child_ modules](/docs/configuration/modules.html), -they allow values to pass from parent to child. +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. Input variable usage is introduced in the Getting Started guide section [_Input Variables_](/intro/getting-started/variables.html). -This page assumes you're familiar with the -[configuration syntax](/docs/configuration/syntax.html) -already. +## Declaring an Input Variable -## Example - -Input variables can be defined as follows: +Each input variable accepted by a module must be declared using a `variable` +block: ```hcl -variable "key" { - type = "string" +variable "image_id" { + type = string } -variable "images" { - type = "map" - - default = { - us-east-1 = "image-1234" - us-west-2 = "image-4567" - } -} - -variable "zones" { - default = ["us-east-1a", "us-east-1b"] +variable "availability_zone_names" { + type = list(string) + default = ["us-west-1a"] } ``` -## Description - -The `variable` block configures a single input variable for a Terraform module. -Each block declares a single variable. - -The name given in the block header is used to assign a value to the variable -via the CLI and to reference the variable elsewhere in the configuration. - -Within the block body (between `{ }`) is configuration for the variable, -which accepts the following arguments: - -- `type` (Optional) - If set this defines the type of the variable. Valid values - are `string`, `list`, and `map`. If this field is omitted, the variable type - will be inferred based on `default`. If no `default` is provided, the type - is assumed to be `string`. - -- `default` (Optional) - This sets a default value for the variable. If no - default is provided, Terraform will raise an error if a value is not provided - by the caller. The default value can be of any of the supported data types, - as described below. If `type` is also set, the given value must be - of the specified type. +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. -- `description` (Optional) - A human-friendly description for the variable. This - is primarily for documentation for users using your Terraform configuration. - When a module is published in [Terraform Registry](https://registry.terraform.io/), - the given description is shown as part of the documentation. +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 +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` and `providers` are reserved for Terraform's own -use and are thus not recommended for any module intended to be used as a -child module. - -The default value of an input variable must be a _literal_ value, containing -no interpolation expressions. To assign a name to an expression so that it -may be re-used within a module, use [Local Values](/docs/configuration/locals.html) -instead. - -### Strings - -String values are simple and represent a basic key to value -mapping where the key is the variable name. An example is: - -```hcl -variable "key" { - type = "string" - default = "value" -} -``` - -A multi-line string value can be provided using heredoc syntax. +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. -```hcl -variable "long_key" { - type = "string" - default = <)` +* `set()` +* `map()` +* `object({attr_name = , ... })` +* `tuple([, ...])` -### Booleans +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). -Although Terraform can automatically convert between boolean and string -values, there are some subtle implications of these conversions that should -be completely understood when using boolean values with input variables. +If both the `type` and `default` arguments are specified, the given default +valuable must be convertible to the specified type. -It is recommended for now to specify boolean values for variables as the -strings `"true"` and `"false"`, to avoid some caveats in the conversion -process. A future version of Terraform will properly support boolean values -and so relying on the current behavior could result in -backwards-incompatibilities at that time. +## Input Variable Documentation -For a configuration such as the following: +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: ```hcl -variable "active" { - default = false +variable "image_id" { + type = string + description = "The id of the machine image (AMI) to use for the server." } ``` -The false is converted to a string `"0"` when running Terraform. +The description for a variable 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 written +from the perspective of the user of the module rather than its maintainer. For +commentary for module maintainers, use comments. -Then, depending on where you specify overrides, the behavior can differ: +## Assigning Values to Root Module Variables -- Variables with boolean values in a `tfvars` file will likewise be converted to - "0" and "1" values. +When variables are declared in the root module of your configuration, they +can be set in a number of ways: -- Variables specified via the `-var` command line flag will be literal strings - "true" and "false", so care should be taken to explicitly use "0" or "1". +* Individual assignments made on the command line. +* Variable definitions files, either specified on the command line or + automatically loaded. +* Environment variables. -- Variables specified with the `TF_VAR_` environment variables will be literal - string values, just like `-var`. +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). -A future version of Terraform will fully support first-class boolean -types which will make the behavior of booleans consistent as you would -expect. This may break some of the above behavior. +### Variables on the Command Line -When passing boolean-like variables as parameters to resource configurations -that expect boolean values, they are converted consistently: +To specify individual modules on the command line, use the `-var` argument +that is accepted by the `terraform plan` and `terraform apply` commands: -- "1" and "true" become `true` -- "0" and "false" become `false` - -The behavior of conversion in _this_ direction (string to boolean) will _not_ -change in future Terraform versions. Therefore, using these string values -rather than literal booleans is recommended when using input variables. - -## Environment Variables - -Environment variables can be used to set the value of an input variable in -the root module. The name of the environment variable must be -`TF_VAR_` followed by the variable name, and the value is the value of the -variable. - -For example, given the configuration below: - -```hcl -variable "image" {} ``` - -The variable can be set via an environment variable: - -```shell -$ TF_VAR_image=foo terraform apply +terraform apply -var="image_id=ami-abc123" ``` -Maps and lists can be specified using environment variables as well using -[HCL](/docs/configuration/syntax.html#HCL) syntax in the value. +### Variable Definitions Files -For a list variable like so: +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: -```hcl -variable "somelist" { - type = "list" -} ``` - -The variable could be set like so: - -```shell -$ TF_VAR_somelist='["ami-abc123", "ami-bcd234"]' terraform plan +terraform apply -var-file="testing.tfvars" ``` -Similarly, for a map declared like: +A variable definitions file uses the same basic syntax as Terraform language +files, but consists only of variable name assignments: ```hcl -variable "somemap" { - type = "map" -} -``` - -The value can be set like this: - -```shell -$ TF_VAR_somemap='{foo = "bar", baz = "qux"}' terraform plan +image_id = "ami-abc123" +availability_zone_names = [ + "us-east-1a", + "us-west-1c", +] ``` -## Variable Files +Terraform also automatically loads a number of variable definitions files +automatically if they are present: -Values for the input variables of a root module can be gathered in -_variable definition files_ and passed together using the `-var-file=FILE` -option. +* Files named exactly `terraform.tfvars` or `terraform.tfvars.json`. +* Any files with names ending in either `.auto.tfvars` or `.auto.tfvars.json`. -For all files which match `terraform.tfvars` or `*.auto.tfvars` present in the -current directory, Terraform automatically loads them to populate variables. If -the file is located somewhere else, you can pass the path to the file using the -`-var-file` flag. It is recommended to name such files with names ending in -`.tfvars`. +Files whose names end with `.json` are parsed instead as JSON objects, with +the root object properties corresponding to variable names: -Variables files use HCL or JSON syntax to define variable values. Strings, lists -or maps may be set in the same manner as the default value in a `variable` block -in Terraform configuration. For example: - -```hcl -foo = "bar" -xyz = "abc" - -somelist = [ - "one", - "two", -] - -somemap = { - foo = "bar" - bax = "qux" +```json +{ + "image_id": "ami-abc123", + "availability_zone_names": ["us-west-1a", "us-west-1c"] } ``` -The `-var-file` flag can be used multiple times per command invocation: - -```shell -$ terraform apply -var-file=foo.tfvars -var-file=bar.tfvars -``` +### Environment Variables --> **Note**: Variable files are evaluated in the order in which they are -specified on the command line. If a particular variable is defined in more than -one variable file, the last value specified is effective. +As a fallback for the other ways of defining variables, Terraform searches +the environment of its own process for environment variables named `TF_VAR_` +followed by the name of a declared variable. -### Variable Merging +This can be useful when running Terraform in automation, or when running a +sequence of Terraform commands in succession with the same variables. +For example, at a `bash` prompt on a Unix system: -When multiple values are provided for the same input variable, map values are -merged while all other values are overriden by the last definition. - -For example, if you define a variable twice on the command line: - -```shell -$ terraform apply -var foo=bar -var foo=baz -``` - -Then the value of `foo` will be `baz`, since it was the last definition seen. - -However, for maps, the values are merged: - -```shell -$ terraform apply -var 'foo={quux="bar"}' -var 'foo={bar="baz"}' ``` - -The resulting value of `foo` will be: - -```shell -{ - quux = "bar" - bar = "baz" -} +$ export TF_VAR_image_id=ami-abc123 +$ terraform plan +... ``` -There is no way currently to unset map values in Terraform. Whenever a map -is modified either via variable input or being passed into a module, the -values are always merged. +On operating systems where environment variable names are case-sensitive, +Terraform matches the variable name exactly as given in configuration, and +so the required environment variable name will usually have a mix of upper +and lower case letters as in the above example. -### Variable Precedence +### Complex-typed Values -Both these files have the variable `baz` defined: +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. -_foo.tfvars_ +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: -```hcl -baz = "foo" ``` - -_bar.tfvars_ - -```hcl -baz = "bar" +$ export TF_VAR_image_id=ami-abc123 ``` -When they are passed in the following order: +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: -```shell -$ terraform apply -var-file=foo.tfvars -var-file=bar.tfvars ``` +$ export TF_VAR_availability_zone_names='["us-west-1b","us-west-1d"]' +``` + +For readability, and to avoid the need to worry about shell escaping, we +recommend always setting complex variable values via varable definitions files. -The result will be that `baz` will contain the value `bar` because `bar.tfvars` -has the last definition loaded. +### Variable Definition Precedence -Definition files passed using the `-var-file` flag will always be evaluated after -those in the working directory. +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: -Values passed within definition files or with `-var` will take precedence over -`TF_VAR_` environment variables, as environment variables are considered defaults. +* 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.