github.com/marksheahan/packer@v0.10.2-0.20160613200515-1acb2d6645a0/website/source/docs/extend/developing-plugins.html.md (about)

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