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