github.com/marksheahan/packer@v0.10.2-0.20160613200515-1acb2d6645a0/website/source/docs/extend/provisioner.html.md (about)

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