packer-cn/website/source/docs/extending/custom-post-processors.html.md

91 lines
4.1 KiB
Markdown
Raw Normal View History

2013-06-18 17:36:21 -04:00
---
2017-06-14 21:04:16 -04:00
description: |
Packer Post-processors are the components of Packer that transform one
artifact into another, for example by compressing files, or uploading them.
2015-07-22 22:31:00 -04:00
layout: docs
2017-06-14 21:04:16 -04:00
page_title: 'Custom Post-Processors - Extending'
sidebar_current: 'docs-extending-custom-post-processors'
---
2013-06-18 17:36:21 -04:00
# Custom Post-Processors
2013-06-18 17:36:21 -04:00
Packer Post-processors are the components of Packer that transform one artifact
2013-06-18 17:36:21 -04:00
into another, for example by compressing files, or uploading them.
2015-07-22 22:31:00 -04:00
In the compression example, the transformation would be taking an artifact with
a set of files, compressing those files, and returning a new artifact with only
a single file (the compressed archive). For the upload example, the
transformation would be taking an artifact with some set of files, uploading
those files, and returning an artifact with a single ID: the URL of the upload.
2013-06-18 17:36:21 -04:00
2015-07-22 22:31:00 -04:00
Prior to reading this page, it is assumed you have read the page on [plugin
2017-03-28 18:28:34 -04:00
development basics](/docs/extending/plugins.html).
2013-06-18 17:36:21 -04:00
2015-07-22 22:31:00 -04:00
Post-processor plugins implement the `packer.PostProcessor` interface and are
served using the `plugin.ServePostProcessor` function.
2013-06-18 17:36:21 -04:00
2017-06-14 21:04:16 -04:00
~> **Warning!** This is an advanced topic. If you're new to Packer, we
recommend getting a bit more comfortable before you dive into writing plugins.
2013-06-18 17:36:21 -04:00
## The Interface
The interface that must be implemented for a post-processor is the
`packer.PostProcessor` interface. It is reproduced below for reference. The
2015-07-22 22:31:00 -04:00
actual interface in the source code contains some basic documentation as well
explaining what each method should do.
2017-06-14 21:04:16 -04:00
``` go
2013-06-18 17:36:21 -04:00
type PostProcessor interface {
2015-07-22 22:31:00 -04:00
Configure(interface{}) error
PostProcess(Ui, Artifact) (a Artifact, keep bool, err error)
2013-06-18 17:36:21 -04:00
}
```
2013-06-18 17:36:21 -04:00
### The "Configure" Method
2015-07-22 22:31:00 -04:00
The `Configure` method for each post-processor is called early in the build
process to configure the post-processor. The configuration is passed in as a raw
`interface{}`. The configure method is responsible for translating this
configuration into an internal structure, validating it, and returning any
errors.
2013-06-18 17:36:21 -04:00
For decoding the `interface{}` into a meaningful structure, the
2013-06-18 17:36:21 -04:00
[mapstructure](https://github.com/mitchellh/mapstructure) library is
recommended. Mapstructure will take an `interface{}` and decode it into an
arbitrarily complex struct. If there are any errors, it generates very
2015-07-22 22:31:00 -04:00
human-friendly errors that can be returned directly from the configure method.
2013-06-18 17:36:21 -04:00
2015-07-22 22:31:00 -04:00
While it is not actively enforced, **no side effects** should occur from running
the `Configure` method. Specifically, don't create files, don't create network
connections, etc. Configure's purpose is solely to setup internal state and
validate the configuration as much as possible.
2013-06-18 17:36:21 -04:00
2015-07-22 22:31:00 -04:00
`Configure` being run is not an indication that `PostProcess` will ever run. For
example, `packer validate` will run `Configure` to verify the configuration
validates, but will never actually run the build.
2013-06-18 17:36:21 -04:00
### The "PostProcess" Method
2015-07-22 22:31:00 -04:00
The `PostProcess` method is where the real work goes. PostProcess is responsible
for taking one `packer.Artifact` implementation, and transforming it into
another.
2013-06-18 17:36:21 -04:00
When we say "transform," we don't mean actually modifying the existing
2015-07-22 22:31:00 -04:00
`packer.Artifact` value itself. We mean taking the contents of the artifact and
creating a new artifact from that. For example, if we were creating a "compress"
post-processor that is responsible for compressing files, the transformation
would be taking the `Files()` from the original artifact, compressing them, and
creating a new artifact with a single file: the compressed archive.
The result signature of this method is `(Artifact, bool, error)`. Each return
value is explained below:
2015-07-22 23:25:58 -04:00
- `Artifact` - The newly created artifact if no errors occurred.
- `bool` - If true, the input artifact will forcefully be kept. By default,
Packer typically deletes all input artifacts, since the user doesn't
generally want intermediary artifacts. However, some post-processors depend
on the previous artifact existing. If this is `true`, it forces packer to
keep the artifact around.
- `error` - Non-nil if there was an error in any way. If this is the case, the
other two return values are ignored.