packer: PostProcessor API change so they can keep artifacts [GH-55]
This commit is contained in:
parent
8eb30482f8
commit
f78cbb45a6
|
@ -13,6 +13,7 @@ IMPROVEMENTS:
|
|||
BUG FIXES:
|
||||
|
||||
* core: More plugin server fixes that avoid hangs on OS X 10.7 [GH-87]
|
||||
* vagrant: AWS boxes will keep the AMI artifact around [GH-55]
|
||||
* virtualbox: More robust version parsing for uploading guest additions. [GH-69]
|
||||
* virtualbox: Output dir and VM name defaults depend on build name,
|
||||
avoiding collisions. [GH-91]
|
||||
|
|
|
@ -194,7 +194,7 @@ PostProcessorRunSeqLoop:
|
|||
}
|
||||
|
||||
builderUi.Say(fmt.Sprintf("Running post-processor: %s", corePP.processorType))
|
||||
artifact, err := corePP.processor.PostProcess(ppUi, priorArtifact)
|
||||
artifact, keep, err := corePP.processor.PostProcess(ppUi, priorArtifact)
|
||||
if err != nil {
|
||||
errors = append(errors, fmt.Errorf("Post-processor failed: %s", err))
|
||||
continue PostProcessorRunSeqLoop
|
||||
|
@ -205,11 +205,12 @@ PostProcessorRunSeqLoop:
|
|||
continue PostProcessorRunSeqLoop
|
||||
}
|
||||
|
||||
keep = keep || corePP.keepInputArtifact
|
||||
if i == 0 {
|
||||
// This is the first post-processor. We handle deleting
|
||||
// previous artifacts a bit different because multiple
|
||||
// post-processors may be using the original and need it.
|
||||
if !keepOriginalArtifact && corePP.keepInputArtifact {
|
||||
if !keepOriginalArtifact && keep {
|
||||
log.Printf(
|
||||
"Flagging to keep original artifact from post-processor '%s'",
|
||||
corePP.processorType)
|
||||
|
@ -218,7 +219,7 @@ PostProcessorRunSeqLoop:
|
|||
} else {
|
||||
// We have a prior artifact. If we want to keep it, we append
|
||||
// it to the results list. Otherwise, we destroy it.
|
||||
if corePP.keepInputArtifact {
|
||||
if keep {
|
||||
artifacts = append(artifacts, priorArtifact)
|
||||
} else {
|
||||
log.Printf("Deleting prior artifact from post-processor '%s'", corePP.processorType)
|
||||
|
|
|
@ -245,6 +245,33 @@ func TestBuild_Run_Artifacts(t *testing.T) {
|
|||
if !reflect.DeepEqual(artifactIds, expectedIds) {
|
||||
t.Fatalf("unexpected ids: %#v", artifactIds)
|
||||
}
|
||||
|
||||
// Test case: Test that with a single post-processor that forcibly
|
||||
// keeps inputs, that the artifacts are kept.
|
||||
build = testBuild()
|
||||
build.postProcessors = [][]coreBuildPostProcessor{
|
||||
[]coreBuildPostProcessor{
|
||||
coreBuildPostProcessor{
|
||||
&TestPostProcessor{artifactId: "pp", keep: true}, "pp", 42, false,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
build.Prepare()
|
||||
artifacts, err = build.Run(ui, cache)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
||||
expectedIds = []string{"b", "pp"}
|
||||
artifactIds = make([]string, len(artifacts))
|
||||
for i, artifact := range artifacts {
|
||||
artifactIds[i] = artifact.Id()
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(artifactIds, expectedIds) {
|
||||
t.Fatalf("unexpected ids: %#v", artifactIds)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuild_RunBeforePrepare(t *testing.T) {
|
||||
|
|
|
@ -19,7 +19,7 @@ func (c *cmdPostProcessor) Configure(config interface{}) error {
|
|||
return c.p.Configure(config)
|
||||
}
|
||||
|
||||
func (c *cmdPostProcessor) PostProcess(ui packer.Ui, a packer.Artifact) (packer.Artifact, error) {
|
||||
func (c *cmdPostProcessor) PostProcess(ui packer.Ui, a packer.Artifact) (packer.Artifact, bool, error) {
|
||||
defer func() {
|
||||
r := recover()
|
||||
c.checkExit(r, nil)
|
||||
|
|
|
@ -12,8 +12,8 @@ func (helperPostProcessor) Configure(interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (helperPostProcessor) PostProcess(packer.Ui, packer.Artifact) (packer.Artifact, error) {
|
||||
return nil, nil
|
||||
func (helperPostProcessor) PostProcess(packer.Ui, packer.Artifact) (packer.Artifact, bool, error) {
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
func TestPostProcessor_NoExist(t *testing.T) {
|
||||
|
|
|
@ -12,6 +12,7 @@ type PostProcessor interface {
|
|||
Configure(interface{}) error
|
||||
|
||||
// PostProcess takes a previously created Artifact and produces another
|
||||
// Artifact. If an error occurs, it should return that error.
|
||||
PostProcess(Ui, Artifact) (Artifact, error)
|
||||
// Artifact. If an error occurs, it should return that error. If `keep`
|
||||
// is to true, then the previous artifact is forcibly kept.
|
||||
PostProcess(Ui, Artifact) (a Artifact, keep bool, err error)
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package packer
|
|||
|
||||
type TestPostProcessor struct {
|
||||
artifactId string
|
||||
keep bool
|
||||
configCalled bool
|
||||
configVal interface{}
|
||||
ppCalled bool
|
||||
|
@ -15,9 +16,9 @@ func (pp *TestPostProcessor) Configure(v interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (pp *TestPostProcessor) PostProcess(ui Ui, a Artifact) (Artifact, error) {
|
||||
func (pp *TestPostProcessor) PostProcess(ui Ui, a Artifact) (Artifact, bool, error) {
|
||||
pp.ppCalled = true
|
||||
pp.ppArtifact = a
|
||||
pp.ppUi = ui
|
||||
return &TestArtifact{id: pp.artifactId}, nil
|
||||
return &TestArtifact{id: pp.artifactId}, pp.keep, nil
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ type PostProcessorServer struct {
|
|||
|
||||
type PostProcessorProcessResponse struct {
|
||||
Err error
|
||||
Keep bool
|
||||
RPCAddress string
|
||||
}
|
||||
|
||||
|
@ -33,30 +34,30 @@ func (p *postProcessor) Configure(raw interface{}) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (p *postProcessor) PostProcess(ui packer.Ui, a packer.Artifact) (packer.Artifact, error) {
|
||||
func (p *postProcessor) PostProcess(ui packer.Ui, a packer.Artifact) (packer.Artifact, bool, error) {
|
||||
server := rpc.NewServer()
|
||||
RegisterArtifact(server, a)
|
||||
RegisterUi(server, ui)
|
||||
|
||||
var response PostProcessorProcessResponse
|
||||
if err := p.client.Call("PostProcessor.PostProcess", serveSingleConn(server), &response); err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
if response.Err != nil {
|
||||
return nil, response.Err
|
||||
return nil, false, response.Err
|
||||
}
|
||||
|
||||
if response.RPCAddress == "" {
|
||||
return nil, nil
|
||||
return nil, false, nil
|
||||
}
|
||||
|
||||
client, err := rpc.Dial("tcp", response.RPCAddress)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
return Artifact(client), nil
|
||||
return Artifact(client), response.Keep, nil
|
||||
}
|
||||
|
||||
func (p *PostProcessorServer) Configure(raw *interface{}, reply *error) error {
|
||||
|
@ -76,7 +77,7 @@ func (p *PostProcessorServer) PostProcess(address string, reply *PostProcessorPr
|
|||
|
||||
responseAddress := ""
|
||||
|
||||
artifact, err := p.p.PostProcess(&Ui{client}, Artifact(client))
|
||||
artifact, keep, err := p.p.PostProcess(&Ui{client}, Artifact(client))
|
||||
if err == nil && artifact != nil {
|
||||
server := rpc.NewServer()
|
||||
RegisterArtifact(server, artifact)
|
||||
|
@ -89,6 +90,7 @@ func (p *PostProcessorServer) PostProcess(address string, reply *PostProcessorPr
|
|||
|
||||
*reply = PostProcessorProcessResponse{
|
||||
Err: err,
|
||||
Keep: keep,
|
||||
RPCAddress: responseAddress,
|
||||
}
|
||||
|
||||
|
|
|
@ -22,11 +22,11 @@ func (pp *TestPostProcessor) Configure(v interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (pp *TestPostProcessor) PostProcess(ui packer.Ui, a packer.Artifact) (packer.Artifact, error) {
|
||||
func (pp *TestPostProcessor) PostProcess(ui packer.Ui, a packer.Artifact) (packer.Artifact, bool, error) {
|
||||
pp.ppCalled = true
|
||||
pp.ppArtifact = a
|
||||
pp.ppUi = ui
|
||||
return testPostProcessorArtifact, nil
|
||||
return testPostProcessorArtifact, false, nil
|
||||
}
|
||||
|
||||
func TestPostProcessorRPC(t *testing.T) {
|
||||
|
@ -63,7 +63,7 @@ func TestPostProcessorRPC(t *testing.T) {
|
|||
// Test PostProcess
|
||||
a := new(testArtifact)
|
||||
ui := new(testUi)
|
||||
artifact, err := pClient.PostProcess(ui, a)
|
||||
artifact, _, err := pClient.PostProcess(ui, a)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ func (p *AWSBoxPostProcessor) Configure(raw interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *AWSBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, error) {
|
||||
func (p *AWSBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
|
||||
// Determine the regions...
|
||||
tplData := &AWSVagrantfileTemplate{
|
||||
Images: make(map[string]string),
|
||||
|
@ -42,7 +42,7 @@ func (p *AWSBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact
|
|||
for _, regions := range strings.Split(artifact.Id(), ",") {
|
||||
parts := strings.Split(regions, ":")
|
||||
if len(parts) != 2 {
|
||||
return nil, fmt.Errorf("Poorly formatted artifact ID: %s", artifact.Id())
|
||||
return nil, false, fmt.Errorf("Poorly formatted artifact ID: %s", artifact.Id())
|
||||
}
|
||||
|
||||
tplData.Images[parts[0]] = parts[1]
|
||||
|
@ -51,20 +51,20 @@ func (p *AWSBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact
|
|||
// Compile the output path
|
||||
outputPath, err := ProcessOutputPath(p.config.OutputPath, "aws", artifact)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// Create a temporary directory for us to build the contents of the box in
|
||||
dir, err := ioutil.TempDir("", "packer")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
// Create the Vagrantfile from the template
|
||||
vf, err := os.Create(filepath.Join(dir, "Vagrantfile"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
defer vf.Close()
|
||||
|
||||
|
@ -72,13 +72,13 @@ func (p *AWSBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact
|
|||
if p.config.VagrantfileTemplate != "" {
|
||||
f, err := os.Open(p.config.VagrantfileTemplate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
contents, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
vagrantfileContents = string(contents)
|
||||
|
@ -91,15 +91,15 @@ func (p *AWSBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact
|
|||
// Create the metadata
|
||||
metadata := map[string]string{"provider": "aws"}
|
||||
if err := WriteMetadata(dir, metadata); err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// Compress the directory to the given output path
|
||||
if err := DirToBox(outputPath, dir); err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
return NewArtifact("aws", outputPath), nil
|
||||
return NewArtifact("aws", outputPath), true, nil
|
||||
}
|
||||
|
||||
var defaultAWSVagrantfile = `
|
||||
|
|
|
@ -68,10 +68,10 @@ func (p *PostProcessor) Configure(raw interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, error) {
|
||||
func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
|
||||
ppName, ok := builtins[artifact.BuilderId()]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Unknown artifact type, can't build box: %s", artifact.BuilderId())
|
||||
return nil, false, fmt.Errorf("Unknown artifact type, can't build box: %s", artifact.BuilderId())
|
||||
}
|
||||
|
||||
// Use the premade PostProcessor if we have one. Otherwise, we
|
||||
|
@ -81,12 +81,12 @@ func (p *PostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (pac
|
|||
log.Printf("Premade post-processor for '%s' not found. Creating.", ppName)
|
||||
pp = keyToPostProcessor(ppName)
|
||||
if pp == nil {
|
||||
return nil, fmt.Errorf("Vagrant box post-processor not found: %s", ppName)
|
||||
return nil, false, fmt.Errorf("Vagrant box post-processor not found: %s", ppName)
|
||||
}
|
||||
|
||||
config := map[string]string{"output": p.config.OutputPath}
|
||||
if err := pp.Configure(config); err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,24 +37,24 @@ func (p *VBoxBoxPostProcessor) Configure(raw interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *VBoxBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, error) {
|
||||
func (p *VBoxBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
|
||||
var err error
|
||||
tplData := &VBoxVagrantfileTemplate{}
|
||||
tplData.BaseMacAddress, err = p.findBaseMacAddress(artifact)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// Compile the output path
|
||||
outputPath, err := ProcessOutputPath(p.config.OutputPath, "virtualbox", artifact)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// Create a temporary directory for us to build the contents of the box in
|
||||
dir, err := ioutil.TempDir("", "packer")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
|
@ -63,25 +63,25 @@ func (p *VBoxBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifac
|
|||
ui.Message(fmt.Sprintf("Copying: %s", path))
|
||||
src, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
dst, err := os.Create(filepath.Join(dir, filepath.Base(path)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
if _, err := io.Copy(dst, src); err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
}
|
||||
|
||||
// Create the Vagrantfile from the template
|
||||
vf, err := os.Create(filepath.Join(dir, "Vagrantfile"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
defer vf.Close()
|
||||
|
||||
|
@ -89,13 +89,13 @@ func (p *VBoxBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifac
|
|||
if p.config.VagrantfileTemplate != "" {
|
||||
f, err := os.Open(p.config.VagrantfileTemplate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
contents, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
vagrantfileContents = string(contents)
|
||||
|
@ -108,22 +108,22 @@ func (p *VBoxBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifac
|
|||
// Create the metadata
|
||||
metadata := map[string]string{"provider": "virtualbox"}
|
||||
if err := WriteMetadata(dir, metadata); err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// Rename the OVF file to box.ovf, as required by Vagrant
|
||||
ui.Message("Renaming the OVF to box.ovf...")
|
||||
if err := p.renameOVF(dir); err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// Compress the directory to the given output path
|
||||
ui.Message(fmt.Sprintf("Compressing box..."))
|
||||
if err := DirToBox(outputPath, dir); err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
return NewArtifact("virtualbox", outputPath), nil
|
||||
return NewArtifact("virtualbox", outputPath), false, nil
|
||||
}
|
||||
|
||||
func (p *VBoxBoxPostProcessor) findBaseMacAddress(a packer.Artifact) (string, error) {
|
||||
|
|
|
@ -29,17 +29,17 @@ func (p *VMwareBoxPostProcessor) Configure(raw interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (p *VMwareBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, error) {
|
||||
func (p *VMwareBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, error) {
|
||||
// Compile the output path
|
||||
outputPath, err := ProcessOutputPath(p.config.OutputPath, "vmware", artifact)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// Create a temporary directory for us to build the contents of the box in
|
||||
dir, err := ioutil.TempDir("", "packer")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
defer os.RemoveAll(dir)
|
||||
|
||||
|
@ -48,37 +48,37 @@ func (p *VMwareBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artif
|
|||
ui.Message(fmt.Sprintf("Copying: %s", path))
|
||||
src, err := os.Open(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
dst, err := os.Create(filepath.Join(dir, filepath.Base(path)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
defer dst.Close()
|
||||
|
||||
if _, err := io.Copy(dst, src); err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
}
|
||||
|
||||
if p.config.VagrantfileTemplate != "" {
|
||||
f, err := os.Open(p.config.VagrantfileTemplate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
contents, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// Create the Vagrantfile from the template
|
||||
vf, err := os.Create(filepath.Join(dir, "Vagrantfile"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
defer vf.Close()
|
||||
|
||||
|
@ -90,14 +90,14 @@ func (p *VMwareBoxPostProcessor) PostProcess(ui packer.Ui, artifact packer.Artif
|
|||
// Create the metadata
|
||||
metadata := map[string]string{"provider": "vmware_desktop"}
|
||||
if err := WriteMetadata(dir, metadata); err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
// Compress the directory to the given output path
|
||||
ui.Message(fmt.Sprintf("Compressing box..."))
|
||||
if err := DirToBox(outputPath, dir); err != nil {
|
||||
return nil, err
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
return NewArtifact("vmware", outputPath), nil
|
||||
return NewArtifact("vmware", outputPath), false, nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue