Added manifest post-processor, which creates a manifest of build artifacts
This commit is contained in:
parent
73d376633d
commit
db593a517d
|
@ -39,6 +39,7 @@ import (
|
|||
dockerpushpostprocessor "github.com/mitchellh/packer/post-processor/docker-push"
|
||||
dockersavepostprocessor "github.com/mitchellh/packer/post-processor/docker-save"
|
||||
dockertagpostprocessor "github.com/mitchellh/packer/post-processor/docker-tag"
|
||||
manifestpostprocessor "github.com/mitchellh/packer/post-processor/manifest"
|
||||
shelllocalpostprocessor "github.com/mitchellh/packer/post-processor/shell-local"
|
||||
vagrantpostprocessor "github.com/mitchellh/packer/post-processor/vagrant"
|
||||
vagrantcloudpostprocessor "github.com/mitchellh/packer/post-processor/vagrant-cloud"
|
||||
|
@ -108,6 +109,7 @@ var PostProcessors = map[string]packer.PostProcessor{
|
|||
"docker-push": new(dockerpushpostprocessor.PostProcessor),
|
||||
"docker-save": new(dockersavepostprocessor.PostProcessor),
|
||||
"docker-tag": new(dockertagpostprocessor.PostProcessor),
|
||||
"manifest": new(manifestpostprocessor.PostProcessor),
|
||||
"shell-local": new(shelllocalpostprocessor.PostProcessor),
|
||||
"vagrant": new(vagrantpostprocessor.PostProcessor),
|
||||
"vagrant-cloud": new(vagrantcloudpostprocessor.PostProcessor),
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package manifest
|
||||
|
||||
import "fmt"
|
||||
|
||||
const BuilderId = "packer.post-processor.manifest"
|
||||
|
||||
type Artifact struct {
|
||||
BuildName string `json:"build_name"`
|
||||
BuildTime int64 `json:"build_time"`
|
||||
Description string `json:"description"`
|
||||
BuildFiles []string `json:"files"`
|
||||
BuildId string `json:"artifact_id"`
|
||||
}
|
||||
|
||||
func (a *Artifact) BuilderId() string {
|
||||
return BuilderId
|
||||
}
|
||||
|
||||
func (a *Artifact) Files() []string {
|
||||
return a.BuildFiles
|
||||
}
|
||||
|
||||
func (a *Artifact) Id() string {
|
||||
return a.BuildId
|
||||
}
|
||||
|
||||
func (a *Artifact) String() string {
|
||||
return fmt.Sprintf("%s-%s", a.BuildName, a.BuildId)
|
||||
}
|
||||
|
||||
func (a *Artifact) State(name string) interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Artifact) Destroy() error {
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package manifest
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/mitchellh/packer/common"
|
||||
"github.com/mitchellh/packer/helper/config"
|
||||
"github.com/mitchellh/packer/packer"
|
||||
"github.com/mitchellh/packer/template/interpolate"
|
||||
)
|
||||
|
||||
// The artifact-override post-processor allows you to specify arbitrary files as
|
||||
// artifacts. These will override any other artifacts created by the builder.
|
||||
// This allows you to use a builder and provisioner to create some file, such as
|
||||
// a compiled binary or tarball, extract it from the builder (VM or container)
|
||||
// and then save that binary or tarball and throw away the builder.
|
||||
|
||||
type Config struct {
|
||||
common.PackerConfig `mapstructure:",squash"`
|
||||
|
||||
Filename string `mapstructure:"filename"`
|
||||
|
||||
ctx interpolate.Context
|
||||
}
|
||||
|
||||
type PostProcessor struct {
|
||||
config Config
|
||||
}
|
||||
|
||||
type ManifestFile struct {
|
||||
Builds []Artifact `json:"builds"`
|
||||
}
|
||||
|
||||
func (p *PostProcessor) Configure(raws ...interface{}) error {
|
||||
err := config.Decode(&p.config, &config.DecodeOpts{
|
||||
Interpolate: true,
|
||||
InterpolateContext: &p.config.ctx,
|
||||
InterpolateFilter: &interpolate.RenderFilter{
|
||||
Exclude: []string{},
|
||||
},
|
||||
}, raws...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if p.config.Filename == "" {
|
||||
p.config.Filename = "packer-manifest.json"
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *PostProcessor) PostProcess(ui packer.Ui, source packer.Artifact) (packer.Artifact, bool, error) {
|
||||
artifact := &Artifact{}
|
||||
|
||||
// Create the current artifact.
|
||||
artifact.BuildFiles = source.Files()
|
||||
artifact.BuildId = source.Id()
|
||||
artifact.BuildName = source.BuilderId()
|
||||
artifact.BuildTime = time.Now().Unix()
|
||||
artifact.Description = source.String()
|
||||
|
||||
// Create a lock file with exclusive access. If this fails we will retry
|
||||
// after a delay
|
||||
lockFilename := p.config.Filename + ".lock"
|
||||
_, err := os.OpenFile(lockFilename, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
|
||||
defer os.Remove(lockFilename)
|
||||
|
||||
// Read the current manifest file from disk
|
||||
contents := []byte{}
|
||||
if contents, err = ioutil.ReadFile(p.config.Filename); err != nil && !os.IsNotExist(err) {
|
||||
return nil, true, fmt.Errorf("Unable to open %s for reading: %s", p.config.Filename, err)
|
||||
}
|
||||
|
||||
// Parse the manifest file JSON, if we have some
|
||||
manifestFile := &ManifestFile{}
|
||||
if len(contents) > 0 {
|
||||
if err = json.Unmarshal(contents, manifestFile); err != nil {
|
||||
return nil, true, fmt.Errorf("Unable to parse content from %s: %s", p.config.Filename, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Add the current artifact to the manifest file
|
||||
manifestFile.Builds = append(manifestFile.Builds, *artifact)
|
||||
|
||||
// Write JSON to disk
|
||||
if out, err := json.Marshal(manifestFile); err == nil {
|
||||
if err := ioutil.WriteFile(p.config.Filename, out, 0664); err != nil {
|
||||
return nil, true, fmt.Errorf("Unable to write %s: %s", p.config.Filename, err)
|
||||
}
|
||||
} else {
|
||||
return nil, true, fmt.Errorf("Unable to marshal JSON %s", err)
|
||||
}
|
||||
|
||||
return artifact, true, err
|
||||
}
|
Loading…
Reference in New Issue