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