I'm using Packer to provision a VM for my project's CI pipeline, which is hosted on a supported cloud provider. My provisioning scripts are a little complicated, so I need to iterate on them carefully to get them right. To save money I'm using a local image builder with the same provisioners as used in the cloud builder. This local image won't be used in production, or even in development; it just serves to help me validate my provisioning scripts (and the resulting environment).
Since I'm testing my provisioner scripts, I want to share one provisioner
block with all relevant build
blocks. However, I can't figure out for the life of me how to do that; for now, I've been copying and pasting my provisioner
block. The only
field is the only field that varies, as I don't usually want to build the local and cloud images at the same time. How can I use one provisioner
block within multiple build
blocks in an HCL-formatted template, plus the occasional override?
Here's (a simplified version of) the code that I want to shrink:
# Variables go here...
source "vagrant" "windows-local" {
source_path = "gusztavvargadr/visual-studio"
box_name = "build-runner-windows-local"
box_version = "v2019.0.2010"
communicator = "ssh"
# Other fields omitted for brevity
}
source "amazon-ebs" "windows" {
access_key = "${var.aws_access_key}"
ami_name = "build-runner-windows"
communicator = "winrm"
instance_type = "t2.micro"
region = "${var.aws_region}"
secret_key = "${var.aws_secret_key}"
source_ami_filter {
filters = {
name = "Windows_Server-2019-English-Full-Base-2020.11.11"
root-device-type = "ebs"
virtualization-type = "hvm"
}
most_recent = true
owners = ["amazon"]
}
# Other fields omitted for brevity
}
build {
name = "windows-aws"
sources = ["source.amazon-ebs.windows"]
provisioner "powershell" {
environment_vars = [
"AWS_ACCESS_KEY_ID=${var.aws_access_key}",
"AWS_SECRET_ACCESS_KEY=${var.aws_secret_key}",
"AWS_DEFAULT_REGION=${var.aws_region}",
"A_DOZEN_MORE_VARS=..."
]
only = ["amazon-ebs.windows"] # Note: Not the same value as in the windows-local build
scripts = [
"windows/first-script.ps1",
"windows/second-script.ps1",
"windows/cleanup.ps1"
]
}
provisioner "windows-restart" {}
}
build {
name = "windows-local"
sources = ["source.vagrant.windows-local"]
provisioner "powershell" {
environment_vars = [
"AWS_ACCESS_KEY_ID=${var.aws_access_key}",
"AWS_SECRET_ACCESS_KEY=${var.aws_secret_key}",
"AWS_DEFAULT_REGION=${var.aws_region}",
"A_DOZEN_MORE_VARS=..."
]
only = ["vagrant.windows-local"] # Note: Not the same value as in the windows-aws build
scripts = [
"windows/first-script.ps1",
"windows/second-script.ps1",
"windows/cleanup.ps1"
]
}
provisioner "windows-restart" {}
}
You just need to add the source builders to sources in the build. In your case, that would be:
Then, you can remove name from build and add them in the specific source block, like:
If you need more information, here some doc you might find helpful: https://www.packer.io/docs/templates/hcl_templates/blocks/build/source https://www.packer.io/docs/templates/hcl_templates/blocks/build/provisioner