No results found

Your search did not match any results.

We suggest you try the following to help find what you're looking for:

  • Check the spelling of your keyword search.
  • Use synonyms for the keyword you typed, for example, try "application" instead of "software."
  • Try one of the popular searches shown below.
  • Start a new search.
Trending Questions
 

Terraform Variables

This lesson will take a deeper look at Terraform variabales.

Author: Tim Clegg

Updated:

1 Introduction

Terraform 101 Tutorial Series
Terraform 101

This lesson will take a deeper look at Terraform variabales. You’ve already had a little bit of exposure to them in the Experiencing Terraform tutorial, as well as a brief summary in the Understanding Terraform Concepts tutorial. Let’s dive in and take a deeper look at what these are and how they’re used.

2 Why use variables?

Variables provide a way to easily decouple a value and its reference from your Terraform code. A topology may be defined, but the specifics are given programmatically (or manually). Writing parameterized Terraform code (using variables for many of the customizable values), means that as an environment changes new values for the variables may be provided without requiring any modification to the underlying Terraform code.

Here are some common use-cases for parameterizing code:

  • Multiple deployments of the same topology. This could be for deploying separate development, staging and production environments that share identical topologies (but have unique names, compartments, CIDR blocks, etc.).
  • Passing secret/sensitive data in via variables. Rather than hard-coding credentials, keys and other sensitive data in the Terraform code, this can be passed via variables.
  • Writing extensible modules in Terraform, where variables are used as inputs to the module, determining its behavior and/or setting resource attributes.

Warning: NEVER commit secrets, credentials, keys and any other sensitive data to a git repo!

3 Types of variables

There are two kinds of variables:

  • Input variables (variables)
  • Local values (locals)

Input variables (variables)

Most Terraform projects use variables in one way or another. Variables are very common, and for good reason. Variables are accessible within the entire project (or module, if you’re building projects made of one or more modules).

Local values (locals)

There’s another kind of variable called a local variable (aka locals) which is not accessible to your entire project, but is limited to the context of a single Terraform file. This means that if you define a local variable in a particular Terraform file, it will only be available to code within that same file (but not to code in other Terraform files).

4 Getting the contents of a variable

To use a variable, prepend var. at the beginning of the variable name. Take for example the var.tenancy_ocid used in the following VCN resource block:

resource oci_core_vcn tf_101 {
                      cidr_block     = "192.168.1.0/24"
                      compartment_id = var.tenancy_ocid
                      display_name   = "tf-101"
                      dns_label      = "tf101"
                    }
                    

If this looks familiar, it should - it’s borrowed from the Experiencing Terraform tutorial! This is how the tenancy_ocid variable is referenced (read and used).

Getting the contents of a local

To use a local (variable), simply prepend the local variable name with local. Here’s an example:

resource oci_core_vcn tf_101 {
                      cidr_block     = local.cidr
                      compartment_id = var.tenancy_ocid
                      display_name   = "tf-101"
                      dns_label      = "tf101"
                    }
                    

The above example is setting the cidr_block attribute to whatever is in the cidr local.

5 Setting variable values

There are multiple ways to set the values of a variable. Terraform uses the following order of precedence when setting the value of a variable (listed from the highest to lowest priority):

  1. CLI arguments (-var and -var-file CLI parameters)
  2. *.auto.tfvars
  3. terraform.tfvars
  4. Environment variables

Setting local values (locals)

Local values are a little different than regular variables (which we’ll be looking at in the rest of this section). Locals (aka local values) are set in the Terraform code itself. A benefit of locals is — because they’re set within the Terraform code — they can be computed programmatically, granting the ability to use Terraform functions, reference to other variables, locals, and resources.

Here’s an example of how locals are defined.

locals {
                      comp_id = len(var.compartment_id) > 0 ? var.compartment_id : "abcd.1234"
                    }
                    

The above example is just fictitious (and not even the most efficient method of doing this), but gives you an idea about how you’d set the comp_id local (variable). Locals are defined within a plural locals block, but when referenced, are singular (local.comp_id).

Via the command-line interface

Terraform supports many command-line parameters, one of which is the -var parameter which allows you to set the value of a variable when you run Terraform. Here’s an example of how you might set the compartment_id variable using the command-line.

$ terraform plan -var 'compartment_id=abcd.1234'
                    

Or alternatively, you can use the following formatting.

$ terraform plan -var="compartment_id=abcd.1234"
                    

You can set one or more variables using this technique. This is one way to set variables, but it’s a bit tedious because it can result in a really long command when running Terraform (if there are a lot of variables being set). This would need to be used every time you want to run Terraform!

Variable files

Files ending in .tfvars can be used to set the value of variables. You can tell Terraform which files to read at run-time with the -var-file parameter or you can let it auto-load files (based on their filename).

If the terraform.tfvars file exists in the working directory, Terraform will read it and set the variable values that are given there. Here’s a sample terraform.tfvars file:

compartment_id   = "<your_compartment_OCID_here>"
                    region           = "us-phoenix-1"
                    cidr             = "172.16.0.0/20"
                    

These are setting variable values (note that there’s no var. prefix used). Terraform implicitly uses the terraform.tfvars file for setting variable values.

The terraform.tfvars file is statically read, meaning that there’s no computation that takes place. Terraform does not reference other variables, resources or other Terraform functions. It reads only static values.

The terraform.tfvars file can often be used for setting environment-specific settings. It is usually not committed to git repos (at least alongside the Terraform code), as its values might determine the characteristics for the environment.

*.auto.tfvars

You can specify as many files as you’d like that end in .auto.tfvars and Terraform will gladly read these and set variable values accordingly. This allows you to set different variable definitions between different files. For instance, it might make sense to set the variable definitions as-follows (this is just an example, by no means the only way).

  • network.auto.tfvars
  • storage.auto.tfvars
  • compute.auto.tfvars

Grouping variable assignments like this allows a person to better navigate between variables, especially if there’s a large number of variables.

Via environment variables

Terraform is smart enough to look at the environment variables at run-time. If there are any that begin with TF_VAR_ (the full environment variable would be: TF_VAR_<variable_name>), Terraform will assign the value to the given variable.

Here’s an example of how to set the compartment_id variable on a MacOS/Linux system.

export TF_VAR_compartment_id=<your_compartment_OCID_here>
                    

This same environment variable might be set as follows on Windows:

setx TF_VAR_compartment_id <your_compartment_OCID_here>
                    

Via user-interactive prompts

If a variable is not given a value, Terraform will resort to asking the user to provide it at run-time. Terraform cannot proceed without knowing what value to use.

This is annoying and can be tedious (especially if there are lots of undefined variables), however there are times when this might make perfect sense and be a desirable behavior. In situations where the user should be asked for a value (such as for a confirmation prompt), this can be a good solution.

6 Defining variables

To define the existence of a variable, simply provide the following anywhere in the Terraform code:

variable "compartment_id" {}
                    

It’s common practice to place variable definitions in a single file: variables.tf. This allows for easier management of variable definitions (having them in one place).

Besides the name of the variable, there are several different attributes you can set for a variable, including (but not limited to):

  • type (some of the common types will be discussed shortly)
  • description (it’s nice to let people know how this variable is used)
  • default
  • sensitive

Default values

The default attribute is important to know about, as its behavior is multi-purpose. Notice how there’s no required attribute? If a variable does not have a default value, Terraform will require the variable value to be set. This means that default not only allows you to provide a default, but it can also make a variable “optional” (sort of). This is really just a side effect of providing a value. Every variable defined must have a value. Giving a default value (even if empty, such as a value of "" or null) keeps Terraform from “bugging” the operator, which gives the impression that it’s not required. It’s a matter of how you look at it.

Some variables might best be left blank (so it’s very obvious if the user running Terraform doesn’t set it to a specific value). Often times it’s nice to have “sane defaults” set so that a reasonable default value is used on a variable, minimizing the amount of inputs that must be provided. When a variable is given a default value, the default value is used unless it is overridden (with a value explicitly set).

To define a default value, add the default attribute to the variable definition.

variable "compartment_id" {
                      default = "abcd.1234"
                    }
                    

In the above example, unless a value is explicitly provided, the default value of “abcd.1234” will be used for the the compartment_id variable.

Sensitive variables

If you set the sensitive attribute of a variable to true, Terraform tries to minimize displaying the value to the user. This is not a guarantee that it’s not accessible to the user or that it won’t be shown on the screen. See the Terraform documentation for more information.

Here’s an example:

variable "api_token" {
                      sensitive = true
                    }
                    

In the above example, the visibility of the api_token variable is minimized through the use of setting the sensitive attribute to true for the api_token variable.

7 Variable Types

Strings

The variables used up to this point have been string values. String values are enclosed by double-quotes (“).

compartment_id="<your_compartment_OCID_here>"
                    

Here’s how this is defined in variables.tf:

variable tenancy_id {
                      type = string
                    }
                    

Strings are common, but are by no means the only kind that you can use.

Numbers

Numbers are numeric values that are not surrounded by quotes.

number_of_computes=10
                    

Here’s how this might be defined in variables.tf:

variable "number_of_computes" {
                      type = number
                    }
                    

Boolean

Like many other languages, Terraform supports true and false boolean values. Here’s an example of a Boolean variable being set.

create_computes = true
                    

In the above example, the create_computes variable is set to true. These can be useful for many things, including specifying the desired behavior (like this example, where it might be possible to not create the computes if the value was set to false).

Here’s how this might be defined in variables.tf:

variable "create_computes" {
                      type = bool
                    }
                    

Lists

There are times when a list is needed. Terraform lists are similar to arrays in many other languages. A Terraform list is an ordered lists of values of a given type (could be string values, number values, etc.). Here’s an example of a string list.

compute_names = [ "web1", "web2", "app1", "app2", "db1", "db2" ]
                    

Here’s how this might be defined in variables.tf.

variable "compute_names" {
                      type = list(string)
                    }
                    

To reference a list element, use the index of the item. Terraform is zero-indexed, so the first item is index 0, the second item is index 1, and so on. Look at how you might reference the db1 value (from the above list example, being element 5, index 4):

var.compute_names[4]   # this equals "db1"
                    

Maps

When the power of a key-value relationship is needed, Terraform maps are here to help! Maps are similar to hashes in some other languages, allowing you to have multiple keys, with each key having a value. Here’s an example of a map.

compute_shapes = {
                      "web1" = "VM.Standard2.1",
                      "web2" = "VM.Standard2.1",
                      "app1" = "VM.Standard2.4",
                      "app2" = "VM.Standard2.4",
                      "db1"  = "VM.Standard2.8",
                      "db2"  = "VM.Standard2.8"
                    }
                    

Here’s how this is defined in variables.tf.

variable "compute_shapes" {
                      type = map(string)
                    }
                    

Notice that it is given what kind of values to expect in the map. This could’ve been a map of numbers (instead of strings) or another valid variable type.

To reference a map element, use the item key. Here’s how the db1 value might be referenced.

var.compute_shapes["db1"]   # this equals "VM.Standard2.8"
                    

8 Sample Variable Definitions

Here’s an example of a “toggle” variable (a boolean, which is either true or false):

variable "extra_power" {
                      type = bool
                      default = true
                    }
                    

And here’s an example of a more complex variable (taken from https://github.com/oracle-devrel/terraform-oci-ocloud-landing-zone):

variable "subnet" {
                      type = object({
                        cidr_block                  = string,
                        prohibit_public_ip_on_vnic  = bool, 
                        dhcp_options_id             = string,
                        route_table_id              = string
                      })
                      description                   = "Parameters for each subnet to be managed"
                    }
                    

In the above example, the subnet variable contains several attributes (cidr_block, prohibit_public_ip_on_vnic, etc.), which are of different types. This is just one example of how complex variables can be crafted. Don’t worry about this though, as complex variables are optional (you can stick with single-value variables for most use-cases).

These are just a few examples. You can get really crazy with variables! Have fun with them, be creative, and remember that variables largely define the input interface for the Terraform environment. Look at the Terraform language documentation on input variables to discover some of the other variable types and Terraform variable functionality.