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

     1  ---
     2  layout: "docs"
     3  page_title: "Custom Post-Processor Development"
     4  ---
     5  
     6  # Custom Post-Processor Development
     7  
     8  Post-processors are the components of Packer that transform one artifact
     9  into another, for example by compressing files, or uploading them.
    10  
    11  In the compression example, the transformation would be taking an artifact
    12  with a set of files, compressing those files, and returning a new
    13  artifact with only a single file (the compressed archive). For the
    14  upload example, the transformation would be taking an artifact with
    15  some set of files, uploading those files, and returning an artifact
    16  with a single ID: the URL of the upload.
    17  
    18  Prior to reading this page, it is assumed you have read the page on
    19  [plugin development basics](/docs/extend/developing-plugins.html).
    20  
    21  Post-processor plugins implement the `packer.PostProcessor` interface and
    22  are served using the `plugin.ServePostProcessor` function.
    23  
    24  <div class="alert alert-block">
    25    <strong>Warning!</strong> This is an advanced topic. If you're new to Packer,
    26    we recommend getting a bit more comfortable before you dive into writing
    27    plugins.
    28  </div>
    29  
    30  
    31  ## The Interface
    32  
    33  The interface that must be implemented for a post-processor is the
    34  `packer.PostProcessor` interface. It is reproduced below for easy reference.
    35  The actual interface in the source code contains some basic documentation as well explaining
    36  what each method should do.
    37  
    38  
    39  <pre class="prettyprint">
    40  type PostProcessor interface {
    41  	Configure(interface{}) error
    42  	PostProcess(Ui, Artifact) (a Artifact, keep bool, err error)
    43  }
    44  </pre>
    45  
    46  ### The "Configure" Method
    47  
    48  The `Configure` method for each post-processor is called early in the
    49  build process to configure the post-processor. The configuration is passed
    50  in as a raw `interface{}`. The configure method is responsible for translating
    51  this configuration into an internal structure, validating it, and returning
    52  any errors.
    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
    58  human-friendly errors that can be returned directly from the configure
    59  method.
    60  
    61  While it is not actively enforced, **no side effects** should occur from
    62  running the `Configure` method. Specifically, don't create files, don't
    63  create network connections, etc. Configure's purpose is solely to setup
    64  internal state and validate the configuration as much as possible.
    65  
    66  `Configure` being run is not an indication that `PostProcess` will ever
    67  run. For example, `packer validate` will run `Configure` to verify the
    68  configuration validates, but will never actually run the build.
    69  
    70  ### The "PostProcess" Method
    71  
    72  The `PostProcess` method is where the real work goes. PostProcess is
    73  responsible for taking one `packer.Artifact` implementation, and transforming
    74  it into another.
    75  
    76  When we say "transform," we don't mean actually modifying the existing
    77  `packer.Artifact` value itself. We mean taking the contents of the artifact
    78  and creating a new artifact from that. For example, if we were creating
    79  a "compress" post-processor that is responsible for compressing files,
    80  the transformation would be taking the `Files()` from the original artifact,
    81  compressing them, and creating a new artifact with a single file: the
    82  compressed archive.
    83  
    84  The result signature of this method is `(Artifact, bool, error)`. Each
    85  return value is explained below:
    86  
    87  * `Artifact` - The newly created artifact if no errors occurred.
    88  * `bool` - If true, the input artifact will forcefully be kept. By default,
    89    Packer typically deletes all input artifacts, since the user doesn't generally
    90    want intermediary artifacts. However, some post-processors depend on the
    91    previous artifact existing. If this is `true`, it forces packer to keep the
    92    artifact around.
    93  * `error` - Non-nil if there was an error in any way. If this is the case,
    94    the other two return values are ignored.