»Input Variables and local variables

This page introduces input variables and local variables as a way to parameterize a configuration. Once defined, input variables are settable from a default value, environment, special var files, and command line arguments. Local variables can be a compound of input variables and local variables.

»Defining Variables and locals

Let's create a file variables.pkr.hcl with the following contents.

# variables.pkr.hcl

variable "access_key" {}
variable "secret_key" {}
variable "region" {
  default = "us-east-1"
}

locals {
  debian_ami_name = "${var.image_id}-debian"
  foo             = "bar"
}

This defines three variables within your Packer configuration. The first two have empty blocks {}. The third sets a default. If a default value is set, the variable is optional. Otherwise, the variable is required. This also defines two locals: debian_ami_name and foo.

»Using Variables and locals in Configuration

Next, you can define a source using the variables :

# source.pkr.hcl

source "amazon-ebs" "debian" {
  ami_name   = local.debian_ami_name
  access_key = var.aws_access_key
  secret_key = "${var.aws_secret_key}"
  region     = "${var.aws_region}"
}

This uses more interpolations, this time prefixed with var. and local.. This tells Packer that you're accessing variables. This configures the builder with the given variables.

»Assigning Variables

There are multiple ways to assign variables. Below is also the order in which variable values are chosen. The following is the descending order of precedence in which variables are considered. So first defined; first used.

»Command-line flags

You can set variables directly on the command-line with the -var flag.:

$ packer build \
  -var 'access_key=foo' \
  -var 'secret_key=bar'
# ...

Once again, setting variables this way will not save them, and they'll have to be input repeatedly as commands are executed.

»From a file

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

access_key = "foo"
secret_key = "bar"

For all files which match *.auto.pkrvars.hcl present in the current directory, Packer automatically loads them to populate variables. If the file is named something else, you can use the -var-file flag directly to specify a file. These files are the same syntax as Packer configuration files. And like Packer configuration files, these files can also be JSON.

We don't recommend saving usernames and password to version control, but you can create a local secret variables file and use -var-file to load it.

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

$ packer build \
  -var-file="secret.pkrvars.hcl" \
  -var-file="production.pkrvars.hcl"

»From environment variables

Packer will read environment variables in the form of PKR_VAR_name to find the value for a variable. For example, the PKR_VAR_access_key variable can be set to set the access_key variable.

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

»Unspecified values fails

If you execute packer build with certain variables unspecified and those are used somewhere, Packer will error.

»Lists

Lists are defined either explicitly or implicitly

# implicitly by using brackets [...]
variable "cidrs" { default = [] }

# explicitly
variable "cidrs" { type = "list" }

You can specify lists in a variables.pkrvars.hcl file:

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

»Maps

Maps are a way to create variables that are lookup tables. An example will show this best. Let's extract our AMIs into a map and add support for the us-west-2 region as well:

variable "amis" {
  type = "map"
  default = {
    "us-east-1" = "ami-b374d5a5"
    "us-west-2" = "ami-4b32be2b"
  }
}

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. The above demonstrates both.

Then we can lookup in maps like in the following:

source "amazon-ebs" "example" {
  source_ami    = "${lookup(var.amis, var.region)}"
  instance_type = "t2.micro"
}

This introduces a new type of interpolation: a function call. The lookup function does a dynamic lookup in a map for a key. The key is var.region, which specifies that the value of the region variables is the key.

You can also do a static lookup of a map directly with ${var.amis["us-east-1"]}.

»Assigning Maps

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

$ packer build -var 'amis={ us-east-1 = "foo", us-west-2 = "bar" }'
# ...

Here is an example of setting a map's keys from a file. Starting with these variable definitions:

variable "region" {}
variable "amis" {
  type = "map"
}

You can specify keys in a variables.pkrvars.hcl file:

amis = {
  "us-east-1" = "ami-abc123"
  "us-west-2" = "ami-def456"
}

And access them via lookup():

output "ami" {
  value = "${lookup(var.amis, var.region)}"
}

Like so:

$ packer build -var region=us-west-2