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.