0% found this document useful (0 votes)
69 views

v1 - Variables I & O

The document discusses input variables in Terraform modules. Input variables allow customizing a module without changing its source code and allow modules to be shared between configurations. Variables are declared in a module and their values are set by the calling module. They serve as parameters for a module and can have default values, type constraints, and custom validation rules defined. Sensitive variables hide their values in CLI output but are still visible in state files.

Uploaded by

Venkateshwaran S
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
69 views

v1 - Variables I & O

The document discusses input variables in Terraform modules. Input variables allow customizing a module without changing its source code and allow modules to be shared between configurations. Variables are declared in a module and their values are set by the calling module. They serve as parameters for a module and can have default values, type constraints, and custom validation rules defined. Sensitive variables hide their values in CLI output but are still visible in state files.

Uploaded by

Venkateshwaran S
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

www.terraform.

io
/docs/language/values/variables.html

Input Variables - Configuration Language -


Terraform by HashiCorp
15-19 minutes

Hands-on: Try the Customize Terraform Configuration with Variables tutorial


on HashiCorp Learn.

Input variables serve as parameters for a Terraform module, allowing aspects


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 options and environment variables.
When you declare them in child
modules,
the calling module should pass values in the module block.

If you're familiar with traditional programming languages, it can be useful to


compare
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.

»
Declaring an Input Variable
Each input variable accepted by a module must be declared using a variable
block:

variable "image_id" {
Just SKIM
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 the variable keyword is a name for the variable, which must
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


except the following: source, version,
providers, count, for_each, lifecycle, depends_on, locals.

These names are reserved for meta-arguments in


module configuration blocks, and
cannot be
declared 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.

»
Default values

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 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.

»
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.

While type constraints are optional, we recommend specifying them; they


can serve as
helpful reminders for users of the module, and they
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
constructors. The
supported type keywords are:

string
number
bool

The type constructors allow you to specify complex types such as


collections:

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, as well
as detailed
information about automatic conversion of complex types, see
Type Constraints.

If both the type and default arguments are specified, the given default
value must be
convertible to the specified type.

»
Input Variable Documentation

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:

variable "image_id" {

type = string

description = "The id of the machine image (AMI) to use for the


server."

The description should concisely explain the purpose


of the variable 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.

»
Custom Validation Rules

In addition to Type Constraints as described above, a module author can specify


arbitrary
custom validation rules for a particular variable using a validation
block nested within
the corresponding variable block:

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-\"."

The condition argument is an expression that must use the value of the
variable to
return true if the value is valid, or false if it is invalid.
The expression can refer only to
the variable that the condition applies to,
and must not produce errors.

If the failure of an expression is the basis of the validation decision, use


the can function
to detect such errors. For example:

variable "image_id" {

type = string

description = "The id of the machine image (AMI) to use for the


server."

validation {

# regex(...) fails if it cannot find a match

condition = can(regex("^ami-", var.image_id))

error_message = "The image_id value must be a valid AMI id,


starting with \"ami-\"."

If condition evaluates to false, Terraform will produce an error message


that includes
the sentences given in error_message. The error message string
should be at least one
full sentence explaining the constraint that failed,
using a sentence structure similar to the
above examples.

»
Suppressing Values in CLI Output

Hands-on: Try the Protect Sensitive Input Variables tutorial on HashiCorp


Learn.

Setting a variable as sensitive prevents Terraform from showing its value in


the plan or
apply output, when you use that variable elsewhere in your
configuration.

Terraform will still record sensitive values in the state,


and so anyone who can access the
state data will have access to the sensitive
values in cleartext. For more information, see
Sensitive Data in State.

Declare a variable as sensitive by setting the sensitive argument to true:

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 treated
as
sensitive themselves, and so in the above example the two arguments of
resource
"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)

+ address = (sensitive)

Plan: 1 to add, 0 to change, 0 to destroy.

In some cases where you use a sensitive variable inside a nested block, Terraform
may
treat the entire block as redacted. This happens for resource types where
all of the blocks
of a particular type are required to be unique, and so
disclosing 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 also


declare an attribute as sensitive,
which will cause Terraform to hide it
from regular output regardless of how
you assign it a value. For more information, see
Sensitive Resource Attributes.

If you use a sensitive value from as part of an


output value then Terraform will require
you
to also mark the output value itself as sensitive, to confirm that you
intended to export it.

»
Cases where Terraform may disclose a sensitive variable

A sensitive 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, an apply will
disclose the value. In the example below, the prefix 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)

+ 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]

»
Using Input Variable Values
Within the module that declared a variable, its value can be accessed from
within
expressions as var.<NAME>,
where <NAME> matches the label given in the declaration
block:

resource "aws_instance" "example" {

instance_type = "t2.micro"

ami = var.image_id

The value assigned to a variable can only be accessed in expressions within


the module
where it was declared.

»
Assigning Values to Root Module Variables
When variables are declared in the root module of your configuration, they
can be set in a
number of ways:

In a Terraform Cloud workspace.


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.
»
Variables on the Command Line

To specify individual variables on the command line, use the -var option
when running the
terraform plan and terraform 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 on
Linux or
macOS. For more information on shell quoting, including additional
examples for Windows
Command Prompt, see
Input Variables on the Command Line.

You can use the -var option multiple times in a single command to set several
different
variables.

»
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 file
on the command line with
-var-file:

terraform apply -var-file="testing.tfvars"

A variable definitions file uses the same basic syntax as Terraform language
files, 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 files


if they are present:

Files named exactly terraform.tfvars or terraform.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:

"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 searches
the environment
of its own process for environment variables named TF_VAR_
followed by the name of a
declared variable.

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:

$ 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, and
so the required
environment variable name will usually have a mix of upper
and lower case letters as in
the above example.

»
Complex-typed Values

When variable values are provided in a variable definitions file, you can use
Terraform's
usual syntax for
literal expressions
to assign complex-typed values, like lists and maps.

Some special rules apply to the -var command line option and to environment
variables.
For convenience, Terraform defaults to interpreting -var and
environment 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 a type constraint


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 careful attention to the string
escaping rules
in 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, we
recommend
always setting complex variable values via variable definitions files.
For more information
on quoting and escaping for -var arguments,
see
Input Variables on the Command Line.

»
Values for Undeclared Variables

If you have defined a variable value, but not its corresponding variable {}
definition,
you may get an error or warning depending on how you have provided
that value.

If you provide values for undeclared variables defined as environment variables


you will
not get an error or warning. This is because environment variables may
be declared but
not used in all configurations that might be run.
If you provide values for undeclared variables defined in a file
you will get a warning. This
is to help in cases where you have provided a variable
value meant for a variable
declaration, but perhaps there is a mistake in the
value definition. For example, the
following configuration:

variable "moose" {

type = string

And the following .tfvars file:

Will cause Terraform to warn you that there is no variable declared "mosse", which can
help
you spot this mistake.

If you use .tfvars files across multiple configurations and expect to continue to see this
warning,
you can use the -compact-warnings
option to simplify your output.

If you provide values for undeclared variables on the command line,


Terraform will error.
To avoid this error, either declare a variable block for the value, or remove
the variable
value from your Terraform call.

»
Variable Definition Precedence

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. Note that the same
variable cannot be assigned multiple
values within a single source.

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 *.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 Cloud
workspace.)
www.terraform.io
/docs/language/values/outputs.html

Output Values - Configuration Language - Terraform


by HashiCorp
5-7 minutes

Hands-on: Try the Output Data From


Terraform
tutorial on HashiCorp Learn.

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, root module outputs can be
accessed by other
configurations via a
terraform_remote_state data source.

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.

»
Declaring an Output Value
Each output value exported by a module must be declared using an output
block:

output "instance_ip_addr" {

value = aws_instance.server.private_ip

The label immediately after the output keyword is the name, which must be a
valid
identifier. In a root module, this name is
displayed to the user; in a child module, it can be
used to access the output's
value.

The value argument takes an expression


whose result is to be returned to the user. In this
example, the expression
refers to the private_ip attribute exposed by an aws_instance
resource
defined elsewhere in this module (not shown). Any valid expression is allowed
as
an output value.

»
Accessing Child Module Outputs
In a parent module, outputs of child modules are available in expressions as
module.
<MODULE NAME>.<OUTPUT NAME>. For example, if a child module named
web_server
declared an output named instance_ip_addr, you could access that
value as
module.web_server.instance_ip_addr.
»
Optional Arguments
output blocks can optionally include description, sensitive, and depends_on
arguments, which are described in the following sections.

»
description — Output Value Documentation

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:

output "instance_ip_addr" {

value = aws_instance.server.private_ip

description = "The private IP address of the main server instance."

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.

»
sensitive — Suppressing Values in CLI Output

An output can be marked as containing sensitive material using the optional


sensitive
argument:

output "db_password" {

value = aws_db_instance.db.password

description = "The password for logging in to the database."

sensitive = true

Terraform will hide values marked as sensitive in the messages from


terraform plan
and terraform apply. In the following scenario, our root
module has an output declared
as sensitive and a module call with a
sensitive output, which we then use in a resource
attribute.

# main.tf

module "foo" {

source = "./mod"

resource "test_instance" "x" {

some_attribute = module.mod.a # resource attribute references a


sensitive output

output "out" {

value = "xyz"

sensitive = true

# mod/main.tf, our module containing a sensitive output

output "a" {

value = "secret"

sensitive = true

When we run a plan or apply, the sensitive value is redacted from output:

Terraform will perform the following actions:

# test_instance.x will be created

+ resource "test_instance" "x" {

+ some_attribute = (sensitive)

Plan: 1 to add, 0 to change, 0 to destroy.

Changes to Outputs:

+ out = (sensitive value)

Terraform will still record sensitive values in the state,


and so anyone who can access the
state data will have access to the sensitive
values in cleartext. For more information, see
Sensitive Data in State.

»
depends_on — Explicit Output Dependencies

Since output values are just a means for passing data out of a module, it is
usually not
necessary to worry about their relationships with other nodes in
the dependency graph.

However, when a parent module accesses an output value exported by one of its
child
modules, the dependencies of that output value allow Terraform to
correctly determine the
dependencies between resources defined in different
modules.

Just as with
resource dependencies,
Terraform analyzes the value expression for an
output value and automatically
determines a set of dependencies, but in less-common
cases there are
dependencies that cannot be recognized implicitly. In these rare cases,
the
depends_on argument can be used to create additional explicit dependencies:

output "instance_ip_addr" {

value = aws_instance.server.private_ip

description = "The private IP address of the main server instance."

depends_on = [

# Security group rule must be created before this IP address could

# actually be used, otherwise the services will be unreachable.

aws_security_group_rule.local_access,

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.

You might also like