Add guide for upgrading plugins to use the packer-plugin-sdk

This commit is contained in:
Megan Marsh 2021-01-12 13:36:12 -08:00
parent e77d270fc4
commit f591396b7e
1 changed files with 184 additions and 0 deletions

View File

@ -0,0 +1,184 @@
---
page_title: Upgrading your plugin to use the packer-plugin-sdk
sidebar_title: Upgrade Your Plugin to use the packer-plugin-sdk
description: |-
This guide tells you how to update your plugin to use the new packer-plugin-sdk
---
# Upgrading your plugin to be compatible with Packer v1.7.0
## 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 replace all the places you import
github.com/hashicorp/packer with github.com/hashicorp/packer-plugin-sdk.
But some of the import paths have changed more than that because we've refactored the SDK some to make it easier to discover and use helpful modules. Here are a few common paths below:
github.com/hashicorp/packer-plugin-sdk/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:
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.
## 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 to have to upgrade your plugin. 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/tree/main/builder/scaffolding
If you already have a working plugin, this 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`.
Now, you'll want to use the NewSet() function to create a server. so,
```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)
}
}
```
So the implementation is extremely similar, but now we use the "NewSet" function, and call Run() instead of Serve().
With this example, you'd install it by putting it into the plugin directory with the name `packer-plugin-bar`.
In the single binary setup, this you'd have used the name "bar" in your packer template. Now, you need to use the name "bar-foo" in the template.
## 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
We will soon write a follow-up guide explaining how to register you new plugin set with HashiCorp.