github.com/askholme/packer@v0.7.2-0.20140924152349-70d9566a6852/website/source/docs/extend/provisioner.html.markdown (about)

     1  ---
     2  layout: "docs"
     3  page_title: "Custom Provisioner Development"
     4  ---
     5  
     6  # Custom Provisioner Development
     7  
     8  Provisioners are the components of Packer that install and configure
     9  software into a running machine prior to turning that machine into an
    10  image. An example of a provisioner is the [shell provisioner](/docs/provisioners/shell.html),
    11  which runs shell scripts within the machines.
    12  
    13  Prior to reading this page, it is assumed you have read the page on
    14  [plugin development basics](/docs/extend/developing-plugins.html).
    15  
    16  Provisioner plugins implement the `packer.Provisioner` interface and
    17  are served using the `plugin.ServeProvisioner` function.
    18  
    19  <div class="alert alert-block">
    20    <strong>Warning!</strong> This is an advanced topic. If you're new to Packer,
    21    we recommend getting a bit more comfortable before you dive into writing
    22    plugins.
    23  </div>
    24  
    25  
    26  ## The Interface
    27  
    28  The interface that must be implemented for a provisioner is the
    29  `packer.Provisioner` interface. It is reproduced below for easy reference.
    30  The actual interface in the source code contains some basic documentation as well explaining
    31  what each method should do.
    32  
    33  
    34  <pre class="prettyprint">
    35  type Provisioner interface {
    36  	Prepare(...interface{}) error
    37  	Provision(Ui, Communicator) error
    38  }
    39  </pre>
    40  
    41  ### The "Prepare" Method
    42  
    43  The `Prepare` method for each provisioner is called prior to any runs with
    44  the configuration that was given in the template. This is passed in as
    45  an array of `interface{}` types, but is generally `map[string]interface{}`. The prepare
    46  method is responsible for translating this configuration into an internal
    47  structure, validating it, and returning any errors.
    48  
    49  For multiple parameters, they should be merged together into the final
    50  configuration, with later parameters overwriting any previous configuration.
    51  The exact semantics of the merge are left to the builder author.
    52  
    53  For decoding the `interface{}` into a meaningful structure, the
    54  [mapstructure](https://github.com/mitchellh/mapstructure) library is recommended.
    55  Mapstructure will take an `interface{}` and decode it into an arbitrarily
    56  complex struct. If there are any errors, it generates very human friendly
    57  errors that can be returned directly from the prepare method.
    58  
    59  While it is not actively enforced, **no side effects** should occur from
    60  running the `Prepare` method. Specifically, don't create files, don't launch
    61  virtual machines, etc. Prepare's purpose is solely to configure the builder
    62  and validate the configuration.
    63  
    64  The `Prepare` method is called very early in the build process so that
    65  errors may be displayed to the user before anything actually happens.
    66  
    67  ### The "Provision" Method
    68  
    69  The `Provision` method is called when a machine is running and ready
    70  to be provisioned. The provisioner should do its real work here.
    71  
    72  The method takes two parameters: a `packer.Ui` and a `packer.Communicator`.
    73  The UI can be used to communicate with the user what is going on. The
    74  communicator is used to communicate with the running machine, and is
    75  guaranteed to be connected at this point.
    76  
    77  The provision method should not return until provisioning is complete.
    78  
    79  ## Using the Communicator
    80  
    81  The `packer.Communicator` parameter and interface is used to communicate
    82  with running machine. The machine may be local (in a virtual machine or
    83  container of some sort) or it may be remote (in a cloud). The communicator
    84  interface abstracts this away so that communication is the same overall.
    85  
    86  The documentation around the [code itself](https://github.com/mitchellh/packer/blob/master/packer/communicator.go)
    87  is really great as an overview of how to use the interface. You should begin
    88  by reading this. Once you have read it, you can see some example usage below:
    89  
    90  <pre class="prettyprint">
    91  // Build the remote command.
    92  var cmd packer.RemoteCmd
    93  cmd.Command = "echo foo"
    94  
    95  // We care about stdout, so lets collect that into a buffer. Since
    96  // we don't set stderr, that will just be discarded.
    97  var stdout bytes.Buffer
    98  cmd.Stdout = &stdout
    99  
   100  // Start the command
   101  if err := comm.Start(&cmd); err != nil {
   102    panic(err)
   103  }
   104  
   105  // Wait for it to complete
   106  cmd.Wait()
   107  
   108  // Read the stdout!
   109  fmt.Printf("Command output: %s", stdout.String())
   110  </pre>