website: plugin development basics
This commit is contained in:
parent
97ec004724
commit
ba3e58f962
|
@ -0,0 +1,148 @@
|
|||
---
|
||||
layout: "docs"
|
||||
---
|
||||
|
||||
# Developing Plugins
|
||||
|
||||
This page will document how you can develop your own Packer plugins.
|
||||
Prior to reading this, it is assumed that you're comfortable with Packer
|
||||
and also know the [basics of how Plugins work](/docs/extend/plugins.html),
|
||||
from a user standpoint.
|
||||
|
||||
Packer plugins must be written in [Go](http://golang.org/), so it is also
|
||||
assumed that you're familiar with the language. This page will not be a
|
||||
Go language tutorial. Thankfully, if you are familiar with Go, the Go toolchain
|
||||
makes it extremely easy to develop Packer plugins.
|
||||
|
||||
<div class="alert alert-block">
|
||||
<strong>Warning!</strong> This is an advanced topic. If you're new to Packer,
|
||||
we recommend getting a bit more comfortable before you dive into writing
|
||||
plugins.
|
||||
</div>
|
||||
|
||||
## Plugin System Architecture
|
||||
|
||||
Packer has a fairly unique plugin architecture. Instead of loading plugins
|
||||
directly into a running application, Packer runs each plugin as a
|
||||
_separate application_. Inter-process communication and RPC is then used
|
||||
to communicate between the many running Packer processes. Packer core
|
||||
itself is responsible for orchestrating the processes and handles cleanup.
|
||||
|
||||
The beauty of this is that your plugin can have any dependencies it wants.
|
||||
Dependencies don't need to line up with what Packer core or any other plugin
|
||||
uses, because they're completely isolated into the process space of the
|
||||
plugin itself.
|
||||
|
||||
And, thanks to Go's [interfaces](http://golang.org/doc/effective_go.html#interfaces_and_types),
|
||||
it doesn't even look like inter-process communication is occuring. You just
|
||||
use the interfaces like normal, but in fact they're being executed in
|
||||
a remote process. Pretty cool.
|
||||
|
||||
## Plugin Development Basics
|
||||
|
||||
Developing a plugin is quite simple. All the various kinds of plugins
|
||||
have a corresponding interface. The plugin simply needs to implement
|
||||
this interface and expose it using the Packer plugin package (covered here shortly),
|
||||
and that's it!
|
||||
|
||||
There are two packages that really matter that every plugin must use.
|
||||
Other than the following two packages, you're encouraged to use whatever
|
||||
packages you want. Because plugins are their own processes, there is
|
||||
no danger of colliding dependencies.
|
||||
|
||||
* `github.com/mitchellh/packer` - Contains all the interfaces that you
|
||||
have to implement for any given plugin.
|
||||
|
||||
* `github.com/mitchellh/packer/plugin` - Contains the code to serve the
|
||||
plugin. This handles all the inter-process communication stuff.
|
||||
|
||||
There are two steps involved in creating a plugin:
|
||||
|
||||
1. Implement the desired interface. For example, if you're building a
|
||||
builder plugin, implement the `packer.Builder` interface.
|
||||
|
||||
2. Serve the interface by calling the appropriate plugin serving method
|
||||
in your main method. In the case of a builder, this is `plugin.ServeBuilder`.
|
||||
|
||||
A basic example is shown below. In this example, assume the `Builder` struct
|
||||
implements the `packer.Builder` interface:
|
||||
|
||||
<pre class="prettyprint">
|
||||
import (
|
||||
"github.com/mitchellh/packer/plugin"
|
||||
)
|
||||
|
||||
// Assume this implements packer.Builder
|
||||
type Builder struct{}
|
||||
|
||||
func main() {
|
||||
plugin.ServeBuilder(new(Builder))
|
||||
}
|
||||
</pre>
|
||||
|
||||
**That's it!** `plugin.ServeBuilder` handles all the nitty gritty of
|
||||
communicating with Packer core and serving your builder over RPC. It
|
||||
can't get much easier than that.
|
||||
|
||||
Next, just build your plugin like a normal Go application, using `go build`
|
||||
or however you please. The resulting binary is the plugin that can be
|
||||
installed using standard installation procedures.
|
||||
|
||||
The specifics of how to implement each type of interface are covered
|
||||
in the relevant subsections available in the navigation to the left.
|
||||
|
||||
## Logging and Debugging
|
||||
|
||||
Plugins can use the standard Go `log` package to log. Anything logged
|
||||
using this will be available in the Packer log files automatically.
|
||||
The Packer log is visible on stderr when the `PACKER_LOG` environmental
|
||||
is set.
|
||||
|
||||
Packer will prefix any logs from plugins with the path to that plugin
|
||||
to make it identifiable where the logs come from. Some example logs are
|
||||
shown below:
|
||||
|
||||
```
|
||||
2013/06/10 21:44:43 ui: Available commands are:
|
||||
2013/06/10 21:44:43 Loading command: build
|
||||
2013/06/10 21:44:43 packer-command-build: 2013/06/10 21:44:43 Plugin minimum port: 10000
|
||||
2013/06/10 21:44:43 packer-command-build: 2013/06/10 21:44:43 Plugin maximum port: 25000
|
||||
2013/06/10 21:44:43 packer-command-build: 2013/06/10 21:44:43 Plugin address: :10000
|
||||
```
|
||||
|
||||
As you can see, the log messages from the "build" command plugin are
|
||||
prefixed with "packer-command-build". Log output is _extremely_ helpful
|
||||
in debugging issues and you're encouraged to be as verbose as you need to
|
||||
be in order for the logs to be helpful.
|
||||
|
||||
## Plugin Development Tips
|
||||
|
||||
Here are some tips for developing plugins, often answering common questions
|
||||
or concerns.
|
||||
|
||||
First, it is standard practice to name the resulting plugin application
|
||||
in the format of `packer-TYPE-NAME`. For example, if you're building a
|
||||
new builder for CustomCloud, it would be standard practice to name the
|
||||
resulting plugin `packer-builder-custom-cloud`. This naming convention
|
||||
helps users identify the purpose of a plugin.
|
||||
|
||||
Next, while developing plugins, you can configure your Packer configuration
|
||||
to point directly to the compiled plugin in order to test it. For example,
|
||||
building the CustomCloud plugin, I may configure packer like so:
|
||||
|
||||
<pre class="prettyprint">
|
||||
{
|
||||
"builders": {
|
||||
"custom-cloud": "/an/absolute/path/to/packer-builder-custom-cloud"
|
||||
}
|
||||
}
|
||||
</pre>
|
||||
|
||||
This would configure Packer to have the "custom-cloud" plugin, and execute
|
||||
the binary that I am building during development. This is extremely useful
|
||||
during development.
|
||||
|
||||
Additionally, it is recommended you use a tool like [goxc](https://github.com/laher/goxc)
|
||||
in order to cross-compile your plugin for every platform that Packer supports,
|
||||
since Go applications are platform-specific. goxc will allow you to build
|
||||
for every platform from your own computer.
|
|
@ -4,7 +4,7 @@ layout: "docs"
|
|||
|
||||
# Packer Plugins
|
||||
|
||||
Plugins allow Packer new functionality to be added to Packer without
|
||||
Plugins allow new functionality to be added to Packer without
|
||||
modifying the core source code. Packer plugins are able to add new
|
||||
commands, builders, provisioners, hooks, and more. In fact, much of Packer
|
||||
itself is implemented by writing plugins that are simply distributed with
|
||||
|
@ -14,7 +14,7 @@ to load with Packer.
|
|||
|
||||
This page will cover how to install and use plugins. If you're interested
|
||||
in developing plugins, the documentation for that is available the
|
||||
[developing plugins](#) page.
|
||||
[developing plugins](/docs/extend/developing-plugins.html) page.
|
||||
|
||||
Because Packer is so young, there is no official listing of available
|
||||
Packer plugins. Plugins are best found via Google. Typically, searching
|
||||
|
@ -65,13 +65,13 @@ from the core Packer configuration.
|
|||
In addition to builders, other types of plugins can be installed. The full
|
||||
list is below:
|
||||
|
||||
* "builders" - A key/value pair of builder type to the builder plugin
|
||||
* `builders` - A key/value pair of builder type to the builder plugin
|
||||
application.
|
||||
|
||||
* "commands" - A key/value pair of the command name to the command plugin
|
||||
* `commands` - A key/value pair of the command name to the command plugin
|
||||
application. The command name is what is executed on the command line, like
|
||||
`packer COMMAND`.
|
||||
|
||||
* "provisioners" - A key/value pair of the provisioner type to the
|
||||
* `provisioners` - A key/value pair of the provisioner type to the
|
||||
provisioner plugin application. The provisioner type is the value of the
|
||||
"type" configuration used within templates.
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
|
||||
<li class="nav-header">Extend Packer</li>
|
||||
<li><a href="/docs/extend/plugins.html">Packer Plugins</a></li>
|
||||
<li><a href="/docs/extend/developing-plugins.html">Developing Plugins</a></li>
|
||||
<li><a href="/docs/extend/builder.html">Custom Builder</a></li>
|
||||
<li><a href="#">Custom Command</a></li>
|
||||
<li><a href="#">Custom Provisioner</a></li>
|
||||
|
|
Loading…
Reference in New Issue