Files

105 lines
5.1 KiB
Plaintext
Raw Permalink Normal View History

2013-06-18 14:36:21 -07:00
---
2020-03-18 18:46:47 -04:00
description: >
2025-01-23 16:02:43 -08:00
Post-processors compress files, upload files, and perform other tasks that transform artifacts. Learn how to create customm post-processors that extend Packer.
page_title: Create custom post-processors
---
2013-06-18 14:36:21 -07:00
2025-01-23 16:02:43 -08:00
# Create custom post-processors
2013-06-18 14:36:21 -07:00
2022-09-15 18:12:37 -04:00
Packer post-processors transform one artifact into another. For example, a post-processor might compress or upload files.
2013-06-18 14:36:21 -07:00
2015-07-22 19:31:00 -07: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 14:36:21 -07:00
Post-processor plugins implement the [`packer.PostProcessor`](https://pkg.go.dev/github.com/hashicorp/packer-plugin-sdk/packer#PostProcessor) interface and are
2015-07-22 19:31:00 -07:00
served using the `plugin.ServePostProcessor` function.
2013-06-18 14:36:21 -07:00
2023-01-27 11:47:08 -06:00
This page explains how to implement and serve custom post-processors. If you want your post-processor to support HashiCorp Cloud Platform (HCP) Packer, you should also review the [HCP Packer Support](/packer/docs/plugins/creation/hcp-support) documentation.
2022-09-15 18:12:37 -04:00
~> **Warning:** This is an advanced topic that requires strong knowledge of Packer and Packer plugins.
## Before You Begin
We recommend reviewing the following resources before you begin development:
2023-01-27 11:47:08 -06:00
- [Developing Plugins - Overview](/packer/docs/plugins/creation)
2022-09-15 18:12:37 -04:00
- The [Go](https://go.dev/) language. You must write custom plugins in Go, so this guide assumes you are familiar with the language.
2013-06-18 14:36:21 -07:00
## The Interface
The interface that must be implemented for a post-processor is the
[`packer.PostProcessor`](https://pkg.go.dev/github.com/hashicorp/packer-plugin-sdk/packer#PostProcessor) interface. It is reproduced below for reference. The
2015-07-22 19:31:00 -07:00
actual interface in the source code contains some basic documentation as well
explaining what each method should do.
2020-03-18 18:46:47 -04:00
```go
2013-06-18 14:36:21 -07:00
type PostProcessor interface {
2019-12-18 16:13:52 +01:00
ConfigSpec() hcldec.ObjectSpec
2015-07-22 19:31:00 -07:00
Configure(interface{}) error
PostProcess(context.Context, Ui, Artifact) (a Artifact, keep, mustKeep bool, err error)
2013-06-18 14:36:21 -07:00
}
```
2013-06-18 14:36:21 -07:00
2019-12-20 12:05:01 -08:00
### The "ConfigSpec" Method
This method returns a hcldec.ObjectSpec, which is a spec necessary for using
HCL2 templates with Packer. For information on how to use and implement this
function, check our
2023-01-27 11:47:08 -06:00
[object spec docs](/packer/guides/hcl/component-object-spec)
2019-12-20 12:05:01 -08:00
2013-06-18 14:36:21 -07:00
### The "Configure" Method
2015-07-22 19:31:00 -07:00
The `Configure` method for each post-processor is called early in the build
2018-10-26 17:02:51 -07:00
process to configure the post-processor. The configuration is passed in as a
raw `interface{}`. The configure method is responsible for translating this
2015-07-22 19:31:00 -07:00
configuration into an internal structure, validating it, and returning any
errors.
2013-06-18 14:36:21 -07:00
2014-01-14 20:13:43 -07:00
For decoding the `interface{}` into a meaningful structure, the
2013-06-18 14:36:21 -07: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 19:31:00 -07:00
human-friendly errors that can be returned directly from the configure method.
2013-06-18 14:36:21 -07:00
2018-10-26 17:02:51 -07: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 14:36:21 -07:00
2018-10-26 17:02:51 -07:00
`Configure` being run is not an indication that `PostProcess` will ever run.
For example, `packer validate` will run `Configure` to verify the configuration
2015-07-22 19:31:00 -07:00
validates, but will never actually run the build.
2013-06-18 14:36:21 -07:00
### The "PostProcess" Method
2018-10-26 17:02:51 -07:00
The `PostProcess` method is where the real work goes. PostProcess is
responsible for taking one `packer.Artifact` implementation, and transforming
it into another.
A `PostProcess` call can be cancelled at any moment. Cancellation is triggered
when the done chan of the context struct (`<-ctx.Done()`) unblocks .
2013-06-18 14:36:21 -07:00
When we say "transform," we don't mean actually modifying the existing
2015-07-22 19:31:00 -07:00
`packer.Artifact` value itself. We mean taking the contents of the artifact and
2018-10-26 17:02:51 -07:00
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.
2013-07-01 11:35:09 -07:00
The result signature of this method is `(Artifact, bool, bool, error)`. Each
return value is explained below:
2013-07-01 11:35:09 -07:00
2020-03-18 18:46:47 -04:00
- `Artifact` - The newly created artifact if no errors occurred.
- `bool` - If keep 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.
- `bool` - If forceOverride is true, then any user input for
keep_input_artifact is ignored and the artifact is either kept or discarded
according to the value set in `keep`.
- `error` - Non-nil if there was an error in any way. If this is the case,
the other two return values are ignored.