Commit 26c7ac2d authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

packer: post-processors

parent 85e615bb
...@@ -19,7 +19,7 @@ func testBuild() *coreBuild { ...@@ -19,7 +19,7 @@ func testBuild() *coreBuild {
}, },
postProcessors: [][]coreBuildPostProcessor{ postProcessors: [][]coreBuildPostProcessor{
[]coreBuildPostProcessor{ []coreBuildPostProcessor{
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp"}, "testPP", make(map[string]interface{}), true}, coreBuildPostProcessor{&MockPostProcessor{ArtifactId: "pp"}, "testPP", make(map[string]interface{}), true},
}, },
}, },
variables: make(map[string]string), variables: make(map[string]string),
...@@ -66,12 +66,12 @@ func TestBuild_Prepare(t *testing.T) { ...@@ -66,12 +66,12 @@ func TestBuild_Prepare(t *testing.T) {
} }
corePP := build.postProcessors[0][0] corePP := build.postProcessors[0][0]
pp := corePP.processor.(*TestPostProcessor) pp := corePP.processor.(*MockPostProcessor)
if !pp.configCalled { if !pp.ConfigureCalled {
t.Fatal("should be called") t.Fatal("should be called")
} }
if !reflect.DeepEqual(pp.configVal, []interface{}{make(map[string]interface{}), packerConfig}) { if !reflect.DeepEqual(pp.ConfigureConfigs, []interface{}{make(map[string]interface{}), packerConfig}) {
t.Fatalf("bad: %#v", pp.configVal) t.Fatalf("bad: %#v", pp.ConfigureConfigs)
} }
} }
...@@ -208,8 +208,8 @@ func TestBuild_Run(t *testing.T) { ...@@ -208,8 +208,8 @@ func TestBuild_Run(t *testing.T) {
} }
// Verify post-processor was run // Verify post-processor was run
pp := build.postProcessors[0][0].processor.(*TestPostProcessor) pp := build.postProcessors[0][0].processor.(*MockPostProcessor)
if !pp.ppCalled { if !pp.PostProcessCalled {
t.Fatal("should be called") t.Fatal("should be called")
} }
} }
...@@ -244,7 +244,7 @@ func TestBuild_Run_Artifacts(t *testing.T) { ...@@ -244,7 +244,7 @@ func TestBuild_Run_Artifacts(t *testing.T) {
build = testBuild() build = testBuild()
build.postProcessors = [][]coreBuildPostProcessor{ build.postProcessors = [][]coreBuildPostProcessor{
[]coreBuildPostProcessor{ []coreBuildPostProcessor{
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp"}, "pp", make(map[string]interface{}), false}, coreBuildPostProcessor{&MockPostProcessor{ArtifactId: "pp"}, "pp", make(map[string]interface{}), false},
}, },
} }
...@@ -269,10 +269,10 @@ func TestBuild_Run_Artifacts(t *testing.T) { ...@@ -269,10 +269,10 @@ func TestBuild_Run_Artifacts(t *testing.T) {
build = testBuild() build = testBuild()
build.postProcessors = [][]coreBuildPostProcessor{ build.postProcessors = [][]coreBuildPostProcessor{
[]coreBuildPostProcessor{ []coreBuildPostProcessor{
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp1"}, "pp", make(map[string]interface{}), false}, coreBuildPostProcessor{&MockPostProcessor{ArtifactId: "pp1"}, "pp", make(map[string]interface{}), false},
}, },
[]coreBuildPostProcessor{ []coreBuildPostProcessor{
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp2"}, "pp", make(map[string]interface{}), true}, coreBuildPostProcessor{&MockPostProcessor{ArtifactId: "pp2"}, "pp", make(map[string]interface{}), true},
}, },
} }
...@@ -297,12 +297,12 @@ func TestBuild_Run_Artifacts(t *testing.T) { ...@@ -297,12 +297,12 @@ func TestBuild_Run_Artifacts(t *testing.T) {
build = testBuild() build = testBuild()
build.postProcessors = [][]coreBuildPostProcessor{ build.postProcessors = [][]coreBuildPostProcessor{
[]coreBuildPostProcessor{ []coreBuildPostProcessor{
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp1a"}, "pp", make(map[string]interface{}), false}, coreBuildPostProcessor{&MockPostProcessor{ArtifactId: "pp1a"}, "pp", make(map[string]interface{}), false},
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp1b"}, "pp", make(map[string]interface{}), true}, coreBuildPostProcessor{&MockPostProcessor{ArtifactId: "pp1b"}, "pp", make(map[string]interface{}), true},
}, },
[]coreBuildPostProcessor{ []coreBuildPostProcessor{
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp2a"}, "pp", make(map[string]interface{}), false}, coreBuildPostProcessor{&MockPostProcessor{ArtifactId: "pp2a"}, "pp", make(map[string]interface{}), false},
coreBuildPostProcessor{&TestPostProcessor{artifactId: "pp2b"}, "pp", make(map[string]interface{}), false}, coreBuildPostProcessor{&MockPostProcessor{ArtifactId: "pp2b"}, "pp", make(map[string]interface{}), false},
}, },
} }
...@@ -328,7 +328,7 @@ func TestBuild_Run_Artifacts(t *testing.T) { ...@@ -328,7 +328,7 @@ func TestBuild_Run_Artifacts(t *testing.T) {
build.postProcessors = [][]coreBuildPostProcessor{ build.postProcessors = [][]coreBuildPostProcessor{
[]coreBuildPostProcessor{ []coreBuildPostProcessor{
coreBuildPostProcessor{ coreBuildPostProcessor{
&TestPostProcessor{artifactId: "pp", keep: true}, "pp", make(map[string]interface{}), false, &MockPostProcessor{ArtifactId: "pp", Keep: true}, "pp", make(map[string]interface{}), false,
}, },
}, },
} }
......
...@@ -161,13 +161,54 @@ func (c *Core) Build(n string) (Build, error) { ...@@ -161,13 +161,54 @@ func (c *Core) Build(n string) (Build, error) {
}) })
} }
// Setup the post-processors
postProcessors := make([][]coreBuildPostProcessor, 0, len(c.template.PostProcessors))
for _, rawPs := range c.template.PostProcessors {
current := make([]coreBuildPostProcessor, 0, len(rawPs))
for _, rawP := range rawPs {
// If we skip, ignore
if rawP.Skip(rawName) {
continue
}
// Get the post-processor
postProcessor, err := c.components.PostProcessor(rawP.Type)
if err != nil {
return nil, fmt.Errorf(
"error initializing post-processor '%s': %s",
rawP.Type, err)
}
if postProcessor == nil {
return nil, fmt.Errorf(
"post-processor type not found: %s", rawP.Type)
}
current = append(current, coreBuildPostProcessor{
processor: postProcessor,
processorType: rawP.Type,
config: rawP.Config,
keepInputArtifact: rawP.KeepInputArtifact,
})
}
// If we have no post-processors in this chain, just continue.
if len(current) == 0 {
continue
}
postProcessors = append(postProcessors, current)
}
// TODO hooks one day
return &coreBuild{ return &coreBuild{
name: n, name: n,
builder: builder, builder: builder,
builderConfig: configBuilder.Config, builderConfig: configBuilder.Config,
builderType: configBuilder.Type, builderType: configBuilder.Type,
provisioners: provisioners, postProcessors: postProcessors,
variables: c.variables, provisioners: provisioners,
variables: c.variables,
}, nil }, nil
} }
......
...@@ -222,6 +222,42 @@ func TestCoreBuild_provSkipInclude(t *testing.T) { ...@@ -222,6 +222,42 @@ func TestCoreBuild_provSkipInclude(t *testing.T) {
} }
} }
func TestCoreBuild_postProcess(t *testing.T) {
config := TestCoreConfig(t)
testCoreTemplate(t, config, fixtureDir("build-pp.json"))
b := TestBuilder(t, config, "test")
p := TestPostProcessor(t, config, "test")
core := TestCore(t, config)
ui := TestUi(t)
b.ArtifactId = "hello"
p.ArtifactId = "goodbye"
build, err := core.Build("test")
if err != nil {
t.Fatalf("err: %s", err)
}
if _, err := build.Prepare(); err != nil {
t.Fatalf("err: %s", err)
}
artifact, err := build.Run(ui, nil)
if err != nil {
t.Fatalf("err: %s", err)
}
if len(artifact) != 1 {
t.Fatalf("bad: %#v", artifact)
}
if artifact[0].Id() != p.ArtifactId {
t.Fatalf("bad: %s", artifact[0].Id())
}
if p.PostProcessArtifact.Id() != b.ArtifactId {
t.Fatalf("bad: %s", p.PostProcessArtifact.Id())
}
}
func TestCoreValidate(t *testing.T) { func TestCoreValidate(t *testing.T) {
cases := []struct { cases := []struct {
File string File string
...@@ -276,7 +312,7 @@ func TestCoreValidate(t *testing.T) { ...@@ -276,7 +312,7 @@ func TestCoreValidate(t *testing.T) {
func testComponentFinder() *ComponentFinder { func testComponentFinder() *ComponentFinder {
builderFactory := func(n string) (Builder, error) { return new(MockBuilder), nil } builderFactory := func(n string) (Builder, error) { return new(MockBuilder), nil }
ppFactory := func(n string) (PostProcessor, error) { return new(TestPostProcessor), nil } ppFactory := func(n string) (PostProcessor, error) { return new(MockPostProcessor), nil }
provFactory := func(n string) (Provisioner, error) { return new(MockProvisioner), nil } provFactory := func(n string) (Provisioner, error) { return new(MockProvisioner), nil }
return &ComponentFinder{ return &ComponentFinder{
Builder: builderFactory, Builder: builderFactory,
......
package packer
// MockPostProcessor is an implementation of PostProcessor that can be
// used for tests.
type MockPostProcessor struct {
ArtifactId string
Keep bool
Error error
ConfigureCalled bool
ConfigureConfigs []interface{}
ConfigureError error
PostProcessCalled bool
PostProcessArtifact Artifact
PostProcessUi Ui
}
func (t *MockPostProcessor) Configure(configs ...interface{}) error {
t.ConfigureCalled = true
t.ConfigureConfigs = configs
return t.ConfigureError
}
func (t *MockPostProcessor) PostProcess(ui Ui, a Artifact) (Artifact, bool, error) {
t.PostProcessCalled = true
t.PostProcessArtifact = a
t.PostProcessUi = ui
return &MockArtifact{
IdValue: t.ArtifactId,
}, t.Keep, t.Error
}
package packer
type TestPostProcessor struct {
artifactId string
keep bool
configCalled bool
configVal []interface{}
ppCalled bool
ppArtifact Artifact
ppUi Ui
}
func (pp *TestPostProcessor) Configure(v ...interface{}) error {
pp.configCalled = true
pp.configVal = v
return nil
}
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}, pp.keep, nil
}
...@@ -11,7 +11,7 @@ import ( ...@@ -11,7 +11,7 @@ import (
func testTemplateComponentFinder() *ComponentFinder { func testTemplateComponentFinder() *ComponentFinder {
builder := new(MockBuilder) builder := new(MockBuilder)
pp := new(TestPostProcessor) pp := new(MockPostProcessor)
provisioner := &MockProvisioner{} provisioner := &MockProvisioner{}
builderMap := map[string]Builder{ builderMap := map[string]Builder{
...@@ -1018,7 +1018,7 @@ func TestTemplate_Build(t *testing.T) { ...@@ -1018,7 +1018,7 @@ func TestTemplate_Build(t *testing.T) {
"test-prov": provisioner, "test-prov": provisioner,
} }
pp := new(TestPostProcessor) pp := new(MockPostProcessor)
ppMap := map[string]PostProcessor{ ppMap := map[string]PostProcessor{
"simple": pp, "simple": pp,
} }
......
{
"builders": [{
"type": "test"
}],
"post-processors": ["test"]
}
...@@ -8,14 +8,6 @@ import ( ...@@ -8,14 +8,6 @@ import (
) )
func TestCoreConfig(t *testing.T) *CoreConfig { func TestCoreConfig(t *testing.T) *CoreConfig {
// Create a UI that is effectively /dev/null everywhere
var buf bytes.Buffer
ui := &BasicUi{
Reader: &buf,
Writer: ioutil.Discard,
ErrorWriter: ioutil.Discard,
}
// Create some test components // Create some test components
components := ComponentFinder{ components := ComponentFinder{
Builder: func(n string) (Builder, error) { Builder: func(n string) (Builder, error) {
...@@ -30,7 +22,7 @@ func TestCoreConfig(t *testing.T) *CoreConfig { ...@@ -30,7 +22,7 @@ func TestCoreConfig(t *testing.T) *CoreConfig {
return &CoreConfig{ return &CoreConfig{
Cache: &FileCache{CacheDir: os.TempDir()}, Cache: &FileCache{CacheDir: os.TempDir()},
Components: components, Components: components,
Ui: ui, Ui: TestUi(t),
} }
} }
...@@ -43,6 +35,15 @@ func TestCore(t *testing.T, c *CoreConfig) *Core { ...@@ -43,6 +35,15 @@ func TestCore(t *testing.T, c *CoreConfig) *Core {
return core return core
} }
func TestUi(t *testing.T) Ui {
var buf bytes.Buffer
return &BasicUi{
Reader: &buf,
Writer: ioutil.Discard,
ErrorWriter: ioutil.Discard,
}
}
// TestBuilder sets the builder with the name n to the component finder // TestBuilder sets the builder with the name n to the component finder
// and returns the mock. // and returns the mock.
func TestBuilder(t *testing.T, c *CoreConfig, n string) *MockBuilder { func TestBuilder(t *testing.T, c *CoreConfig, n string) *MockBuilder {
...@@ -74,3 +75,19 @@ func TestProvisioner(t *testing.T, c *CoreConfig, n string) *MockProvisioner { ...@@ -74,3 +75,19 @@ func TestProvisioner(t *testing.T, c *CoreConfig, n string) *MockProvisioner {
return &b return &b
} }
// TestPostProcessor sets the prov. with the name n to the component finder
// and returns the mock.
func TestPostProcessor(t *testing.T, c *CoreConfig, n string) *MockPostProcessor {
var b MockPostProcessor
c.Components.PostProcessor = func(actual string) (PostProcessor, error) {
if actual != n {
return nil, nil
}
return &b, nil
}
return &b
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment