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