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