github.com/aspring/packer@v0.8.1-0.20150629211158-9db281ac0f89/website/source/docs/extend/developing-plugins.html.markdown (about)

     1  ---
     2  layout: "docs"
     3  page_title: "Developing Plugins"
     4  description: |-
     5    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, from a user standpoint.
     6  ---
     7  
     8  # Developing Plugins
     9  
    10  This page will document how you can develop your own Packer plugins.
    11  Prior to reading this, it is assumed that you're comfortable with Packer
    12  and also know the [basics of how Plugins work](/docs/extend/plugins.html),
    13  from a user standpoint.
    14  
    15  Packer plugins must be written in [Go](http://golang.org/), so it is also
    16  assumed that you're familiar with the language. This page will not be a
    17  Go language tutorial. Thankfully, if you are familiar with Go, the Go toolchain
    18  makes it extremely easy to develop Packer plugins.
    19  
    20  ~> **Warning!** This is an advanced topic. If you're new to Packer, we
    21  recommend getting a bit more comfortable before you dive into writing plugins.
    22  
    23  ## Plugin System Architecture
    24  
    25  Packer has a fairly unique plugin architecture. Instead of loading plugins
    26  directly into a running application, Packer runs each plugin as a
    27  _separate application_. Inter-process communication and RPC is then used
    28  to communicate between the many running Packer processes. Packer core
    29  itself is responsible for orchestrating the processes and handles cleanup.
    30  
    31  The beauty of this is that your plugin can have any dependencies it wants.
    32  Dependencies don't need to line up with what Packer core or any other plugin
    33  uses, because they're completely isolated into the process space of the
    34  plugin itself.
    35  
    36  And, thanks to Go's [interfaces](http://golang.org/doc/effective_go.html#interfaces_and_types),
    37  it doesn't even look like inter-process communication is occurring. You just
    38  use the interfaces like normal, but in fact they're being executed in
    39  a remote process. Pretty cool.
    40  
    41  ## Plugin Development Basics
    42  
    43  Developing a plugin is quite simple. All the various kinds of plugins
    44  have a corresponding interface. The plugin simply needs to implement
    45  this interface and expose it using the Packer plugin package (covered here shortly),
    46  and that's it!
    47  
    48  There are two packages that really matter that every plugin must use.
    49  Other than the following two packages, you're encouraged to use whatever
    50  packages you want. Because plugins are their own processes, there is
    51  no danger of colliding dependencies.
    52  
    53  * `github.com/mitchellh/packer` - Contains all the interfaces that you
    54    have to implement for any given plugin.
    55  
    56  * `github.com/mitchellh/packer/plugin` - Contains the code to serve the
    57    plugin. This handles all the inter-process communication stuff.
    58  
    59  There are two steps involved in creating a plugin:
    60  
    61  1. Implement the desired interface. For example, if you're building a
    62     builder plugin, implement the `packer.Builder` interface.
    63  
    64  2. Serve the interface by calling the appropriate plugin serving method
    65     in your main method. In the case of a builder, this is `plugin.ServeBuilder`.
    66  
    67  A basic example is shown below. In this example, assume the `Builder` struct
    68  implements the `packer.Builder` interface:
    69  
    70  ```go
    71  import (
    72    "github.com/mitchellh/packer/plugin"
    73  )
    74  
    75  // Assume this implements packer.Builder
    76  type Builder struct{}
    77  
    78  func main() {
    79  	plugin.ServeBuilder(new(Builder))
    80  }
    81  ```
    82  
    83  **That's it!** `plugin.ServeBuilder` handles all the nitty gritty of
    84  communicating with Packer core and serving your builder over RPC. It
    85  can't get much easier than that.
    86  
    87  Next, just build your plugin like a normal Go application, using `go build`
    88  or however you please. The resulting binary is the plugin that can be
    89  installed using standard installation procedures.
    90  
    91  The specifics of how to implement each type of interface are covered
    92  in the relevant subsections available in the navigation to the left.
    93  
    94  ~> **Lock your dependencies!** Unfortunately, Go's dependency
    95  management story is fairly sad. There are various unofficial methods out
    96  there for locking dependencies, and using one of them is highly recommended
    97  since the Packer codebase will continue to improve, potentially breaking
    98  APIs along the way until there is a stable release. By locking your dependencies,
    99  your plugins will continue to work with the version of Packer you lock to.
   100  
   101  ## Logging and Debugging
   102  
   103  Plugins can use the standard Go `log` package to log. Anything logged
   104  using this will be available in the Packer log files automatically.
   105  The Packer log is visible on stderr when the `PACKER_LOG` environmental
   106  is set.
   107  
   108  Packer will prefix any logs from plugins with the path to that plugin
   109  to make it identifiable where the logs come from. Some example logs are
   110  shown below:
   111  
   112  ```text
   113  2013/06/10 21:44:43 ui: Available commands are:
   114  2013/06/10 21:44:43 Loading command: build
   115  2013/06/10 21:44:43 packer-command-build: 2013/06/10 21:44:43 Plugin minimum port: 10000
   116  2013/06/10 21:44:43 packer-command-build: 2013/06/10 21:44:43 Plugin maximum port: 25000
   117  2013/06/10 21:44:43 packer-command-build: 2013/06/10 21:44:43 Plugin address: :10000
   118  ```
   119  
   120  As you can see, the log messages from the "build" command plugin are
   121  prefixed with "packer-command-build". Log output is _extremely_ helpful
   122  in debugging issues and you're encouraged to be as verbose as you need to
   123  be in order for the logs to be helpful.
   124  
   125  ## Plugin Development Tips
   126  
   127  Here are some tips for developing plugins, often answering common questions
   128  or concerns.
   129  
   130  ### Naming Conventions
   131  
   132  It is standard practice to name the resulting plugin application
   133  in the format of `packer-TYPE-NAME`. For example, if you're building a
   134  new builder for CustomCloud, it would be standard practice to name the
   135  resulting plugin `packer-builder-custom-cloud`. This naming convention
   136  helps users identify the purpose of a plugin.
   137  
   138  ### Testing Plugins
   139  
   140  While developing plugins, you can configure your Packer configuration
   141  to point directly to the compiled plugin in order to test it. For example,
   142  building the CustomCloud plugin, I may configure packer like so:
   143  
   144  ```javascript
   145  {
   146    "builders": {
   147      "custom-cloud": "/an/absolute/path/to/packer-builder-custom-cloud"
   148    }
   149  }
   150  ```
   151  
   152  This would configure Packer to have the "custom-cloud" plugin, and execute
   153  the binary that I am building during development. This is extremely useful
   154  during development.
   155  
   156  ### Distributing Plugins
   157  
   158  It is recommended you use a tool like [goxc](https://github.com/laher/goxc)
   159  in order to cross-compile your plugin for every platform that Packer supports,
   160  since Go applications are platform-specific. goxc will allow you to build
   161  for every platform from your own computer.