Commit 336051e3 authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

packer: builder prepare can return warnings

parent 24db112b
......@@ -38,8 +38,9 @@ type Build interface {
Name() string
// Prepare configures the various components of this build and reports
// any errors in doing so (such as syntax errors, validation errors, etc.)
Prepare(v map[string]string) error
// any errors in doing so (such as syntax errors, validation errors, etc.).
// It also reports any warnings.
Prepare(v map[string]string) ([]string, error)
// Run runs the actual builder, returning an artifact implementation
// of what is built. If anything goes wrong, an error is returned.
......@@ -115,7 +116,7 @@ func (b *coreBuild) Name() string {
// Prepare prepares the build by doing some initialization for the builder
// and any hooks. This _must_ be called prior to Run. The parameter is the
// overrides for the variables within the template (if any).
func (b *coreBuild) Prepare(userVars map[string]string) (err error) {
func (b *coreBuild) Prepare(userVars map[string]string) (warn []string, err error) {
b.l.Lock()
defer b.l.Unlock()
......@@ -154,7 +155,7 @@ func (b *coreBuild) Prepare(userVars map[string]string) (err error) {
// If there were any problem with variables, return an error right
// away because we can't be certain anything else will actually work.
if len(varErrs) > 0 {
return &MultiError{
return nil, &MultiError{
Errors: varErrs,
}
}
......@@ -168,7 +169,7 @@ func (b *coreBuild) Prepare(userVars map[string]string) (err error) {
}
// Prepare the builder
err = b.builder.Prepare(b.builderConfig, packerConfig)
warn, err = b.builder.Prepare(b.builderConfig, packerConfig)
if err != nil {
log.Printf("Build '%s' prepare failure: %s\n", b.name, err)
return
......
......@@ -8,7 +8,7 @@ import (
func testBuild() *coreBuild {
return &coreBuild{
name: "test",
builder: &TestBuilder{artifactId: "b"},
builder: &MockBuilder{ArtifactId: "b"},
builderConfig: 42,
builderType: "foo",
hooks: map[string][]Hook{
......@@ -26,10 +26,6 @@ func testBuild() *coreBuild {
}
}
func testBuilder() *TestBuilder {
return &TestBuilder{}
}
func testDefaultPackerConfig() map[string]interface{} {
return map[string]interface{}{
BuildNameConfigKey: "test",
......@@ -50,14 +46,14 @@ func TestBuild_Prepare(t *testing.T) {
packerConfig := testDefaultPackerConfig()
build := testBuild()
builder := build.builder.(*TestBuilder)
builder := build.builder.(*MockBuilder)
build.Prepare(nil)
if !builder.prepareCalled {
if !builder.PrepareCalled {
t.Fatal("should be called")
}
if !reflect.DeepEqual(builder.prepareConfig, []interface{}{42, packerConfig}) {
t.Fatalf("bad: %#v", builder.prepareConfig)
if !reflect.DeepEqual(builder.PrepareConfig, []interface{}{42, packerConfig}) {
t.Fatalf("bad: %#v", builder.PrepareConfig)
}
coreProv := build.provisioners[0]
......@@ -81,7 +77,11 @@ func TestBuild_Prepare(t *testing.T) {
func TestBuild_Prepare_Twice(t *testing.T) {
build := testBuild()
if err := build.Prepare(nil); err != nil {
warn, err := build.Prepare(nil)
if len(warn) > 0 {
t.Fatalf("bad: %#v", warn)
}
if err != nil {
t.Fatalf("bad error: %s", err)
}
......@@ -99,20 +99,36 @@ func TestBuild_Prepare_Twice(t *testing.T) {
build.Prepare(nil)
}
func TestBuildPrepare_BuilderWarniings(t *testing.T) {
expected := []string{"foo"}
build := testBuild()
builder := build.builder.(*MockBuilder)
builder.PrepareWarnings = expected
warn, err := build.Prepare(nil)
if err != nil {
t.Fatalf("err: %s", err)
}
if !reflect.DeepEqual(warn, expected) {
t.Fatalf("bad: %#v", warn)
}
}
func TestBuild_Prepare_Debug(t *testing.T) {
packerConfig := testDefaultPackerConfig()
packerConfig[DebugConfigKey] = true
build := testBuild()
builder := build.builder.(*TestBuilder)
builder := build.builder.(*MockBuilder)
build.SetDebug(true)
build.Prepare(nil)
if !builder.prepareCalled {
if !builder.PrepareCalled {
t.Fatalf("should be called")
}
if !reflect.DeepEqual(builder.prepareConfig, []interface{}{42, packerConfig}) {
t.Fatalf("bad: %#v", builder.prepareConfig)
if !reflect.DeepEqual(builder.PrepareConfig, []interface{}{42, packerConfig}) {
t.Fatalf("bad: %#v", builder.PrepareConfig)
}
coreProv := build.provisioners[0]
......@@ -133,19 +149,22 @@ func TestBuildPrepare_variables_default(t *testing.T) {
build := testBuild()
build.variables["foo"] = coreBuildVariable{Default: "bar"}
builder := build.builder.(*TestBuilder)
builder := build.builder.(*MockBuilder)
err := build.Prepare(nil)
warn, err := build.Prepare(nil)
if len(warn) > 0 {
t.Fatalf("bad: %#v", warn)
}
if err != nil {
t.Fatalf("err: %s", err)
}
if !builder.prepareCalled {
if !builder.PrepareCalled {
t.Fatal("prepare should be called")
}
if !reflect.DeepEqual(builder.prepareConfig[1], packerConfig) {
t.Fatalf("prepare bad: %#v", builder.prepareConfig[1])
if !reflect.DeepEqual(builder.PrepareConfig[1], packerConfig) {
t.Fatalf("prepare bad: %#v", builder.PrepareConfig[1])
}
}
......@@ -153,7 +172,10 @@ func TestBuildPrepare_variables_nonexist(t *testing.T) {
build := testBuild()
build.variables["foo"] = coreBuildVariable{Default: "bar"}
err := build.Prepare(map[string]string{"bar": "baz"})
warn, err := build.Prepare(map[string]string{"bar": "baz"})
if len(warn) > 0 {
t.Fatalf("bad: %#v", warn)
}
if err == nil {
t.Fatal("should have had error")
}
......@@ -167,19 +189,22 @@ func TestBuildPrepare_variables_override(t *testing.T) {
build := testBuild()
build.variables["foo"] = coreBuildVariable{Default: "bar"}
builder := build.builder.(*TestBuilder)
builder := build.builder.(*MockBuilder)
err := build.Prepare(map[string]string{"foo": "baz"})
warn, err := build.Prepare(map[string]string{"foo": "baz"})
if len(warn) > 0 {
t.Fatalf("bad: %#v", warn)
}
if err != nil {
t.Fatalf("err: %s", err)
}
if !builder.prepareCalled {
if !builder.PrepareCalled {
t.Fatal("prepare should be called")
}
if !reflect.DeepEqual(builder.prepareConfig[1], packerConfig) {
t.Fatalf("prepare bad: %#v", builder.prepareConfig[1])
if !reflect.DeepEqual(builder.PrepareConfig[1], packerConfig) {
t.Fatalf("prepare bad: %#v", builder.PrepareConfig[1])
}
}
......@@ -187,7 +212,10 @@ func TestBuildPrepare_variablesRequired(t *testing.T) {
build := testBuild()
build.variables["foo"] = coreBuildVariable{Required: true}
err := build.Prepare(map[string]string{})
warn, err := build.Prepare(map[string]string{})
if len(warn) > 0 {
t.Fatalf("bad: %#v", warn)
}
if err == nil {
t.Fatal("should have had error")
}
......@@ -195,7 +223,10 @@ func TestBuildPrepare_variablesRequired(t *testing.T) {
// Test with setting the value
build = testBuild()
build.variables["foo"] = coreBuildVariable{Required: true}
err = build.Prepare(map[string]string{"foo": ""})
warn, err = build.Prepare(map[string]string{"foo": ""})
if len(warn) > 0 {
t.Fatalf("bad: %#v", warn)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
......@@ -216,13 +247,13 @@ func TestBuild_Run(t *testing.T) {
}
// Verify builder was run
builder := build.builder.(*TestBuilder)
if !builder.runCalled {
builder := build.builder.(*MockBuilder)
if !builder.RunCalled {
t.Fatal("should be called")
}
// Verify hooks are disapatchable
dispatchHook := builder.runHook
dispatchHook := builder.RunHook
dispatchHook.Run("foo", nil, nil, 42)
hook := build.hooks["foo"][0].(*MockHook)
......@@ -402,8 +433,8 @@ func TestBuild_Cancel(t *testing.T) {
build := testBuild()
build.Cancel()
builder := build.builder.(*TestBuilder)
if !builder.cancelCalled {
builder := build.builder.(*MockBuilder)
if !builder.CancelCalled {
t.Fatal("cancel should be called")
}
}
......@@ -22,7 +22,10 @@ type Builder interface {
//
// Each of the configuration values should merge into the final
// configuration.
Prepare(...interface{}) error
//
// Prepare should return a list of warnings along with any errors
// that occured while preparing.
Prepare(...interface{}) ([]string, error)
// Run is where the actual build should take place. It takes a Build and a Ui.
Run(ui Ui, hook Hook, cache Cache) (Artifact, error)
......
......@@ -4,7 +4,8 @@ package packer
// You can set some fake return values and you can keep track of what
// methods were called on the builder. It is fairly basic.
type MockBuilder struct {
ArtifactId string
ArtifactId string
PrepareWarnings []string
PrepareCalled bool
PrepareConfig []interface{}
......@@ -15,10 +16,10 @@ type MockBuilder struct {
CancelCalled bool
}
func (tb *MockBuilder) Prepare(config ...interface{}) error {
func (tb *MockBuilder) Prepare(config ...interface{}) ([]string, error) {
tb.PrepareCalled = true
tb.PrepareConfig = config
return nil
return tb.PrepareWarnings, nil
}
func (tb *MockBuilder) Run(ui Ui, h Hook, c Cache) (Artifact, error) {
......
package packer
type TestBuilder struct {
artifactId string
prepareCalled bool
prepareConfig []interface{}
runCalled bool
runCache Cache
runHook Hook
runUi Ui
cancelCalled bool
}
func (tb *TestBuilder) Prepare(config ...interface{}) error {
tb.prepareCalled = true
tb.prepareConfig = config
return nil
}
func (tb *TestBuilder) Run(ui Ui, h Hook, c Cache) (Artifact, error) {
tb.runCalled = true
tb.runHook = h
tb.runUi = ui
tb.runCache = c
return &TestArtifact{id: tb.artifactId}, nil
}
func (tb *TestBuilder) Cancel() {
tb.cancelCalled = true
}
......@@ -17,7 +17,7 @@ func init() {
}
func testComponentFinder() *ComponentFinder {
builderFactory := func(n string) (Builder, error) { return testBuilder(), nil }
builderFactory := func(n string) (Builder, error) { return new(MockBuilder), nil }
ppFactory := func(n string) (PostProcessor, error) { return new(TestPostProcessor), nil }
provFactory := func(n string) (Provisioner, error) { return new(MockProvisioner), nil }
return &ComponentFinder{
......@@ -97,7 +97,7 @@ func TestEnvironment_NilComponents(t *testing.T) {
}
func TestEnvironment_Builder(t *testing.T) {
builder := &TestBuilder{}
builder := &MockBuilder{}
builders := make(map[string]Builder)
builders["foo"] = builder
......
......@@ -9,7 +9,7 @@ import (
)
func testTemplateComponentFinder() *ComponentFinder {
builder := testBuilder()
builder := new(MockBuilder)
pp := new(TestPostProcessor)
provisioner := &MockProvisioner{}
......@@ -706,7 +706,7 @@ func TestTemplate_Build(t *testing.T) {
t.Fatalf("err: %s", err)
}
builder := testBuilder()
builder := new(MockBuilder)
builderMap := map[string]Builder{
"test-builder": builder,
}
......@@ -1194,7 +1194,7 @@ func TestTemplate_Build_ProvisionerOverride(t *testing.T) {
t.Fatalf("bad raw: %#v", RawConfig)
}
builder := testBuilder()
builder := new(MockBuilder)
builderMap := map[string]Builder{
"test-builder": builder,
}
......
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