Packer
The provisioner block
Note: This page is about HCL2 Packer templates. HCL2 templates were first introduced as a beta feature into Packer version 1.5. As of v1.7, HCL2 support is no longer in beta, and is the preferred way to write Packer configuration. For the old-style stable configuration language see template docs. As of v1.6.2, you can convert your legacy JSON template into an HCL2 config file using the hcl2_upgrade command.
The provisioner
block defines how a provisioner is configured.
# builds.pkr.hcl
build {
# ...
provisioner "shell" {
inline = [
"echo provisioning all the things",
"echo the value of 'foo' is '${var.foo}'",
]
}
}
Provisioners use builtin and third-party software to install and configure the machine image after booting. Provisioners prepare the system for use.
The list of available provisioners can be found in the provisioners section.
Run on Specific Sources
You can use the only
or except
configurations to run a provisioner only
with specific sources. These two configurations do what you expect: only
will
only run the provisioner on the specified sources and except
will run the
provisioner on anything other than the specified sources.
An example of only
being used is shown below, but the usage of except
is
effectively the same:
# builds.pkr.hcl
source "amazon-ebs" "first-example" {
#...
}
source "amazon-ebs" "second-example" {
#...
}
build {
sources = [
"source.amazon-ebs.first-example",
"source.amazon-ebs.second-example",
]
provisioner "shell" {
# This provisioner only runs for the 'first-example' source.
only = ["amazon-ebs.first-example"]
inline = [
"echo provisioning all the things",
"echo the value of 'foo' is '${var.foo}'",
]
}
provisioner "shell" {
# This runs with all sources.
inline = [
"echo Hi World!"
]
}
}
The source names within only
and except
must suppress source.
prefix.
The values within only
or except
are source names, not builder types nor build names.
Note: In the cli only
and except
will match against build names (for
example:my_build.amazon-ebs.first-example
) but in a provisioner they will
match on the source name (for example:amazon-ebs.third-example
).
Build-Specific Overrides
While the goal of Packer is to produce identical machine images, it sometimes requires periods of time where the machines are different before they eventually converge to be identical. In these cases, different configurations for provisioners may be necessary depending on the build. This can be done using build-specific overrides.
An example of where this might be necessary is when building both an EC2 AMI and a VMware machine. The source EC2 AMI may setup a user with administrative privileges by default, whereas the VMware machine doesn't have these privileges. In this case, the shell script may need to be executed differently. Of course, the goal is that hopefully the shell script converges these two images to be identical. However, they may initially need to be run differently.
This example is shown below:
source "null" "example1" {
communicator = "none"
}
source "null" "example2" {
communicator = "none"
}
source "null" "example3" {
communicator = "none"
}
build {
sources = ["source.null.example2", "source.null.example3"]
source "source.null.example1" {
// Give a name to this source
name = "renamed"
}
provisioner "shell-local" {
inline = ["echo not overridden"]
override = {
example3 = {
inline = ["echo overrides for example3"]
}
// Refer to the source with the given name
renamed = {
inline = ["echo overrides for renamed"]
}
}
}
}
As you can see, the override
key is used. The value of this key is another
HCL attribute map where the key is the name of a source
definition. The value of this is in turn
another HCL attribute map. This HCL attribute map simply contains the provisioner
configuration as normal. This configuration is merged into the default
provisioner configuration.
On Error Provisioner
You can optionally create a single specialized provisioner called an
error-cleanup-provisioner
. This provisioner will not run unless the normal
provisioning run fails. If the normal provisioning run does fail, this special
error provisioner will run before the instance is shut down. This allows you
to make last minute changes and clean up behaviors that Packer may not be able
to clean up on its own.
For examples, users may use this provisioner to make sure that the instance is properly unsubscribed from any services that it connected to during the build run.
Toy usage example for the error cleanup script:
source "null" "example" {
communicator = "none"
}
build {
sources = ["source.null.example"]
provisioner "shell-local" {
inline = ["exit 2"]
}
error-cleanup-provisioner "shell-local" {
inline = ["echo 'rubber ducky'> ducky.txt"]
}
}
Pausing Before Running
With certain provisioners it is sometimes desirable to pause for some period of time before running it. Specifically, in cases where a provisioner reboots the machine, you may want to wait for some period of time before starting the next provisioner.
Every provisioner definition in a Packer template can take a special
configuration pause_before
that is the amount of time to pause before running
that provisioner. By default, there is no pause. An example is shown below:
# builds.pkr.hcl
build {
# ...
provisioner "shell" {
inline = [
"echo provisioning all the things",
"echo the value of 'foo' is '${var.foo}'",
]
pause_before = "10s"
}
}
For the above provisioner, Packer will wait 10 seconds before uploading and executing the shell script.
Retry on error
With certain provisioners it is sometimes desirable to retry when it fails. Specifically, in cases where the provisioner depends on external processes that are not done yet.
Every provisioner definition in a Packer template can take a special
configuration max_retries
that is the maximum number of times a provisioner will retry on error.
By default, there max_retries
is zero and there is no retry on error. An example is shown below:
# builds.pkr.hcl
build {
# ...
provisioner "shell" {
inline = [
"echo provisioning all the things",
"echo the value of 'foo' is '${var.foo}'",
]
max_retries = 5
}
}
For the above provisioner, Packer will retry maximum five times until stops failing. If after five retries the provisioner still fails, then the complete build will fail.
Timeout
Sometimes a command can take much more time than expected
Every provisioner definition in a Packer template can take a special
configuration timeout
that is the amount of time to wait before
considering that the provisioner failed. By default, there is no timeout. An
example is shown below:
# builds.pkr.hcl
build {
# ...
provisioner "shell" {
inline = [
"echo provisioning all the things",
"echo the value of 'foo' is '${var.foo}'",
]
timeout = "5m"
}
}
For the above provisioner, Packer will cancel the script if it takes more than 5 minutes.
Timeout has no effect in debug mode.
Build Contextual Variables
Packer allows to access connection information and basic instance state information from a provisioner. These information are stored in the build
variable.
Check out the Contextual Variables documentation to learn more about and see some examples of how to use them.