github.com/phobos182/packer@v0.2.3-0.20130819023704-c84d2aeffc68/website/source/docs/extend/builder.html.markdown (about) 1 --- 2 layout: "docs" 3 page_title: "Custom Builder - Extend Packer" 4 --- 5 6 # Custom Builder Development 7 8 Builders are the components of Packer responsible for creating a machine, 9 bringing it to a point where it can be provisioned, and then turning 10 that provisioned machine into some sort of machine image. Several builders 11 are officially distributed with Packer itself, such as the AMI builder, the 12 VMware builder, etc. However, it is possible to write custom builders using 13 the Packer plugin interface, and this page documents how to do that. 14 15 Prior to reading this page, it is assumed you have read the page on 16 [plugin development basics](/docs/extend/developing-plugins.html). 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 ## The Interface 25 26 The interface that must be implemented for a builder is the `packer.Builder` 27 interface. It is reproduced below for easy reference. The actual interface 28 in the source code contains some basic documentation as well explaining 29 what each method should do. 30 31 <pre class="prettyprint"> 32 type Builder interface { 33 Prepare(...interface{}) error 34 Run(ui Ui, hook Hook, cache Cache) (Artifact, error) 35 Cancel() 36 } 37 </pre> 38 39 ### The "Prepare" Method 40 41 The `Prepare` method for each builder is called prior to any runs with 42 the configuration that was given in the template. This is passed in as 43 an array of `interface{}` types, but is generally `map[string]interface{}`. The prepare 44 method is responsible for translating this configuration into an internal 45 structure, validating it, and returning any errors. 46 47 For multiple parameters, they should be merged together into the final 48 configuration, with later parameters overwriting any previous configuration. 49 The exact semantics of the merge are left to the builder author. 50 51 For decoding the `interface{}` into a meaningful structure, the 52 [mapstructure](https://github.com/mitchellh/mapstructure) library is recommended. 53 Mapstructure will take an `interface{}` and decode it into an arbitrarily 54 complex struct. If there are any errors, it generates very human friendly 55 errors that can be returned directly from the prepare method. 56 57 While it is not actively enforced, **no side effects** should occur from 58 running the `Prepare` method. Specifically, don't create files, don't launch 59 virtual machines, etc. Prepare's purpose is solely to configure the builder 60 and validate the configuration. 61 62 In addition to normal configuration, Packer will inject a `map[string]interface{}` 63 with a key of `packer.DebugConfigKey` set to boolean `true` if debug mode 64 is enabled for the build. If this is set to true, then the builder 65 should enable a debug mode which assists builder developers and advanced 66 users to introspect what is going on during a build. During debug 67 builds, parallelism is strictly disabled, so it is safe to request input 68 from stdin and so on. 69 70 ### The "Run" Method 71 72 `Run` is where all the interesting stuff happens. Run is executed, often 73 in parallel for multiple builders, to actually build the machine, provision 74 it, and create the resulting machine image, which is returned as an 75 implementation of the `packer.Artifact` interface. 76 77 The `Run` method takes three parameters. These are all very useful. The 78 `packer.Ui` object is used to send output to the console. `packer.Hook` is 79 used to execute hooks, which are covered in more detail in the hook section 80 below. And `packer.Cache` is used to store files between multiple Packer 81 runs, and is covered in more detail in the cache section below. 82 83 Because builder runs are typically a complex set of many steps, the 84 [multistep](https://github.com/mitchellh/multistep) library is recommended 85 to bring order to the complexity. Multistep is a library which allows you to 86 separate your logic into multiple distinct "steps" and string them together. 87 It fully supports cancellation mid-step and so on. Please check it out, it is 88 how the built-in builders are all implemented. 89 90 Finally, as a result of `Run`, an implementation of `packer.Artifact` should 91 be returned. More details on creating a `packer.Artifact` are covered in the 92 artifact section below. If something goes wrong during the build, an error 93 can be returned, as well. Note that it is perfectly fine to produce no artifact 94 and no error, although this is rare. 95 96 ### The "Cancel" Method 97 98 The `Run` method is often run in parallel. The `Cancel` method can be 99 called at any time and requests cancellation of any builder run in progress. 100 This method should block until the run actually stops. 101 102 Cancels are most commonly triggered by external interrupts, such as the 103 user pressing `Ctrl-C`. Packer will only exit once all the builders clean up, 104 so it is important that you architect your builder in a way that it is quick 105 to respond to these cancellations and clean up after itself. 106 107 ## Creating an Artifact 108 109 The `Run` method is expected to return an implementation of the 110 `packer.Artifact` interface. Each builder must create their own 111 implementation. The interface is very simple and the documentation on the 112 interface is quite clear. 113 114 The only part of an artifact that may be confusing is the `BuilderId` 115 method. This method must return an absolutely unique ID for the builder. 116 In general, I follow the practice of making the ID contain my GitHub username 117 and then the platform it is building for. For example, the builder ID of 118 the VMware builder is "mitchellh.vmware" or something similar. 119 120 Post-processors use the builder ID value in order to make some assumptions 121 about the artifact results, so it is important it never changes. 122 123 Other than the builder ID, the rest should be self-explanatory by reading 124 the [packer.Artifact interface documentation](#). 125 126 ## Provisioning 127 128 Packer has built-in support for provisioning, but the moment when provisioning 129 runs must be invoked by the builder itself, since only the builder knows 130 when the machine is running and ready for communication. 131 132 When the machine is ready to be provisioned, run the `packer.HookProvision` 133 hook, making sure the communicator is not nil, since this is required for 134 provisioners. An example of calling the hook is shown below: 135 136 <pre class="prettyprint"> 137 hook.Run(packer.HookProvision, ui, comm, nil) 138 </pre> 139 140 At this point, Packer will run the provisioners and no additional work 141 is necessary. 142 143 <div class="alert alert-info alert-block"> 144 <strong>Note:</strong> Hooks are still undergoing thought around their 145 general design and will likely change in a future version. They aren't 146 fully "baked" yet, so they aren't documented here other than to tell you 147 how to hook in provisioners. 148 </div> 149 150 ## Caching Files 151 152 It is common for some builders to deal with very large files, or files that 153 take a long time to generate. For example, the VMware builder has the capability 154 to download the operating system ISO from the internet. This is timely process, 155 so it would be convenient to cache the file. This sort of caching is a core 156 part of Packer that is exposed to builders. 157 158 The cache interface is `packer.Cache`. It behaves much like a Go 159 [RWMutex](http://golang.org/pkg/sync/#RWMutex). The builder requests a "lock" 160 on certain cache keys, and is given exclusive access to that key for the 161 duration of the lock. This locking mechanism allows multiple builders to 162 share cache data even though they're running in parallel. 163 164 For example, both the VMware and VirtualBox support downloading an operating 165 system ISO from the internet. Most of the time, this ISO is identical. The 166 locking mechanisms of the cache allow one of the builders to download it 167 only once, but allow both builders to share the downloaded file. 168 169 The [documentation for packer.Cache](#) is 170 very detailed in how it works.