2022-10-10

Terraform Variable

Terraform Variables

Terraform variables provide a flexible and dynamic approach to codify infrastructure. They offer a way to customize modules without altering the source code, making your modules reusable across different configurations. Variables can be declared in the root module, where they can be assigned values using CLI options and environment variables.

Declaring a Variable

A variable in Terraform is declared using a variable block. It requires a unique label, which serves as the variable's name. The label is used to assign a value from outside the module and to reference the value within the module.

Here's an example showcasing different types of variable declarations:

variable "account_id" {}

variable "instance_id" {
  type = string
}

variable "subnet_ids" {
  type    = list(string)
  default = ["subnet-0a4b1f2c3d4e5f6g"]
}

variable "security_group_settings" {
  type = list(object({
    rule       = number
    port_range = number
    protocol   = string
  }))
  default = [
    {
      rule       = 22
      port_range = 22
      protocol   = "tcp"
    }
  ]
}

Variable 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 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 be null within the module.

Default Values

A variable declaration can include a default argument, making the variable optional. If no value is set when calling the module or running Terraform, the default value is used. The default argument requires a literal value and cannot reference other configuration objects.

variable "instance_type" {
  type    = string
  default = "t2.micro"
}

Type Constraints

The type argument in a variable block restricts the type of value that the variable can accept. If no type constraint is set, a value of any type is accepted. Type constraints are not mandatory, but are recommended to provide clarity for users and to enable helpful error messages from Terraform.

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 anymay be used to indicate that any type is acceptable. If both the type and defaultarguments are specified, the default value must be convertible to the specified type.

Variable Documentation

To provide clarity to users of the module, the description argument can be used to explain the variable's purpose and expected value.

variable "image_id" {
  type        = string
  description = "The id of the machine image (AMI) to use for the server."
}

Custom Validation Rules

A validation block can be added within the variable block to specify custom validation rules for a variable.

Example of a validation rule for checking instance ID syntax:

variable "instance_id" {
  type        = string
  description = "The ID of the EC2 instance to manage."

  validation {
    condition     = length(var.instance_id) > 4 && substr(var.instance_id, 0, 4) == "i-"
    error_message = "The instance_id value must be a valid instance ID, starting with \"i-\"."
  }
}

Suppressing Values in CLI Output

The sensitive argument can be used to prevent Terraform from displaying a variable's value in the plan or apply output. This argument is useful when you want to hide potentially sensitive data from being displayed in the console.

variable "database_password" {
  type       = string
  sensitive  = true
}

Disallowing Null Input Values

The nullable argument can be used to specify whether the variable can accept null as its value. If nullable is set to false, the variable value can never be null within the module. The default value for nullable is true.

variable "subnet_id" {
  type     = string
  nullable = false
}

Using and Assigning Variable Values

Once declared, variable values can be accessed and manipulated in a variety of ways within your Terraform configuration.

Accessing Variable Values

In the module that declared a variable, you can use the var.<NAME> syntax to access the variable value within expressions. <NAME> should match the label provided in the declaration block. For example:

resource "aws_instance" "example" {
  instance_type = "t2.micro"
  ami           = var.ami_id
}

This access is restricted to the module in which the variable is declared.

Assigning Values to Root Module Variables

For variables declared in the root module of your configuration, values can be set through various methods:

  • Terraform Cloud workspace
  • Command line option -var
  • Variable definitions files (.tfvars)
  • Environment variables

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:

bash
$ 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"}'

Variable Definitions (.tfvars) Files

For setting many variables at once, you can specify their values in a variable definitions file (ending in .tfvars or .tfvars.json) and then specify that file on the command line with -var-file:

bash
$ 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:

terraform.tfvars
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:

terraform.tfvars.json
{
  "image_id": "ami-abc123",
  "availability_zone_names": ["us-west-1a", "us-west-1c"]
}

Environment Variables

Terraform allows you to set your variable values using environment variables. Each environment variable representing a Terraform variable must start with TF_VAR_ followed by the variable name:

bash
$ export TF_VAR_image_id=ami-abc123
$ terraform plan
...

This can be particularly useful when running Terraform in automated environments, or when needing to store sensitive information outside of your configuration.

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.

References

https://developer.hashicorp.com/terraform/language/values/variables

Ryusei Kakujo

researchgatelinkedingithub

Focusing on data science for mobility

Bench Press 100kg!