Added -force truncation behavior for manifest, and added docs
This commit is contained in:
parent
78070f8ca9
commit
7a9c3bc2a0
7
main.go
7
main.go
|
@ -15,6 +15,7 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/go-uuid"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/mitchellh/packer/command"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
|
@ -36,6 +37,12 @@ func realMain() int {
|
|||
var wrapConfig panicwrap.WrapConfig
|
||||
|
||||
if !panicwrap.Wrapped(&wrapConfig) {
|
||||
// Generate a UUID for this packer run and pass it to the environment.
|
||||
// GenerateUUID always returns a nil error (based on rand.Read) so we'll
|
||||
// just ignore it.
|
||||
UUID, _ := uuid.GenerateUUID()
|
||||
os.Setenv("PACKER_RUN_UUID", UUID)
|
||||
|
||||
// Determine where logs should go in general (requested by the user)
|
||||
logWriter, err := logOutput()
|
||||
if err != nil {
|
||||
|
|
|
@ -10,6 +10,7 @@ type Artifact struct {
|
|||
BuildTime int64 `json:"build_time"`
|
||||
ArtifactFiles []string `json:"files"`
|
||||
ArtifactId string `json:"artifact_id"`
|
||||
PackerRunUUID string `json:"packer_run_uuid"`
|
||||
}
|
||||
|
||||
func (a *Artifact) BuilderId() string {
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
|
@ -26,7 +27,8 @@ type PostProcessor struct {
|
|||
}
|
||||
|
||||
type ManifestFile struct {
|
||||
Builds []Artifact `json:"builds"`
|
||||
Builds []Artifact `json:"builds"`
|
||||
LastRunUUID string `json:"last_run_uuid"`
|
||||
}
|
||||
|
||||
func (p *PostProcessor) Configure(raws ...interface{}) error {
|
||||
|
@ -51,18 +53,28 @@ func (p *PostProcessor) Configure(raws ...interface{}) error {
|
|||
func (p *PostProcessor) PostProcess(ui packer.Ui, source packer.Artifact) (packer.Artifact, bool, error) {
|
||||
artifact := &Artifact{}
|
||||
|
||||
var err error
|
||||
|
||||
// Create the current artifact.
|
||||
artifact.ArtifactFiles = source.Files()
|
||||
artifact.ArtifactId = source.Id()
|
||||
artifact.BuilderType = p.config.PackerBuilderType
|
||||
artifact.BuildName = p.config.PackerBuildName
|
||||
artifact.BuildTime = time.Now().Unix()
|
||||
artifact.PackerRunUUID = os.Getenv("PACKER_RUN_UUID")
|
||||
|
||||
// Create a lock file with exclusive access. If this fails we will retry
|
||||
// after a delay
|
||||
// TODO add retry
|
||||
// after a delay.
|
||||
lockFilename := p.config.Filename + ".lock"
|
||||
_, err := os.OpenFile(lockFilename, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
|
||||
for i := 0; i < 3; i++ {
|
||||
_, err = os.OpenFile(lockFilename, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
log.Printf("Error locking manifest file for reading and writing. Will sleep and retry. %s", err)
|
||||
// The file should not be locked for very long so we'll keep this short.
|
||||
time.Sleep((time.Duration(i+1) * 200 * time.Millisecond))
|
||||
}
|
||||
defer os.Remove(lockFilename)
|
||||
|
||||
// TODO fix error on first run:
|
||||
|
@ -74,7 +86,7 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, source packer.Artifact) (packe
|
|||
return source, true, fmt.Errorf("Unable to open %s for reading: %s", p.config.Filename, err)
|
||||
}
|
||||
|
||||
// Parse the manifest file JSON, if we have some
|
||||
// Parse the manifest file JSON, if we have one
|
||||
manifestFile := &ManifestFile{}
|
||||
if len(contents) > 0 {
|
||||
if err = json.Unmarshal(contents, manifestFile); err != nil {
|
||||
|
@ -82,12 +94,19 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, source packer.Artifact) (packe
|
|||
}
|
||||
}
|
||||
|
||||
// If -force is set and we are not on same run, truncate the file. Otherwise
|
||||
// we will continue to add new builds to the existing manifest file.
|
||||
if p.config.PackerForce && os.Getenv("PACKER_RUN_UUID") != manifestFile.LastRunUUID {
|
||||
manifestFile = &ManifestFile{}
|
||||
}
|
||||
|
||||
// Add the current artifact to the manifest file
|
||||
manifestFile.Builds = append(manifestFile.Builds, *artifact)
|
||||
manifestFile.LastRunUUID = os.Getenv("PACKER_RUN_UUID")
|
||||
|
||||
// Write JSON to disk
|
||||
if out, err := json.MarshalIndent(manifestFile, "", " "); err == nil {
|
||||
if err := ioutil.WriteFile(p.config.Filename, out, 0664); err != nil {
|
||||
if err = ioutil.WriteFile(p.config.Filename, out, 0664); err != nil {
|
||||
return source, true, fmt.Errorf("Unable to write %s: %s", p.config.Filename, err)
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
---
|
||||
description: |
|
||||
The manifest post-processor writes a JSON file with the build artifacts and IDs from a packer run.
|
||||
layout: docs
|
||||
page_title: 'Manifest Post-Processor'
|
||||
...
|
||||
|
||||
# Manifest Post-Processor
|
||||
|
||||
Type: `manifest`
|
||||
|
||||
The manifest post-processor writes a JSON file with a list of all of the artifacts packer produces during a run. If your packer template includes multiple builds, this helps you keep track of which output artifacts (files, AMI IDs, docker containers, etc.) correspond to each build.
|
||||
|
||||
The manifest post-processor is invoked each time a build completes and *updates* data in the manifest file. Builds are identified by name and type, and include their build time, artifact ID, and file list.
|
||||
|
||||
If packer is run with the `-force` flag the manifest file will be truncated automatically during each packer run. Otherwise, subsequent builds will be added to the file. You can use the timestamps to see which is the latest artifact.
|
||||
|
||||
You can specify manifest more than once and write each build to its own file, or write all builds to the same file. For simple builds manifest only needs to be specified once (see below) but you can also chain it together with other post-processors such as Docker and Artifice.
|
||||
|
||||
## Configuration
|
||||
|
||||
### Optional:
|
||||
|
||||
- `filename` (string) The manifest will be written to this file. This defaults to `packer-manifest.json`.
|
||||
|
||||
### Example Configuration
|
||||
|
||||
You can simply add `{"type":"manifest"}` to your post-processor section. Below is a more verbose example:
|
||||
|
||||
``` {.javascript}
|
||||
{
|
||||
"post-processors": [
|
||||
{
|
||||
"type": "manifest",
|
||||
"filename": "manifest.json"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
Loading…
Reference in New Issue