...

/

Customizing Packer With Plugins

Customizing Packer With Plugins

Understand how to make our own plugins for Packer.

The built-in provisioners that we used are pretty powerful. By providing shell access and file uploads, it is possible to do almost everything inside a Packer provisioner.

For large builds, this can be quite tedious. And, if the case is something common, you might want to simply have your own Go application do the work for you.

Packer allows for building plugins that can be used as the following:

  • A Packer builder

  • A Packer provisioner

  • A Packer post-processor

Builders are used when you need to interact with the system that will use your image: Docker, AWS, GCP, Azure, or others. As this isn't a common use outside cloud providers or companies such as VMware adding support, we will not cover this.

Post-processors are normally used to push an image to upload the artifacts generated earlier. As this isn't common, we will not cover this.

Provisioners are the most common, as they are part of the build process to output an image.

Packer has two ways of writing these plugins:

  • Single-plugins

  • Multi-plugins

Single plugins are an older style of writing plugins. The Goss provisioner is written in the older style, which is why we installed it manually.

With the newer style, packer init can be used to download the plugin. In addition, a plugin can register multiple builders, provisioners, or post-processors in a single plugin. This is the recommended way of writing a plugin.

Unfortunately, the official documentation for multi-plugins and doing releases that support packer init is incomplete at the time of this writing. Following the directions will not yield a plugin that can be released using their suggested process.

The instructions included here will fill in the gaps to allow building a multi-plugin that users can install using packer init.

Let's get into how we can write a custom plugin.

Writing your own plugin

Provisioners are powerful extensions to the Packer application. They allow us to customize the application to do whatever we need.

We have already seen how a provisioner can execute Goss to validate our builds. This allowed us to make sure future builds follow a specification for the image.

To write a custom provisioner, we must implement the following interface:

Press + to interact
type Provisioner interface {
ConfigSpec() hcldec.ObjectSpec
Prepare(...interface{}) error
Provision(context.Context, Ui, Communicator, map[string] interface{}) error
}

The preceding code is described as follows:

  • Line 2: ConfigSpec() ...