371 lines
10 KiB
Plaintext
371 lines
10 KiB
Plaintext
---
|
|
page_title: Input and Local Variables guide
|
|
sidebar_title: Variables
|
|
description: |-
|
|
This page introduces input variables and local variables as a way to
|
|
parameterize a configuration.
|
|
---
|
|
|
|
# Input Variables and local variables
|
|
|
|
@include 'guides/hcl2-beta-note.mdx'
|
|
|
|
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
|
|
|
|
In the legacy JSON packer templates, any variables we hadn't already defined in
|
|
the "variables" stanza of our json template could simply be passed in via the
|
|
command line or a var-file; if a variable was never defined it would generally
|
|
be interpolated to an empty string.
|
|
|
|
_In the HCL2 packer templates, we must always pre-define our variables in the
|
|
HCL equivalent of the "variables" stanza._
|
|
|
|
Another difference between JSON and HCL packer templates is that in JSON packer
|
|
templates, the "variables" stanza, if used, was always in the same .json file
|
|
as the builds and builders. In HCL, it can exist in its own file if you want it
|
|
to.
|
|
|
|
To demonstrate, let's create a file `variables.pkr.hcl` with the following
|
|
contents.
|
|
|
|
-> **Note**: that the file can be named anything, since Packer loads all
|
|
files ending in `.pkr.hcl` in a directory. If you split your configuration
|
|
across multiple files, use
|
|
`packer build <command line flags> <source directory>` to initiate a build.
|
|
|
|
```hcl
|
|
// variables.pkr.hcl
|
|
|
|
// For those variables that you don't provide a default for, you must
|
|
// set them from the command line, a var-file, or the environment.
|
|
|
|
variable "weekday" {}
|
|
|
|
variable "sudo_password" {
|
|
type = string
|
|
default = "mypassword"
|
|
// Sensitive vars are hidden from output as of Packer v1.6.5
|
|
sensitive = true
|
|
}
|
|
|
|
variable "flavor" {
|
|
type = string
|
|
default = "strawberry"
|
|
}
|
|
|
|
variable "exit_codes" {
|
|
type = list(number)
|
|
default = [0]
|
|
}
|
|
|
|
locals {
|
|
ice_cream_flavor = "${var.flavor}-ice-cream"
|
|
foo = "bar"
|
|
}
|
|
```
|
|
|
|
This defines several variables within your Packer configuration, each showing
|
|
off a different way to set them. The first variable, "weekday", is an empty
|
|
block `{}`, without a type or a default.
|
|
|
|
However, it's generally best to provide the type in your variable definition,
|
|
as you can see in variable "flavor", which we have given a type of "string",
|
|
and variable "exit_codes", which we have given a type of "list(number)",
|
|
meaning it is a list/array of numbers.
|
|
|
|
When a variable is passed from the cli or environment and the variable's type
|
|
is not set, Packer will expect it to be a string. But if it is passed from a
|
|
var-file where Packer can interpret HCL properly it can be a slice or any
|
|
supported type.
|
|
|
|
In addition to setting the type, the "flavor" and "exit_codes" variables also
|
|
provide a default. If you set a default value, then you don't need to set the
|
|
variable at run time. Packer will use a provided command-line var,
|
|
var-file, or environment var if it exists, but if not Packer will fall back to
|
|
this default value.
|
|
|
|
If you do not set a default value, Packer will fail immediately when you try to
|
|
run a `build` if you have not provided the missing variable via the
|
|
command-line, a var-file, or the environment. The `validate`, `inspect` and
|
|
`console` commands will work, but variables with unknown values will be
|
|
`<unknown>`.
|
|
|
|
This also defines two locals: `ice_cream_flavor` and `foo`.
|
|
|
|
-> **Note**: that it is _not_ possible to reference a variable in the
|
|
definition of another variable. But it _is_ possible to use locals and
|
|
variables in the definition of a local, as shown in the ice_cream_flavor
|
|
definition.
|
|
|
|
## Using Variables and locals in Configuration
|
|
|
|
For simplicity's sake, we're going to put a null source in the same file as
|
|
we are putting the build configuration. This file demonstrates how to use the
|
|
variables we previously defined.
|
|
|
|
```hcl
|
|
// null_example.pkr.hcl
|
|
|
|
source "null" "example" {
|
|
communicator = "none"
|
|
}
|
|
|
|
build {
|
|
sources = [
|
|
"source.null.example"
|
|
]
|
|
provisioner "shell-local" {
|
|
// Note that for options that are documented as template engines,
|
|
// we still have to use the golang template engine syntax rather than our
|
|
// specialized HCL2 variable syntax. This example shows a combination of
|
|
// an HCL2 variable and the golang template engines built into the
|
|
// execute_command option
|
|
execute_command = ["/bin/sh", "-c", "echo ${var.sudo_password}| {{.Vars}} {{.Script}}"]
|
|
environment_vars = ["HELLO_USER=packeruser", "UUID=${build.PackerRunUUID}"]
|
|
inline = ["echo the Packer run uuid is $UUID"]
|
|
}
|
|
provisioner "shell-local" {
|
|
inline = ["echo var.flavor is: ${var.flavor}",
|
|
"echo local.ice_cream_flavor is: ${local.ice_cream_flavor}"]
|
|
valid_exit_codes = var.exit_codes
|
|
}
|
|
}
|
|
```
|
|
|
|
As you can see in the example, you can access your variables directly by
|
|
giving them the `var.` or `local.` prefix. If you want to embed the variables
|
|
in a string, you can do so with the `${}` HCL interpolation syntax. If you are
|
|
using an option that is a template engine, you still need to use the golang
|
|
templating engine syntax `{{ .OPTION }}` for those engines.
|
|
|
|
## 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.:
|
|
|
|
```shell-session
|
|
$ packer build \
|
|
-var 'weekday=Sunday' \
|
|
-var 'flavor=chocolate' \
|
|
-var 'sudo_password=hunter42' .
|
|
```
|
|
|
|
Once again, setting variables this way will not save them, and they'll
|
|
have to be input repeatedly as commands are executed.
|
|
|
|
If you plan to assign variables via the command line, we strongly recommend that
|
|
you at least set a default type instead of using empty blocks; this helps the
|
|
HCL parser understand what is being set. Otherwise it will interpret all of your
|
|
command line variables as strings.
|
|
|
|
#### 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:
|
|
|
|
```hcl
|
|
sudo_password = "partyparrot"
|
|
weekday = "Sunday"
|
|
```
|
|
|
|
You tell Packer to use this var file using the `-var-file` command line flag.
|
|
|
|
```shell-session
|
|
$ packer build -var-file="variables.pkrvars.hcl" .
|
|
```
|
|
|
|
Packer will automatically load any var file that matches the name
|
|
`*.auto.pkrvars.hcl`, without the need to pass the file via the command line.
|
|
if we rename the above var-file from variables.pkrvars.hcl to
|
|
variables.auto.pkrvars.hcl, then we can run our build simply by calling
|
|
|
|
```shell-session
|
|
$ packer build .
|
|
```
|
|
|
|
You may provide as many -var-file flags as you would like:
|
|
|
|
```shell-session
|
|
$ packer build \
|
|
-var-file="secret.pkrvars.hcl" \
|
|
-var-file="production.pkrvars.hcl" .
|
|
```
|
|
|
|
These files can also be JSON:
|
|
|
|
variables.json:
|
|
|
|
```json
|
|
{
|
|
"weekday": "sunday",
|
|
"flavor": "mint"
|
|
}
|
|
```
|
|
|
|
```shell-session
|
|
$ packer build -var-file=variables.json
|
|
```
|
|
|
|
We don't recommend saving sensitive information 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:
|
|
|
|
```shell-session
|
|
$ 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.
|
|
|
|
```shell-session
|
|
$ export PKR_VAR_weekday=Monday
|
|
$ packer build .
|
|
```
|
|
|
|
#### 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.
|
|
|
|
If all of your variables have defaults, then you can call a packer build using:
|
|
|
|
```shell-session
|
|
$ packer build .
|
|
```
|
|
|
|
You can make this work for yourself using the variable example file above by
|
|
commenting out or removing the "weekday" variable declaration, since it is not
|
|
actually used in the example build.
|
|
|
|
If your variable definitions are stored in the same file as your source and
|
|
build, you can call the build against that specific file:
|
|
|
|
```shell-session
|
|
$ packer build self_contained_example.pkr.hcl
|
|
```
|
|
|
|
#### Unspecified Values Fail
|
|
|
|
If you call `packer build` with any variables defined but not set, Packer will
|
|
error.
|
|
|
|
## Variable Type Reference
|
|
|
|
### Lists
|
|
|
|
Lists are defined either explicitly or implicitly
|
|
|
|
```hcl
|
|
# implicitly by using brackets [...]
|
|
variable "cidrs" { default = [] }
|
|
|
|
# explicitly
|
|
variable "cidrs" { type = list }
|
|
```
|
|
|
|
You can specify lists in a `variables.pkrvars.hcl` file:
|
|
|
|
```hcl
|
|
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:
|
|
|
|
```hcl
|
|
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:
|
|
|
|
```hcl
|
|
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:
|
|
|
|
```shell-session
|
|
$ 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:
|
|
|
|
```hcl
|
|
variable "region" {}
|
|
variable "amis" {
|
|
type = map
|
|
}
|
|
```
|
|
|
|
You can specify keys in a `variables.pkrvars.hcl` file:
|
|
|
|
```hcl
|
|
amis = {
|
|
"us-east-1" = "ami-abc123"
|
|
"us-west-2" = "ami-def456"
|
|
}
|
|
```
|
|
|
|
And access them via `lookup()`:
|
|
|
|
```hcl
|
|
output "ami" {
|
|
value = "${lookup(var.amis, var.region)}"
|
|
}
|
|
```
|
|
|
|
Like so:
|
|
|
|
```shell-session
|
|
$ packer build -var region=us-west-2
|
|
```
|