Get Started - Google Cloud

Input Variables

You now have enough Terraform knowledge to create useful configurations, but the configuration still hardcodes the project name, zone, and other arguments. To become truly shareable and version controlled, we need to parameterize the configurations. This page introduces input variables as a way to do this.

Defining Variables

First, convert a few of the hardcoded values into variables.

Create another file called variables.tf with the following contents:

variable "project" { }

variable "credentials_file" { }

variable "region" {
  default = "us-central1"
}

variable "zone" {
  default = "us-central1-c"
}

This file defines three variables within your Terraform configuration. The first one has an empty block: { }. The other two set defaults. If a default value is set, the variable is optional. Otherwise, the variable is required. If you run terraform plan now, Terraform will prompt you for the values for project and credentials_file.

Using Variables in Configuration

Next, update the GCP provider configuration in main.tf to use these new variables.

provider "google" {
  version = "3.5.0"

  credentials = file(var.credentials_file)

  project = var.project
  region  = var.region
  zone    = var.zone
}

Variables are referenced with the var. prefix.

Assigning Variables

There are several ways to assign variables, depending on your needs.

Command-line flags

You can set variables directly on the command-line with the -var flag. Any command in Terraform that inspects the configuration accepts this flag, such as apply, plan, and refresh:

$ terraform plan -var 'project=<PROJECT_ID>'
...

Setting variables this way will not save them, and they'll have to be passed this way every time you run terraform.

From a file

To persist variable values, create a file and assign variables within this file. Create a new file named terraform.tfvars with the following contents:

project = "<PROJECT_ID>"
credentials_file = "<NAME>.json"

Terraform automatically loads all files which match terraform.tfvars or *.auto.tfvars present in the current directory to populate variables. You can also specify a file to load with the -var-file commandline argument.

These files are the same syntax as Terraform configuration files.

For security reasons, we recommend never saving usernames and passwords to version control. Your terraform configuration will probably need these secret values, though. One solution is to create a local secret variables file and use -var-file to load it.

You can also use multiple -var-file arguments in a single command, with some checked in to version control and others not checked in. For example:

$ terraform apply \
  -var-file="secret.tfvars" \
  -var-file="production.tfvars"

From environment variables

Terraform will read environment variables in the form of TF_VAR_name to find the value for a variable. For example, in this configuration the TF_VAR_region environment variable could be used to set the region terraform variable.

UI Input

If you execute terraform apply with some variables unspecified, Terraform will ask you to input their values interactively. These values are not saved, but this provides a convenient workflow when getting started with Terraform. UI input is not recommended for everyday use of Terraform.

Variable Defaults

If no value is assigned to a variable via any of these methods and the variable has a default key in its declaration, that value will be used for the variable.

Variable Types

Terraform supports a number of different variable types. The most common ones are described below, and you can read the Terraform documentation for a complete list.

Strings

If no type is specified, then Terraform assumes a variable is a string. Like most programming languages, strings are just a sequence of characters. You can also explicitly define a variable as a string.

Explicitly define project as a string by updating variables.tf.

variable "project" {
  type = string
}

This usually isn't necessary, though, since the string type would otherwise be assumed.

Numbers

A number, like a string, is pretty straightforward. Any valid integer or floating point value is allowed. When processing your configuration, Terraform will generally do the right thing when converting from a string to a number. So defining the number type is more about ensure the correct type of input is used.

variable "web_instance_count" {
  type    = number
  default = 1
}

Lists

Like lists or arrays found in many programming languages, a list is a sequence of values.

Add a variable to variables.tf to define the CIDR network blocks to your configuration as a list by either setting the default to a list, or setting the type to list.

variable "cidrs" { default = [] }

You can specify list values in a tfvars file as well. Add the following to terraform.tfvars:

cidrs = [ "10.0.0.0/16", "10.1.0.0/16" ]

We'll use these values later on in this guide.

Maps

Maps are a way to create variables that are lookup tables. Terraform maps are similar to data structures found in programming languages, sometimes referred to as maps or dictionaries.

In your configuration, the machine type is currently set to f1-micro. You might want different machine types for different environments. You can use a map to accomplish this.

Add a map that defines the machine types for each environment to your variables.tf file.

variable "environment" {
  type    = string
  default = "dev"
}

variable "machine_types" {
  type    = map
  default = {
    dev  = "f1-micro"
    test = "n1-highcpu-32"
    prod = "n1-highcpu-32"
  }
}

As with lists, a variable can have a map type assigned explicitly, or it can be implicitly declared as a map by specifying a default value that is a map.

Use the machine_types map to set the machine type for the first vm_instance in main.tf.

resource "google_compute_instance" "vm_instance" {
  name         = "terraform-instance"
  machine_type = var.machine_types[var.environment]
  tags         = ["web", "dev"]
  # ...
}

The square-bracket index notation used here is how we access values inside a map type variable.

Run terraform plan. Because of the default value we used for environment, you should see that there are no changes to apply.

Maps can also use a static value lookup directly. For example: var.machine_types["dev"] will resolve to "f1-micro".

Assigning Maps

We set defaults above, but maps can also be set using the -var and -var-file values. For example:

$ terraform apply -var 'machine_types={ dev = "f1-micro", test = "n1-standard-16", prod = "n1-standard-16" }'
# ...

You can also set a map's keys from a .tfvars file after it is defined as a map.

Starting with these variable definitions in variables.tf.

variable "region" {
  type = string
  default = "us-central1"
}

variable "machine_types" {
  type    = map
  default = {
    dev  = "f1-micro"
    test = "n1-highcpu-32"
    prod = "n1-highcpu-32"
  }
}

Specify values in your terraform.tfvars file.

region = "us-central1"

machine_types = {
  dev  = "f1-micro"
  test = "n1-highcpu-32"
  prod = "n1-highcpu-32"
}

Once again, running terraform apply at this point will have no effect, because the value "f1-micro" from the map is the same as the hard coded value used originally.