Why Create a Template Pipeline?
A common issue users face when beginning to create their Packer templates is that while they may need several specialized images, the early provisioning steps are all the same. It can feel tedious to copy all of those images' basic configuraton into each build template. It can feel even more tedious to wait a long time for similar builds to run duplicate steps.
This is one reason why Packer recommends breaking your builds into small, discrete steps. Not only does it allow you to create "base" images that you can build from to create further customizations, but it also allows you to save time in your build process because the "base" images are likely to change less than your customizations.
It also makes it so that a failing build takes less time to debug and re-run.
In this example, we will use the Virtualbox builders, but the concepts from this example can be applied to other builders as well.
Starting from an ISO
Here is an extremely basic virtualbox-iso template:
In order to build using this template, create a directory named "http" in your current working directory. Copy the minimal example from our preseed guide into a file in your http directory and name it "ubuntu_preseed.cfg". Copy the above json template into your current working directory and save it as "example_virtualbox_iso.json"
To run the build, call packer build example_virtualbox_iso.json
.
This example does not set the output_directory or output_filename, so the file will be placed in a default name of "output-virtualbox-iso/vbox-example.ovf" -- the builder will print this file name to the UI output, but in this example the manifest post-processor to will store build information, including the names of the output files, in a json file named "stage-1-manifest.json". From there, you can programmatically look up the output file information.
Customizing the iso using the virtualbox-ovf builder
That output filename generated in the first stage can be used as the source_path for the virtualbox-ovf builder.
More efficiencies
You may find that you want to run time-consuming import post-processors like the "amazon-import" post-processor independently of the build that produces the artifacts you want to process.
In this case, you can use a null builder and manually modify the input to the post-processing chain so that you can get the behavior you want. The below example shows a "vagrant" post-processor being used with a null builder, and manually sets the artifact from our stage-2 ovf build:
By using the null builder instead of just running an ovf builder, we can spare ourselves all of the time Packer would normally spend launching and destroying VMs.
Putting it all together
Packer templates don't come with a custom "glue" to bind them together. We recommend using your CI system or wrapping scripts to connect the templates into a chain.
Chaining together several of the same builders to make "save points"
If you want to use the same builder for several builds in a row, this can feel tedious to implement in json. We recommend you try using HCL configs so that you can reuse the same source in several builds:
HCL templates work by allowing you to draw sources and variables from multiple different files in a single directory, so the following files are assumed to exist in their own folder:
sources.pkr.hcl
build.pkr.hcl
pipeline.sh
To run the pipeline, call pipeline.sh. You can create as many build steps as you want. Each can either inhabit one file, or you can put multiple steps in a single file like shown in the example above.