Variables
In the previous tutorial, you implemented your first provisioner. However, your Packer template is static. Currently if you want to change the contents of the file, you need to manually update your template.
You can use input variables to serve as parameters for a Packer build, allowing aspects of the build to be customized without altering Packer template. In addition, Packer variables are useful when you want to reference a specific value throughout your template.
In this tutorial, you will add Packer variables to parameterize your Packer build, making it more robust.
Prerequisites
This tutorial assumes that you are continuing from the previous tutorials. If not, follow the steps below before continuing.
Install Packer
Create a directory named
packer_tutorial
and paste the following configuration into a file namedaws-ubuntu.pkr.hcl
.packer { required_plugins { amazon = { version = ">= 1.2.8" source = "github.com/hashicorp/amazon" } }} source "amazon-ebs" "ubuntu" { ami_name = "learn-packer-linux-aws-redis-msg" instance_type = "t2.micro" region = "us-west-2" source_ami_filter { filters = { name = "ubuntu/images/*ubuntu-jammy-22.04-amd64-server-*" root-device-type = "ebs" virtualization-type = "hvm" } most_recent = true owners = ["099720109477"] } ssh_username = "ubuntu"} build { name = "learn-packer" sources = [ "source.amazon-ebs.ubuntu" ] provisioner "shell" { environment_vars = [ "FOO=hello world", ] inline = [ "echo Installing Redis", "sleep 30", "sudo apt-get update", "sudo apt-get install -y redis-server", "echo \"FOO is $FOO\" > example.txt", ] } provisioner "shell" { inline = ["echo This provisioner runs last"] }}
Initialize the Packer template.
$ packer init .
Once you have successfully initialized the template, you can continue with the rest of this tutorial.
Add variable to template
Packer has two types of variables: input variables and local variables. In this section, you will use both input and local variables to generate a unique AMI name. This way, you don't need to update your AMI name before each new run.
Add input variable
Add the following variable block to your aws-ubuntu.pkr.hcl
file.
variable "ami_prefix" { type = string default = "learn-packer-linux-aws-redis"}
Variable blocks declare the variable name (ami_prefix
), the data type (string
), and the default value (learn-packer-linux-aws-redis
). While the variable type and default values are optional, we recommend you define these attributes when creating new variables.
You can override the values of input variables at run time using command line flags, environment variables, or special variable definitions files. However, nothing can change the value of an input variable once you run Packer. See Assigning values to input variables for more information.
Add local variable
Add the following local variable block to your aws-ubuntu.pkr.hcl
file.
locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "")}
Local blocks declare the local variable name (timestamp
) and the value (regex_replace(timestamp(), "[- TZ:]", "")
). You can set the local value to anything, including other input variables and locals. Locals are useful when you need to format commonly used values.
In this example, Packer sets the timestamp
local variable to a formatted timestamp using functions.
Unlike input variables, you cannot override the value of local variables. Local variables are set to expressions that are evaluated at run time. The expressions can reference input variables, local variables, data sources, and HCL functions.
Update AMI name
In your Packer template, update your source block to reference the ami_prefix
variable. Notice how the template references the variable as var.ami_prefix
.
source "amazon-ebs" "ubuntu" {- ami_name = "learn-packer-linux-aws-redis-msg"+ ami_name = "${var.ami_prefix}-${local.timestamp}" ## ...}
Build image
Build the image.
$ packer build aws-ubuntu.pkr.hcllearn-packer.amazon-ebs.ubuntu: output will be in this color. ==> learn-packer.amazon-ebs.ubuntu: Prevalidating any provided VPC information==> learn-packer.amazon-ebs.ubuntu: Prevalidating AMI Name: learn-packer-linux-aws-redis-20210429164822## ... ==> Wait completed after 5 minutes 36 seconds ==> Builds finished. The artifacts of successful builds are:--> learn-packer.amazon-ebs.ubuntu: AMIs were created:us-west-2: ami-0bf9922af503bc024
Notice how the Packer creates an AMI where its name consists of learn-packer-linux-aws-redis
, the default value for the ami_prefix
variable, and a timestamp.
Build image with variables
Since ami_prefix
is parameterized, you can define your variable before building the image. There are multiple ways to assign variables. The order of ascending precedence is: variable defaults, environment variables, variable file(s), command-line flag. In this section, you will define variables using variable files and command-line flags.
Build image with variable file
Create a file named example.pkrvars.hcl
and add the following snippet into it.
ami_prefix = "learn-packer-aws-redis-var"
Build the image with the --var-file
flag.
$ packer build --var-file=example.pkrvars.hcl aws-ubuntu.pkr.hcllearn-packer.amazon-ebs.ubuntu: output will be in this color. ==> learn-packer.amazon-ebs.ubuntu: Prevalidating any provided VPC information==> learn-packer.amazon-ebs.ubuntu: Prevalidating AMI Name: learn-packer-aws-redis-var-20210429165423## ...
Notice how the AMI name starts with learn-packer-aws-redis-var-
, the value for ami_prefix
defined by the variable file.
Note
Never commit sensitive values into source control.
Packer will automatically load any variable file that matches the name *.auto.pkrvars.hcl
, without the need to pass the file via the command line.
Rename your variable file so Packer automatically loads it.
$ mv example.pkrvars.hcl example.auto.pkrvars.hcl
Build the image and notice how the AMI name starts with learn-packer-aws-redis-var-
. The packer build .
command loads all the contents in the current directory.
$ packer build .learn-packer.amazon-ebs.ubuntu: output will be in this color. ==> learn-packer.amazon-ebs.ubuntu: Prevalidating any provided VPC information==> learn-packer.amazon-ebs.ubuntu: Prevalidating AMI Name: learn-packer-aws-redis-var-20210429170145## ...
Build image with command line flag
Build the image, setting the variable directly from the command line.
$ packer build --var ami_prefix=learn-packer-aws-redis-var-flag .learn-packer.amazon-ebs.ubuntu: output will be in this color. ==> learn-packer.amazon-ebs.ubuntu: Prevalidating any provided VPC information==> learn-packer.amazon-ebs.ubuntu: Prevalidating AMI Name: learn-packer-aws-redis-var-flag-20210429165729## ...
Notice how the AMI name starts with learn-packer-aws-redis-var-flag
, the value for ami_prefix
defined by the command-line flag. The command-line flag has the highest precedence and will override values defined by other methods.
Next steps
In this tutorial, you made your Packer template more robust by parameterizing it with input and local variables. Then, you defined your variables using variable files and command-line flags during the build step, learning variable definition order of precedence in the process. Continue to the next tutorial to create multiple images in parallel using the same template.
Refer to the following resources for additional details on the concepts covered in this tutorial:
- Read more about the Packer variables.
- Learn more about how to use Packer variable blocks.
- Learn more about how to use Packer local variable blocks.
- Read more about Packer functions.