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.