mirror of https://github.com/hashicorp/packer
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
207 lines
13 KiB
207 lines
13 KiB
---
|
|
page_title: Upgrading your plugin to use the Packer plugin sdk
|
|
sidebar_title: Upgrade Your Plugin to use the Packer plugin sdk
|
|
---
|
|
|
|
# Upgrading your plugin to be compatible with Packer v1.7.0 and later
|
|
|
|
In version v1.7.0 the Packer plugin development model was split into two separate packages: the Packer core
|
|
and the Packer plugin SDK. Prior to version 1.7.0, the Packer core repository (https://github.com/hashicorp/packer) contained the libraries and interfaces used by Packer plugins. In version 1.7.0, these libraries were moved into their own repository (https://github.com/hashicorp/packer-plugin-sdk). If you authored a plugin prior to the v1.7.0 release using the API version 4, you should switch to the Packer Plugin SDK.
|
|
|
|
## Update plugins to use the new SDK
|
|
|
|
### Why update to the new SDK?
|
|
|
|
The goal of the SDK is to clearly separate the Packer core from the Packer plugins; as a plugin maintainer, you should only have to import the SDK and not the core. The SDK will allow us to use semantic versioning to express the changes to the API that our maintainers are expected to use, and will help us keep a clearer promise to you about the location and functionality of our helper tools.
|
|
|
|
Packer is currently backwards compatible with the old API because the plugin API itself has not changed yet, so if you choose to continue using the old Packer imports, you will be able to do so until you need to upgrade the version of Packer you are importing to create your plugin.
|
|
|
|
### How to update plugins to use the packer-plugin-SDK
|
|
|
|
In a best-case scenario, all you'll have to do is update the packer imports to use the packer-plugin-sdk import path. Replacing `github.com/hashicorp/packer` with `github.com/hashicorp/packer-plugin-sdk`.
|
|
|
|
To help with the migration of existing plugins the [packer-sdk-migrator](https://github.com/hashicorp/packer-sdk-migrator#packer-sdk-migrator) CLI tool is available to automatically rewrite all of the import paths to use to `packer-plugin-sdk` module. The migration CLI provides an [eligibility check](https://github.com/hashicorp/packer-sdk-migrator#packer-sdk-migrator-check-check-eligibility-for-migration) that can be used to determine if a plugin can be migrated with the tool.
|
|
|
|
|
|
With the creation of the SDK the import paths may not map directly to the paths within Packer core, as they have been refactored to make it easier to discover and use helpful modules. Below are a few common import paths. For a full list of available imports see [Packer Plugin SDK Docs](https://pkg.go.dev/github.com/hashicorp/packer-plugin-sdk/)
|
|
|
|
|
|
| Old Path | New Path |
|
|
| ---------| -------- |
|
|
| github.com/hashicorp/packer/template/config | github.com/hashicorp/packer-plugin-sdk/template/config |
|
|
| github.com/hashicorp/packer/packer | github.com/hashicorp/packer-plugin-sdk/packer |
|
|
| github.com/hashicorp/packer/template/interpolate | github.com/hashicorp/packer-plugin-sdk/template/interpolate |
|
|
|
|
Here is a more comprehensive list of old imports and their new replacements:
|
|
|
|
| Old Path | New Path |
|
|
| ---------| -------- |
|
|
| github.com/hashicorp/packer/helper/builder/testing | github.com/hashicorp/packer-plugin-sdk/acctest |
|
|
| **new** | github.com/hashicorp/packer-plugin-sdk/acctest/provisioneracc
|
|
| github.com/hashicorp/packer/helper/tests | github.com/hashicorp/packer-plugin-sdk/acctest/testutils |
|
|
| github.com/hashicorp/packer/common/adapter | github.com/hashicorp/packer-plugin-sdk/adapter |
|
|
| github.com/hashicorp/packer/common/bootcommand | github.com/hashicorp/packer-plugin-sdk/bootcommand |
|
|
| github.com/hashicorp/packer/common/chroot | github.com/hashicorp/packer-plugin-sdk/chroot |
|
|
| github.com/hashicorp/packer/common | github.com/hashicorp/packer-plugin-sdk/common |
|
|
| github.com/hashicorp/packer/helper/communicator | github.com/hashicorp/packer-plugin-sdk/communicator |
|
|
| github.com/hashicorp/packer/helper/config | github.com/hashicorp/packer-plugin-sdk/template/config |
|
|
| github.com/hashicorp/packer/template/interpolate | github.com/hashicorp/packer-plugin-sdk/template/interpolate |
|
|
| github.com/hashicorp/packer/communicator/ssh | github.com/hashicorp/packer-plugin-sdk/communicator/ssh |
|
|
| github.com/hashicorp/packer/helper/communicator/sshkey | github.com/hashicorp/packer-plugin-sdk/communicator/sshkey |
|
|
| github.com/hashicorp/packer/provisioner | github.com/hashicorp/packer-plugin-sdk/guestexec |
|
|
| github.com/hashicorp/packer/common/json | github.com/hashicorp/packer-plugin-sdk/json |
|
|
| github.com/hashicorp/packer/helper/multistep | github.com/hashicorp/packer-plugin-sdk/multistep |
|
|
| steps from github.com/hashicorp/packer/common | github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps |
|
|
| github.com/hashicorp/packer/common/net | github.com/hashicorp/packer-plugin-sdk/net |
|
|
| github.com/hashicorp/packer/packer | github.com/hashicorp/packer-plugin-sdk/packer |
|
|
| github.com/hashicorp/packer/builder | github.com/hashicorp/packer-plugin-sdk/packerbuilderdata |
|
|
| github.com/hashicorp/packer/packer | github.com/hashicorp/packer-plugin-sdk/pathing |
|
|
| github.com/hashicorp/packer/packer/plugin | github.com/hashicorp/packer-plugin-sdk/plugin |
|
|
| github.com/hashicorp/packer/common/random | github.com/hashicorp/packer-plugin-sdk/random |
|
|
| github.com/hashicorp/packer/common | github.com/hashicorp/packer-plugin-sdk/retry |
|
|
| github.com/hashicorp/packer/packer/rpc | github.com/hashicorp/packer-plugin-sdk/rpc |
|
|
| github.com/hashicorp/packer/communicator | github.com/hashicorp/packer-plugin-sdk/sdk-internals/communicator |
|
|
| github.com/hashicorp/packer/common/shell | github.com/hashicorp/packer-plugin-sdk/shell |
|
|
| github.com/hashicorp/packer/common/shell-local | github.com/hashicorp/packer-plugin-sdk/shell-local |
|
|
| github.com/hashicorp/packer/helper/builder/localexec | github.com/hashicorp/packer-plugin-sdk/shell-local/localexec |
|
|
| github.com/hashicorp/packer/common/shutdowncommand | github.com/hashicorp/packer-plugin-sdk/shutdowncommand |
|
|
| github.com/hashicorp/packer/template | github.com/hashicorp/packer-plugin-sdk/template |
|
|
| github.com/hashicorp/packer/packer/tmp | github.com/hashicorp/packer-plugin-sdk/tmp |
|
|
| github.com/hashicorp/packer/helper/useragent | github.com/hashicorp/packer-plugin-sdk/useragent |
|
|
| github.com/hashicorp/packer/common/uuid | github.com/hashicorp/packer-plugin-sdk/uuid |
|
|
| **new** | github.com/hashicorp/packer-plugin-sdk/version
|
|
|
|
|
|
When in doubt you can search the packer-plugin-sdk repo for the name of your imported structs or functions to see where they exist in the SDK now; we have not changed struct or function names. Or refer to the [Packer Plugin SDK Docs](https://pkg.go.dev/github.com/hashicorp/packer-plugin-sdk/) for help.
|
|
|
|
## Upgrade plugins to use new multi-plugin rpc server
|
|
|
|
### Why upgrade to the new rpc server?
|
|
|
|
The goal of this server is to enable multiple related plugins, for example plugins that share a hypervisor or cloud, to rely on shared libraries without having to submodule common code. The helps maintainers who are experts in a specific technology to focus on that technology without having to maintain several repositories. Having a single global plugin wrapper also helps the Packer core register, download, and install plugins. Finally, it allows more clarity in the plugin binary naming and name-usage within a template.
|
|
|
|
### Do I have to upgrade?
|
|
|
|
For now, you do not have to upgrade your plugin, but we recommend doing it. Packer will continue to understand how to discover and launch old-style plugins. However, you will not be able to register your plugin with HashiCorp until you have upgraded the plugin.
|
|
|
|
### How to upgrade the plugin
|
|
|
|
We've created a scaffolding repository over at https://github.com/hashicorp/packer-plugin-scaffolding/
|
|
|
|
If you already have a working plugin, the [builder plugin scaffolding](https://github.com/hashicorp/packer-plugin-scaffolding/tree/main/builder/scaffolding) should look pretty familiar. You'll notice that there are some changes to main.go.
|
|
|
|
Previously, you may have had a main.go that looks something like:
|
|
|
|
```golang
|
|
package main
|
|
|
|
import (
|
|
"github.com/hashicorp/packer-plugin-sdk/plugin"
|
|
)
|
|
|
|
func main() {
|
|
server, err := plugin.Server()
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// MyProvisioner fulfils the Provisioner interface and is defined elsewhere
|
|
server.RegisterProvisioner(new(MyProvisioner))
|
|
server.Serve()
|
|
}
|
|
|
|
```
|
|
|
|
With this single-plugin binary you'd install it by putting it into the plugin directory with the name
|
|
`packer-provisioner-foo`.
|
|
|
|
|
|
In the new multi-plugin binary you'll want to use the NewSet() function to create a server.
|
|
|
|
```golang
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
|
|
"github.com/hashicorp/packer-plugin-sdk/plugin"
|
|
)
|
|
|
|
func main() {
|
|
pps := plugin.NewSet()
|
|
pps.RegisterProvisioner("foo", new(CommentProvisioner))
|
|
err := pps.Run()
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err.Error())
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
```
|
|
|
|
The implementation is extremely similar, but now we use the "NewSet" function to create the plugin Server, and call Run() instead of Serve().
|
|
|
|
With the multi-plugin binary example, it is important to note that the name of the binary must be in the form of `packer-pluign-name`. Otherwise Packer will not register it as a multi-plugin, nor to download it.
|
|
|
|
```go
|
|
go build -o packer-plugin-bar
|
|
```
|
|
|
|
Then you'd install it by putting it into the plugin directory with the name `packer-plugin-name`.
|
|
|
|
With the multi-plugin binary you would then refer to your newly installed plugin as `bar-foo` within your Packer template. Whereas, in the single binary setup, you'd have used the name "bar" in your Packer template.
|
|
|
|
At this point it is important to note that multi-plugins are to Packer, what providers are to Terraform. Multi-plugin binaries provide one or more plugin types to Packer which depend on the same cloud or other APIs. See [registering multiple plugins](#registering-multiple-plugins) for details on how to register more than one plugin type.
|
|
|
|
If your plugin providers a single plugin type please continue reading for instruction on using the Set architecture for single plugins.
|
|
|
|
|
|
## Using the Set Architecture for Single Plugins
|
|
|
|
***THIS IS ON THE PACKER MASTER BRANCH AND WILL BE AVAILABLE IN V1.7.0***
|
|
|
|
The naming described above could be awkward for users who have given plugins singular names. For example, in a prior world, you may have created a provisioner saved as `packer-provisioner-foo` and accessed it in your template using `"type": "foo"`; Now, if you install a plugin named `packer-plugin-foo`, and register it using NewSet() and RegisterProvisioner() with the name "foo", you'll have to access it in your template using `"type": "foo-foo"` which stutters and breaks backwards compatibility.
|
|
|
|
To solve this we have a specialized string constant you can use to register your plugins instead:
|
|
|
|
instead of registering your plugin using
|
|
|
|
```golang
|
|
pps.RegisterProvisioner("foo", new(MyProvisioner))
|
|
```
|
|
|
|
you can register it using
|
|
|
|
```golang
|
|
pps.RegisterProvisioner(plugin.DEFAULT_NAME, new(MyProvisioner))
|
|
```
|
|
|
|
This will tell the Packer core that when consuming this plugin set, the given plugin should just use the root plugin name, rather than a compound name. Therefore, when accessing a plugin registered this way, you can again reference it in your Packer template using `"type": "foo"`.
|
|
|
|
## Registering multiple plugins
|
|
|
|
This is useful where "bar" is the name of the hypervisor or environment, and "foo" is the specific plugin type. Many Packer plugins already follow this naming convention. To use an example from the Packer core; if you were writing a custom VSphere plugin, you could now name the plugin `packer-plugin-vsphere`, and register different VSphere builder plugins using:
|
|
|
|
```golang
|
|
func main() {
|
|
pps := plugin.NewSet()
|
|
pps.RegisterBuilder("iso", new(ISOBuilder))
|
|
pps.RegisterBuilder("clone", new(CloneBuilder))
|
|
err := pps.Run()
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err.Error())
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
```
|
|
|
|
And then reference your plugin in the Packer template using "vsphere-iso" and "vsphere-clone" just like Packer currently does.
|
|
|
|
You can still use the `DEFAULT_NAME` constant with a set implementation; in this example, whatever you register with the DEFAULT_NAME will be referenced in the Packer template as "vsphere". You can only register one plugin per plugin set using the DEFAULT_NAME
|
|
|
|
## Distributing migrated plugins
|
|
Once a plugin has been migrated to use the `packer-plugin-sdk` it can be released as it normally would and used by Packer by [installing the plugin](/docs/plugins#installing-plugins) manually into the respective Packer plugin directory.
|
|
|
|
If however, you would like to take advantage of Packer's automated plugin installation process via `packer init` -- the preferred method of installation -- you will need to make the plugin available on GitHub and in a repository named after the multi-plugin `https://github.com/<yourorg>/packer-plugin-name`. See [Creating a GitHub Release](/docs/plugins/creation#creating-a-github-release) for details on the recommended practice for releasing Packer plugins on GitHub.
|