Input Variables
Hands-on: Try theCustomize Terraform Configuration with Variables tutorial.
Input variables let you customize aspects of Terraform modules without alteringthe module's own source code. This functionality allows you to share modules across differentTerraform configurations, making your module composable and reusable.
When you declare variables in the root module of your configuration, you canset their values using CLI options and environment variables.When you declare them inchild modules,the calling module should pass values in themodule block.
If you're familiar with traditional programming languages, it can be useful tocompare Terraform modules to function definitions:
- Input variables are like function arguments.
- Output values are like function return values.
- Local values are like a function's temporary local variables.
Note: For brevity, input variables are often referred to as just"variables" or "Terraform variables" when it is clear from context what sort ofvariable is being discussed. Other kinds of variables in Terraform includeenvironment variables (set by the shell where Terraform runs) andexpressionvariables (used to indirectly represent a value in anexpression).
Declaring an Input Variable
Each input variable accepted by a module must be declared using avariableblock:
variable "image_id" { type= string}variable "availability_zone_names" { type= list(string) default= ["us-west-1a"]}variable "docker_ports" { type= list(object({ internal= number external= number protocol= string })) default= [ { internal= 8300 external= 8300 protocol= "tcp" } ]}The label after thevariable keyword is a name for the variable, which mustbe unique among all variables in the same module. This name is used toassign a value to the variable from outside and to reference the variable'svalue from within the module.
The name of a variable can be any valididentifierexcept the following:source,version,providers,count,for_each,lifecycle,depends_on,locals.
These names are reserved for meta-arguments inmodule configuration blocks, and cannot bedeclared as variable names.
Arguments
Terraform CLI defines the following optional arguments for variable declarations:
default- A default value which then makes the variable optional.type- This argument specifies what value types are accepted for the variable.description- This specifies the input variable's documentation.validation- A block to define validation rules, usually in addition to type constraints.sensitive- Limits Terraform UI output when the variable is used in configuration.nullable- Specify if the variable can benullwithin the module.
Default values
The variable declaration can also include adefault argument. If present,the variable is considered to beoptional and the default value will be usedif no value is set when calling the module or running Terraform. Thedefaultargument requires a literal value and cannot reference other objects in theconfiguration.
Type Constraints
Thetype argument in avariable block allows you to restrict thetype of value that will be accepted asthe value for a variable. If no type constraint is set then a value of any typeis accepted.
While type constraints are optional, we recommend specifying them; theycan serve as helpful reminders for users of the module, and theyallow Terraform to return a helpful error message if the wrong type is used.
Type constraints are created from a mixture of type keywords and typeconstructors. The supported type keywords are:
The type constructors allow you to specify complex types such ascollections:
The keywordany may be used to indicate that any type is acceptable. Formore information on the meaning and behavior of these different types, as wellas detailed information about automatic conversion of complex types, seeType Constraints.
If both thetype anddefault arguments are specified, the given defaultvalue must be convertible to the specified type.
Input Variable Documentation
Because the input variables of a module are part of its user interface, you canbriefly describe the purpose of each variable using the optionaldescription argument:
variable "image_id" { type= string description= "The id of the machine image (AMI) to use for the server."}The description should concisely explain the purposeof the variable and what kind of value is expected. This description stringmight be included in documentation about the module, and so it should be writtenfrom the perspective of the user of the module rather than its maintainer. Forcommentary for module maintainers, use comments.
Custom Validation Rules
This feature was introduced in Terraform CLI v0.13.0.
You can specify custom validation rules for a particular variable by adding avalidation block within the correspondingvariable block. The example below checks whether the AMI ID has the correct syntax.
variable "image_id" { type= string description= "The id of the machine image (AMI) to use for the server." validation { condition= length(var.image_id) > 4 && substr(var.image_id, 0, 4) == "ami-" error_message= "The image_id value must be a valid AMI id, starting with \"ami-\"." }}Refer toCustom Condition Checks for more details.
Suppressing Values in CLI Output
This feature was introduced in Terraform v0.14.0.
Hands-on: Try theProtect Sensitive Input Variables tutorial.
Setting a variable assensitive prevents Terraform from showing its value intheplan orapply output, when you use that variable elsewhere in yourconfiguration.
Terraform will still record sensitive values in thestate,and so anyone who can access the state data will have access to the sensitivevalues in cleartext. For more information, seeSensitive Data in State.
Declare a variable as sensitive by setting thesensitive argument totrue:
variable "user_information" { type= object({ name= string address= string }) sensitive= true}resource "some_resource" "a" { name= var.user_information.name address= var.user_information.address}Any expressions whose result depends on the sensitive variable will be treatedas sensitive themselves, and so in the above example the two arguments ofresource "some_resource" "a" will also be hidden in the plan output:
Terraform will perform the following actions: # some_resource.a will be created + resource "some_resource" "a" { + name = (sensitive value) + address = (sensitive value) } Plan: 1 to add, 0 to change, 0 to destroy.In some cases where you use a sensitive variable inside a nested block, Terraformmay treat the entire block as redacted. This happens for resource types whereall of the blocks of a particular type are required to be unique, and sodisclosing the content of one block might imply the content of a sibling block.
# some_resource.a will be updated in-place ~ resource "some_resource" "a" { ~ nested_block { # At least one attribute in this block is (or was) sensitive, # so its contents will not be displayed. } }A provider can alsodeclare an attribute as sensitive,which will cause Terraform to hide it from regular output regardless of howyou assign it a value. For more information, seeSensitive Resource Attributes.
If you use a sensitive value as part of anoutput value then Terraform will requireyou to also mark the output value itself as sensitive, to confirm that youintended to export it.
Cases where Terraform may disclose a sensitive variable
Asensitive variable is a configuration-centered concept, and values are sent to providers without any obfuscation. A provider error could disclose a value if that value is included in the error message. For example, a provider might return the following error even if "foo" is a sensitive value:"Invalid value 'foo' for field"
If a resource attribute is used as, or part of, the provider-defined resource id, anapply will disclose the value. In the example below, theprefix attribute has been set to a sensitive variable, but then that value ("jae") is later disclosed as part of the resource id:
# random_pet.animal will be created + resource "random_pet" "animal" { + id = (known after apply) + length = 2 + prefix = (sensitive value) + separator = "-" } Plan: 1 to add, 0 to change, 0 to destroy. ... random_pet.animal: Creating...random_pet.animal: Creation complete after 0s [id=jae-known-mongoose]Disallowing Null Input Values
This feature is available in Terraform v1.1.0 and later.
Thenullable argument in a variable block controls whether the module callermay assign the valuenull to the variable.
variable "example" { type= string nullable= false}The default value fornullable istrue. Whennullable istrue,nullis a valid value for the variable, and the module configuration must alwaysaccount for the possibility of the variable value beingnull. Passing anull value as a module input argument will override anydefault value.
Settingnullable tofalse ensures that the variable value will never benull within the module. Ifnullable isfalse and the variable has adefault value, then Terraform uses the default when a module input argument isnull.
Thenullable argument only controls where the direct value of the variable may benull.For variables of collection or structural types, such as lists or objects,the caller may still usenull in nested elements or attributes, as long asthe collection or structure itself is not null.
Using Input Variable Values
Within the module that declared a variable, its value can be accessed fromwithinexpressions asvar.<NAME>,where<NAME> matches the label given in the declaration block:
Note: Input variables arecreated by avariable block, but youreference them as attributes on an object namedvar.
resource "aws_instance" "example" { instance_type= "t2.micro" ami= var.image_id}The value assigned to a variable can only be accessed in expressions withinthe module where it was declared.
Assigning Values to Root Module Variables
When variables are declared in the root module of your configuration, theycan be set in a number of ways:
- In a Terraform Cloud workspace.
- Individually, with the
-varcommand line option. - In variable definitions (
.tfvars) files, either specified on the command lineor automatically loaded. - As environment variables.
The following sections describe these options in more detail. This section doesnot apply tochild modules, where values for input variables are insteadassigned in the configuration of their parent module, as described inModules.
Variables on the Command Line
To specify individual variables on the command line, use the-var optionwhen running theterraform plan andterraform apply commands:
terraform apply -var="image_id=ami-abc123"terraform apply -var='image_id_list=["ami-abc123","ami-def456"]' -var="instance_type=t2.micro"terraform apply -var='image_id_map={"us-east-1":"ami-abc123","us-east-2":"ami-def456"}'The above examples show appropriate syntax for Unix-style shells, such as onLinux or macOS. For more information on shell quoting, including additionalexamples for Windows Command Prompt, seeInput Variables on the Command Line.
You can use the-var option multiple times in a single command to set severaldifferent variables.
Variable Definitions (.tfvars) Files
To set lots of variables, it is more convenient to specify their values inavariable definitions file (with a filename ending in either.tfvarsor.tfvars.json) and then specify that file on the command line with-var-file:
Linux, Mac OS, and UNIX:
terraform apply -var-file="testing.tfvars"PowerShell:
terraform apply -var-file='testing.tfvars'Windowscmd.exe:
terraform apply -var-file="testing.tfvars"Note: This is how Terraform Cloud passesworkspace variables to Terraform.
A variable definitions file uses the same basic syntax as Terraform languagefiles, but consists only of variable name assignments:
image_id= "ami-abc123"availability_zone_names= [ "us-east-1a", "us-west-1c",]Terraform also automatically loads a number of variable definitions filesif they are present:
- Files named exactly
terraform.tfvarsorterraform.tfvars.json. - Any files with names ending in
.auto.tfvarsor.auto.tfvars.json.
Files whose names end with.json are parsed instead as JSON objects, withthe root object properties corresponding to variable names:
{ "image_id": "ami-abc123", "availability_zone_names": ["us-west-1a", "us-west-1c"]}Environment Variables
As a fallback for the other ways of defining variables, Terraform searchesthe environment of its own process for environment variables namedTF_VAR_followed by the name of a declared variable.
This can be useful when running Terraform in automation, or when running asequence of Terraform commands in succession with the same variables.For example, at abash prompt on a Unix system:
$ export TF_VAR_image_id=ami-abc123$ terraform plan...On operating systems where environment variable names are case-sensitive,Terraform matches the variable name exactly as given in configuration, andso the required environment variable name will usually have a mix of upperand lower case letters as in the above example.
Complex-typed Values
When variable values are provided in a variable definitions file, you can useTerraform's usual syntax forliteral expressionsto assign complex-typed values, like lists and maps.
Some special rules apply to the-var command line option and to environmentvariables. For convenience, Terraform defaults to interpreting-var andenvironment variable values as literal strings, which need only shell quoting,and no special quoting for Terraform. For example, in a Unix-style shell:
$ export TF_VAR_image_id='ami-abc123'However, if a root module variable uses atype constraintto require a complex value (list, set, map, object, or tuple), Terraform willinstead attempt to parse its value using the same syntax used within variabledefinitions files, which requires careful attention to the string escaping rulesin your shell:
$ export TF_VAR_availability_zone_names='["us-west-1b","us-west-1d"]'For readability, and to avoid the need to worry about shell escaping, werecommend always setting complex variable values via variable definitions files.For more information on quoting and escaping for-var arguments,seeInput Variables on the Command Line.
Values for Undeclared Variables
If you have defined a variable value, but not its correspondingvariable {}definition, you may get an error or warning depending on how you have providedthat value.
If you provide values for undeclared variables defined asenvironment variablesyou will not get an error or warning. This is because environment variables maybe declared but not used in all configurations that might be run.
If you provide values for undeclared variables definedin a fileyou will get a warning. This is to help in cases where you have provided a variablevaluemeant for a variable declaration, but perhaps there is a mistake in thevalue definition. For example, the following configuration:
variable "moose" { type= string}And the following.tfvars file:
mosse= "Moose"Will cause Terraform to warn you that there is no variable declared"mosse", which can helpyou spot this mistake.
If you use.tfvars files across multiple configurations and expect to continue to see this warning,you can use the-compact-warningsoption to simplify your output.
If you provide values for undeclared variables on thecommand line,Terraform will return an error. To avoid this error, either declare a variable block for the value, or removethe variable value from your Terraform call.
Variable Definition Precedence
The above mechanisms for setting variables can be used together in anycombination. If the same variable is assigned multiple values, Terraform usesthelast value it finds, overriding any previous values. Note that the samevariable cannot be assigned multiple values within a single source.
Terraform loads variables in the following order, with later sources takingprecedence over earlier ones:
- Environment variables
- The
terraform.tfvarsfile, if present. - The
terraform.tfvars.jsonfile, if present. - Any
*.auto.tfvarsor*.auto.tfvars.jsonfiles, processed in lexical orderof their filenames. - Any
-varand-var-fileoptions on the command line, in the order theyare provided. (This includes variables set by a Terraform Cloudworkspace.)
Important: In Terraform 0.12 and later, variables with map and objectvalues behave the same way as other variables: the last value found overridesthe previous values. This is a change from previous versions of Terraform, whichwouldmerge map values instead of overriding them.
Variable precedence within Terraform tests
Within Terraform test files, you can specify variable values withinvariables blocks, either nested withinrun blocks or defined directly withinthe file.
Variables defined in this way take precedence over all other mechanisms duringtest execution, with variables defined withinrun blocks taking precedenceover those defined within the file.