Merge branch 'f-builder-warnings'

This commit is contained in:
Mitchell Hashimoto 2013-11-02 23:23:39 -05:00
commit 80aa1eea56
31 changed files with 1015 additions and 401 deletions

View File

@ -45,15 +45,15 @@ type Builder struct {
runner multistep.Runner
}
func (b *Builder) Prepare(raws ...interface{}) error {
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
md, err := common.DecodeConfig(&b.config, raws...)
if err != nil {
return err
return nil, err
}
b.config.tpl, err = packer.NewConfigTemplate()
if err != nil {
return err
return nil, err
}
b.config.tpl.UserVars = b.config.PackerUserVars
b.config.tpl.Funcs(awscommon.TemplateFuncs)
@ -140,11 +140,11 @@ func (b *Builder) Prepare(raws ...interface{}) error {
}
if errs != nil && len(errs.Errors) > 0 {
return errs
return nil, errs
}
log.Println(common.ScrubConfig(b.config, b.config.AccessKey, b.config.SecretKey))
return nil
return nil, nil
}
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {

View File

@ -26,7 +26,10 @@ func TestBuilderPrepare_AMIName(t *testing.T) {
// Test good
config["ami_name"] = "foo"
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -34,7 +37,10 @@ func TestBuilderPrepare_AMIName(t *testing.T) {
// Test bad
config["ami_name"] = "foo {{"
b = Builder{}
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatal("should have error")
}
@ -42,7 +48,10 @@ func TestBuilderPrepare_AMIName(t *testing.T) {
// Test bad
delete(config, "ami_name")
b = Builder{}
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatal("should have error")
}
@ -53,7 +62,10 @@ func TestBuilderPrepare_ChrootMounts(t *testing.T) {
config := testConfig()
config["chroot_mounts"] = nil
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Errorf("err: %s", err)
}
@ -61,7 +73,10 @@ func TestBuilderPrepare_ChrootMounts(t *testing.T) {
config["chroot_mounts"] = [][]string{
[]string{"bad"},
}
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatal("should have error")
}
@ -71,13 +86,19 @@ func TestBuilderPrepare_SourceAmi(t *testing.T) {
config := testConfig()
config["source_ami"] = ""
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatal("should have error")
}
config["source_ami"] = "foo"
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Errorf("err: %s", err)
}
@ -88,7 +109,10 @@ func TestBuilderPrepare_CommandWrapper(t *testing.T) {
config := testConfig()
config["command_wrapper"] = "echo hi; {{.Command}}"
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Errorf("err: %s", err)
}

View File

@ -33,15 +33,15 @@ type Builder struct {
runner multistep.Runner
}
func (b *Builder) Prepare(raws ...interface{}) error {
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
md, err := common.DecodeConfig(&b.config, raws...)
if err != nil {
return err
return nil, err
}
b.config.tpl, err = packer.NewConfigTemplate()
if err != nil {
return err
return nil, err
}
b.config.tpl.UserVars = b.config.PackerUserVars
b.config.tpl.Funcs(awscommon.TemplateFuncs)
@ -53,11 +53,11 @@ func (b *Builder) Prepare(raws ...interface{}) error {
errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(b.config.tpl)...)
if errs != nil && len(errs.Errors) > 0 {
return errs
return nil, errs
}
log.Println(common.ScrubConfig(b.config, b.config.AccessKey, b.config.SecretKey))
return nil
return nil, nil
}
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {

View File

@ -31,7 +31,10 @@ func TestBuilder_Prepare_BadType(t *testing.T) {
"access_key": []string{},
}
err := b.Prepare(c)
warnings, err := b.Prepare(c)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatalf("prepare should fail")
}
@ -43,7 +46,10 @@ func TestBuilderPrepare_AMIName(t *testing.T) {
// Test good
config["ami_name"] = "foo"
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -51,7 +57,10 @@ func TestBuilderPrepare_AMIName(t *testing.T) {
// Test bad
config["ami_name"] = "foo {{"
b = Builder{}
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatal("should have error")
}
@ -59,7 +68,10 @@ func TestBuilderPrepare_AMIName(t *testing.T) {
// Test bad
delete(config, "ami_name")
b = Builder{}
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatal("should have error")
}
@ -71,7 +83,10 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) {
// Add a random key
config["i_should_not_be_valid"] = true
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatal("should have error")
}

View File

@ -45,15 +45,15 @@ type Builder struct {
runner multistep.Runner
}
func (b *Builder) Prepare(raws ...interface{}) error {
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
md, err := common.DecodeConfig(&b.config, raws...)
if err != nil {
return err
return nil, err
}
b.config.tpl, err = packer.NewConfigTemplate()
if err != nil {
return err
return nil, err
}
b.config.tpl.UserVars = b.config.PackerUserVars
b.config.tpl.Funcs(awscommon.TemplateFuncs)
@ -156,11 +156,11 @@ func (b *Builder) Prepare(raws ...interface{}) error {
}
if errs != nil && len(errs.Errors) > 0 {
return errs
return nil, errs
}
log.Println(common.ScrubConfig(b.config, b.config.AccessKey, b.config.SecretKey))
return nil
return nil, nil
}
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {

View File

@ -40,19 +40,28 @@ func TestBuilderPrepare_AccountId(t *testing.T) {
config := testConfig()
config["account_id"] = ""
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatal("should have error")
}
config["account_id"] = "foo"
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Errorf("err: %s", err)
}
config["account_id"] = "0123-0456-7890"
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("err: %s", err)
}
@ -68,7 +77,10 @@ func TestBuilderPrepare_AMIName(t *testing.T) {
// Test good
config["ami_name"] = "foo"
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -76,7 +88,10 @@ func TestBuilderPrepare_AMIName(t *testing.T) {
// Test bad
config["ami_name"] = "foo {{"
b = Builder{}
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatal("should have error")
}
@ -84,7 +99,10 @@ func TestBuilderPrepare_AMIName(t *testing.T) {
// Test bad
delete(config, "ami_name")
b = Builder{}
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatal("should have error")
}
@ -95,7 +113,10 @@ func TestBuilderPrepare_BundleDestination(t *testing.T) {
config := testConfig()
config["bundle_destination"] = ""
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("err: %s", err)
}
@ -110,7 +131,10 @@ func TestBuilderPrepare_BundlePrefix(t *testing.T) {
config := testConfig()
config["bundle_prefix"] = ""
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("err: %s", err)
}
@ -126,7 +150,10 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) {
// Add a random key
config["i_should_not_be_valid"] = true
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatal("should have error")
}
@ -137,13 +164,19 @@ func TestBuilderPrepare_S3Bucket(t *testing.T) {
config := testConfig()
config["s3_bucket"] = ""
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatal("should have error")
}
config["s3_bucket"] = "foo"
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Errorf("err: %s", err)
}
@ -154,13 +187,19 @@ func TestBuilderPrepare_X509CertPath(t *testing.T) {
config := testConfig()
config["x509_cert_path"] = ""
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatal("should have error")
}
config["x509_cert_path"] = "i/am/a/file/that/doesnt/exist"
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Error("should have error")
}
@ -172,7 +211,10 @@ func TestBuilderPrepare_X509CertPath(t *testing.T) {
defer os.Remove(tf.Name())
config["x509_cert_path"] = tf.Name()
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -183,13 +225,19 @@ func TestBuilderPrepare_X509KeyPath(t *testing.T) {
config := testConfig()
config["x509_key_path"] = ""
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatal("should have error")
}
config["x509_key_path"] = "i/am/a/file/that/doesnt/exist"
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Error("should have error")
}
@ -201,7 +249,10 @@ func TestBuilderPrepare_X509KeyPath(t *testing.T) {
defer os.Remove(tf.Name())
config["x509_key_path"] = tf.Name()
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -212,7 +263,10 @@ func TestBuilderPrepare_X509UploadPath(t *testing.T) {
config := testConfig()
config["x509_upload_path"] = ""
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}

View File

@ -49,15 +49,15 @@ type Builder struct {
runner multistep.Runner
}
func (b *Builder) Prepare(raws ...interface{}) error {
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
md, err := common.DecodeConfig(&b.config, raws...)
if err != nil {
return err
return nil, err
}
b.config.tpl, err = packer.NewConfigTemplate()
if err != nil {
return err
return nil, err
}
b.config.tpl.UserVars = b.config.PackerUserVars
@ -161,11 +161,11 @@ func (b *Builder) Prepare(raws ...interface{}) error {
b.config.stateTimeout = stateTimeout
if errs != nil && len(errs.Errors) > 0 {
return errs
return nil, errs
}
common.ScrubConfig(b.config, b.config.ClientID, b.config.APIKey)
return nil
return nil, nil
}
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {

View File

@ -34,7 +34,10 @@ func TestBuilder_Prepare_BadType(t *testing.T) {
"api_key": []string{},
}
err := b.Prepare(c)
warnings, err := b.Prepare(c)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatalf("prepare should fail")
}
@ -46,7 +49,10 @@ func TestBuilderPrepare_APIKey(t *testing.T) {
// Test good
config["api_key"] = "foo"
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -58,7 +64,10 @@ func TestBuilderPrepare_APIKey(t *testing.T) {
// Test bad
delete(config, "api_key")
b = Builder{}
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatal("should have error")
}
@ -67,7 +76,10 @@ func TestBuilderPrepare_APIKey(t *testing.T) {
delete(config, "api_key")
os.Setenv("DIGITALOCEAN_API_KEY", "foo")
defer os.Setenv("DIGITALOCEAN_API_KEY", "")
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -79,7 +91,10 @@ func TestBuilderPrepare_ClientID(t *testing.T) {
// Test good
config["client_id"] = "foo"
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -91,7 +106,10 @@ func TestBuilderPrepare_ClientID(t *testing.T) {
// Test bad
delete(config, "client_id")
b = Builder{}
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatal("should have error")
}
@ -100,7 +118,10 @@ func TestBuilderPrepare_ClientID(t *testing.T) {
delete(config, "client_id")
os.Setenv("DIGITALOCEAN_CLIENT_ID", "foo")
defer os.Setenv("DIGITALOCEAN_CLIENT_ID", "")
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -112,7 +133,10 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) {
// Add a random key
config["i_should_not_be_valid"] = true
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatal("should have error")
}
@ -123,7 +147,10 @@ func TestBuilderPrepare_RegionID(t *testing.T) {
config := testConfig()
// Test default
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -135,7 +162,10 @@ func TestBuilderPrepare_RegionID(t *testing.T) {
// Test set
config["region_id"] = 2
b = Builder{}
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -150,7 +180,10 @@ func TestBuilderPrepare_SizeID(t *testing.T) {
config := testConfig()
// Test default
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -162,7 +195,10 @@ func TestBuilderPrepare_SizeID(t *testing.T) {
// Test set
config["size_id"] = 67
b = Builder{}
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -177,7 +213,10 @@ func TestBuilderPrepare_ImageID(t *testing.T) {
config := testConfig()
// Test default
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -189,7 +228,10 @@ func TestBuilderPrepare_ImageID(t *testing.T) {
// Test set
config["size_id"] = 2
b = Builder{}
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -204,7 +246,10 @@ func TestBuilderPrepare_SSHUsername(t *testing.T) {
config := testConfig()
// Test default
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -216,7 +261,10 @@ func TestBuilderPrepare_SSHUsername(t *testing.T) {
// Test set
config["ssh_username"] = "foo"
b = Builder{}
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -231,7 +279,10 @@ func TestBuilderPrepare_SSHTimeout(t *testing.T) {
config := testConfig()
// Test default
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -243,7 +294,10 @@ func TestBuilderPrepare_SSHTimeout(t *testing.T) {
// Test set
config["ssh_timeout"] = "30s"
b = Builder{}
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -251,7 +305,10 @@ func TestBuilderPrepare_SSHTimeout(t *testing.T) {
// Test bad
config["ssh_timeout"] = "tubes"
b = Builder{}
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatal("should have error")
}
@ -263,7 +320,10 @@ func TestBuilderPrepare_StateTimeout(t *testing.T) {
config := testConfig()
// Test default
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -275,7 +335,10 @@ func TestBuilderPrepare_StateTimeout(t *testing.T) {
// Test set
config["state_timeout"] = "5m"
b = Builder{}
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -283,7 +346,10 @@ func TestBuilderPrepare_StateTimeout(t *testing.T) {
// Test bad
config["state_timeout"] = "tubes"
b = Builder{}
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatal("should have error")
}
@ -295,7 +361,10 @@ func TestBuilderPrepare_SnapshotName(t *testing.T) {
config := testConfig()
// Test default
err := b.Prepare(config)
warnings, err := b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -307,7 +376,10 @@ func TestBuilderPrepare_SnapshotName(t *testing.T) {
// Test set
config["snapshot_name"] = "foobarbaz"
b = Builder{}
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -315,7 +387,10 @@ func TestBuilderPrepare_SnapshotName(t *testing.T) {
// Test set with template
config["snapshot_name"] = "{{timestamp}}"
b = Builder{}
err = b.Prepare(config)
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}

View File

@ -29,15 +29,15 @@ type Builder struct {
runner multistep.Runner
}
func (b *Builder) Prepare(raws ...interface{}) error {
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
md, err := common.DecodeConfig(&b.config, raws...)
if err != nil {
return err
return nil, err
}
b.config.tpl, err = packer.NewConfigTemplate()
if err != nil {
return err
return nil, err
}
b.config.tpl.UserVars = b.config.PackerUserVars
@ -48,11 +48,11 @@ func (b *Builder) Prepare(raws ...interface{}) error {
errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(b.config.tpl)...)
if errs != nil && len(errs.Errors) > 0 {
return errs
return nil, errs
}
log.Println(common.ScrubConfig(b.config, b.config.Password))
return nil
return nil, nil
}
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {

View File

@ -32,7 +32,10 @@ func TestBuilder_Prepare_BadType(t *testing.T) {
"password": []string{},
}
err := b.Prepare(c)
warns, err := b.Prepare(c)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatalf("prepare should fail")
}
@ -44,7 +47,10 @@ func TestBuilderPrepare_ImageName(t *testing.T) {
// Test good
config["image_name"] = "foo"
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -52,7 +58,10 @@ func TestBuilderPrepare_ImageName(t *testing.T) {
// Test bad
config["image_name"] = "foo {{"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -60,7 +69,10 @@ func TestBuilderPrepare_ImageName(t *testing.T) {
// Test bad
delete(config, "image_name")
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -72,7 +84,10 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) {
// Add a random key
config["i_should_not_be_valid"] = true
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}

View File

@ -72,20 +72,21 @@ type config struct {
tpl *packer.ConfigTemplate
}
func (b *Builder) Prepare(raws ...interface{}) error {
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
md, err := common.DecodeConfig(&b.config, raws...)
if err != nil {
return err
return nil, err
}
b.config.tpl, err = packer.NewConfigTemplate()
if err != nil {
return err
return nil, err
}
b.config.tpl.UserVars = b.config.PackerUserVars
// Accumulate any errors
// Accumulate any errors and warnings
errs := common.CheckUnusedConfig(md)
warnings := make([]string, 0)
if b.config.DiskSize == 0 {
b.config.DiskSize = 40000
@ -363,11 +364,18 @@ func (b *Builder) Prepare(raws ...interface{}) error {
}
}
if errs != nil && len(errs.Errors) > 0 {
return errs
// Warnings
if b.config.ShutdownCommand == "" {
warnings = append(warnings,
"A shutdown_command was not specified. Without a shutdown command, Packer\n"+
"will forcibly halt the virtual machine, which may result in data loss.")
}
return nil
if errs != nil && len(errs.Errors) > 0 {
return warnings, errs
}
return warnings, nil
}
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {

View File

@ -43,6 +43,7 @@ func testConfig() map[string]interface{} {
"iso_checksum": "foo",
"iso_checksum_type": "md5",
"iso_url": "http://www.google.com/",
"shutdown_command": "yes",
"ssh_username": "foo",
packer.BuildNameConfigKey: "foo",
@ -60,7 +61,10 @@ func TestBuilder_ImplementsBuilder(t *testing.T) {
func TestBuilderPrepare_Defaults(t *testing.T) {
var b Builder
config := testConfig()
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -104,7 +108,10 @@ func TestBuilderPrepare_BootWait(t *testing.T) {
// Test a default boot_wait
delete(config, "boot_wait")
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("err: %s", err)
}
@ -115,7 +122,10 @@ func TestBuilderPrepare_BootWait(t *testing.T) {
// Test with a bad boot_wait
config["boot_wait"] = "this is not good"
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -123,7 +133,10 @@ func TestBuilderPrepare_BootWait(t *testing.T) {
// Test with a good one
config["boot_wait"] = "5s"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -134,7 +147,10 @@ func TestBuilderPrepare_DiskSize(t *testing.T) {
config := testConfig()
delete(config, "disk_size")
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("bad err: %s", err)
}
@ -145,7 +161,10 @@ func TestBuilderPrepare_DiskSize(t *testing.T) {
config["disk_size"] = 60000
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -160,7 +179,10 @@ func TestBuilderPrepare_FloppyFiles(t *testing.T) {
config := testConfig()
delete(config, "floppy_files")
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("bad err: %s", err)
}
@ -171,7 +193,10 @@ func TestBuilderPrepare_FloppyFiles(t *testing.T) {
config["floppy_files"] = []string{"foo", "bar"}
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -188,7 +213,10 @@ func TestBuilderPrepare_GuestAdditionsMode(t *testing.T) {
// test default mode
delete(config, "guest_additions_mode")
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("bad err: %s", err)
}
@ -196,7 +224,10 @@ func TestBuilderPrepare_GuestAdditionsMode(t *testing.T) {
// Test another mode
config["guest_additions_mode"] = "attach"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -208,7 +239,10 @@ func TestBuilderPrepare_GuestAdditionsMode(t *testing.T) {
// Test bad mode
config["guest_additions_mode"] = "teleport"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should error")
}
@ -219,7 +253,10 @@ func TestBuilderPrepare_GuestAdditionsPath(t *testing.T) {
config := testConfig()
delete(config, "guest_additions_path")
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("bad err: %s", err)
}
@ -230,7 +267,10 @@ func TestBuilderPrepare_GuestAdditionsPath(t *testing.T) {
config["guest_additions_path"] = "foo"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -245,7 +285,10 @@ func TestBuilderPrepare_GuestAdditionsSHA256(t *testing.T) {
config := testConfig()
delete(config, "guest_additions_sha256")
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("bad err: %s", err)
}
@ -256,7 +299,10 @@ func TestBuilderPrepare_GuestAdditionsSHA256(t *testing.T) {
config["guest_additions_sha256"] = "FOO"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -271,7 +317,10 @@ func TestBuilderPrepare_GuestAdditionsURL(t *testing.T) {
config := testConfig()
config["guest_additions_url"] = ""
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("err: %s", err)
}
@ -282,7 +331,10 @@ func TestBuilderPrepare_GuestAdditionsURL(t *testing.T) {
config["guest_additions_url"] = "http://www.packer.io"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Errorf("should not have error: %s", err)
}
@ -294,7 +346,10 @@ func TestBuilderPrepare_HardDriveInterface(t *testing.T) {
// Test a default boot_wait
delete(config, "hard_drive_interface")
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("err: %s", err)
}
@ -306,7 +361,10 @@ func TestBuilderPrepare_HardDriveInterface(t *testing.T) {
// Test with a bad
config["hard_drive_interface"] = "fake"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -314,7 +372,10 @@ func TestBuilderPrepare_HardDriveInterface(t *testing.T) {
// Test with a good
config["hard_drive_interface"] = "sata"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -327,7 +388,10 @@ func TestBuilderPrepare_HTTPPort(t *testing.T) {
// Bad
config["http_port_min"] = 1000
config["http_port_max"] = 500
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -335,7 +399,10 @@ func TestBuilderPrepare_HTTPPort(t *testing.T) {
// Bad
config["http_port_min"] = -500
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -344,7 +411,10 @@ func TestBuilderPrepare_HTTPPort(t *testing.T) {
config["http_port_min"] = 500
config["http_port_max"] = 1000
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -356,7 +426,10 @@ func TestBuilderPrepare_Format(t *testing.T) {
// Bad
config["format"] = "illegal value"
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -364,7 +437,10 @@ func TestBuilderPrepare_Format(t *testing.T) {
// Good
config["format"] = "ova"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -372,7 +448,10 @@ func TestBuilderPrepare_Format(t *testing.T) {
// Good
config["format"] = "ovf"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -384,7 +463,10 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) {
// Add a random key
config["i_should_not_be_valid"] = true
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -396,7 +478,10 @@ func TestBuilderPrepare_ISOChecksum(t *testing.T) {
// Test bad
config["iso_checksum"] = ""
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -404,7 +489,10 @@ func TestBuilderPrepare_ISOChecksum(t *testing.T) {
// Test good
config["iso_checksum"] = "FOo"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -420,7 +508,10 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) {
// Test bad
config["iso_checksum_type"] = ""
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -428,7 +519,10 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) {
// Test good
config["iso_checksum_type"] = "mD5"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -440,7 +534,10 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) {
// Test unknown
config["iso_checksum_type"] = "fake"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -455,7 +552,10 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) {
// Test both epty
config["iso_url"] = ""
b = Builder{}
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -463,7 +563,10 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) {
// Test iso_url set
config["iso_url"] = "http://www.packer.io"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Errorf("should not have error: %s", err)
}
@ -477,7 +580,10 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) {
config["iso_url"] = "http://www.packer.io"
config["iso_urls"] = []string{"http://www.packer.io"}
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -490,7 +596,10 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) {
}
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Errorf("should not have error: %s", err)
}
@ -517,7 +626,10 @@ func TestBuilderPrepare_OutputDir(t *testing.T) {
config["output_directory"] = dir
b = Builder{}
err = b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -525,19 +637,40 @@ func TestBuilderPrepare_OutputDir(t *testing.T) {
// Test with a good one
config["output_directory"] = "i-hope-i-dont-exist"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
}
func TestBuilderPrepare_ShutdownCommand(t *testing.T) {
var b Builder
config := testConfig()
delete(config, "shutdown_command")
warns, err := b.Prepare(config)
if err != nil {
t.Fatalf("bad: %s", err)
}
if len(warns) != 1 {
t.Fatalf("bad: %#v", warns)
}
}
func TestBuilderPrepare_ShutdownTimeout(t *testing.T) {
var b Builder
config := testConfig()
// Test with a bad value
config["shutdown_timeout"] = "this is not good"
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -545,7 +678,10 @@ func TestBuilderPrepare_ShutdownTimeout(t *testing.T) {
// Test with a good one
config["shutdown_timeout"] = "5s"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -559,7 +695,10 @@ func TestBuilderPrepare_SSHHostPort(t *testing.T) {
config["ssh_host_port_min"] = 1000
config["ssh_host_port_max"] = 500
b = Builder{}
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -567,7 +706,10 @@ func TestBuilderPrepare_SSHHostPort(t *testing.T) {
// Bad
config["ssh_host_port_min"] = -500
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -576,7 +718,10 @@ func TestBuilderPrepare_SSHHostPort(t *testing.T) {
config["ssh_host_port_min"] = 500
config["ssh_host_port_max"] = 1000
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -588,14 +733,20 @@ func TestBuilderPrepare_sshKeyPath(t *testing.T) {
config["ssh_key_path"] = ""
b = Builder{}
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
config["ssh_key_path"] = "/i/dont/exist"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -614,7 +765,10 @@ func TestBuilderPrepare_sshKeyPath(t *testing.T) {
config["ssh_key_path"] = tf.Name()
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -625,7 +779,10 @@ func TestBuilderPrepare_sshKeyPath(t *testing.T) {
tf.Write([]byte(testPem))
config["ssh_key_path"] = tf.Name()
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("err: %s", err)
}
@ -637,14 +794,20 @@ func TestBuilderPrepare_SSHUser(t *testing.T) {
config["ssh_username"] = ""
b = Builder{}
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
config["ssh_username"] = "exists"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -656,7 +819,10 @@ func TestBuilderPrepare_SSHWaitTimeout(t *testing.T) {
// Test a default boot_wait
delete(config, "ssh_wait_timeout")
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("err: %s", err)
}
@ -668,7 +834,10 @@ func TestBuilderPrepare_SSHWaitTimeout(t *testing.T) {
// Test with a bad value
config["ssh_wait_timeout"] = "this is not good"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -676,7 +845,10 @@ func TestBuilderPrepare_SSHWaitTimeout(t *testing.T) {
// Test with a good one
config["ssh_wait_timeout"] = "5s"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -688,7 +860,10 @@ func TestBuilderPrepare_VBoxManage(t *testing.T) {
// Test with empty
delete(config, "vboxmanage")
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("err: %s", err)
}
@ -703,7 +878,10 @@ func TestBuilderPrepare_VBoxManage(t *testing.T) {
}
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -723,7 +901,10 @@ func TestBuilderPrepare_VBoxVersionFile(t *testing.T) {
// Test empty
delete(config, "virtualbox_version_file")
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("err: %s", err)
}
@ -735,7 +916,10 @@ func TestBuilderPrepare_VBoxVersionFile(t *testing.T) {
// Test with a good one
config["virtualbox_version_file"] = "foo"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}

View File

@ -66,20 +66,21 @@ type config struct {
tpl *packer.ConfigTemplate
}
func (b *Builder) Prepare(raws ...interface{}) error {
func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
md, err := common.DecodeConfig(&b.config, raws...)
if err != nil {
return err
return nil, err
}
b.config.tpl, err = packer.NewConfigTemplate()
if err != nil {
return err
return nil, err
}
b.config.tpl.UserVars = b.config.PackerUserVars
// Accumulate any errors
errs := common.CheckUnusedConfig(md)
warnings := make([]string, 0)
if b.config.DiskName == "" {
b.config.DiskName = "disk"
@ -326,11 +327,18 @@ func (b *Builder) Prepare(raws ...interface{}) error {
errs, fmt.Errorf("vnc_port_min must be less than vnc_port_max"))
}
if errs != nil && len(errs.Errors) > 0 {
return errs
// Warnings
if b.config.ShutdownCommand == "" {
warnings = append(warnings,
"A shutdown_command was not specified. Without a shutdown command, Packer\n"+
"will forcibly halt the virtual machine, which may result in data loss.")
}
return nil
if errs != nil && len(errs.Errors) > 0 {
return warnings, errs
}
return warnings, nil
}
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {

View File

@ -44,6 +44,7 @@ func testConfig() map[string]interface{} {
"iso_checksum": "foo",
"iso_checksum_type": "md5",
"iso_url": "http://www.packer.io",
"shutdown_command": "foo",
"ssh_username": "foo",
packer.BuildNameConfigKey: "foo",
@ -64,7 +65,10 @@ func TestBuilderPrepare_BootWait(t *testing.T) {
// Test a default boot_wait
delete(config, "boot_wait")
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("err: %s", err)
}
@ -75,7 +79,10 @@ func TestBuilderPrepare_BootWait(t *testing.T) {
// Test with a bad boot_wait
config["boot_wait"] = "this is not good"
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -83,7 +90,10 @@ func TestBuilderPrepare_BootWait(t *testing.T) {
// Test with a good one
config["boot_wait"] = "5s"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -95,7 +105,10 @@ func TestBuilderPrepare_ISOChecksum(t *testing.T) {
// Test bad
config["iso_checksum"] = ""
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -103,7 +116,10 @@ func TestBuilderPrepare_ISOChecksum(t *testing.T) {
// Test good
config["iso_checksum"] = "FOo"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -119,7 +135,10 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) {
// Test bad
config["iso_checksum_type"] = ""
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -127,7 +146,10 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) {
// Test good
config["iso_checksum_type"] = "mD5"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -139,7 +161,10 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) {
// Test unknown
config["iso_checksum_type"] = "fake"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -147,7 +172,10 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) {
func TestBuilderPrepare_Defaults(t *testing.T) {
var b Builder
config := testConfig()
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -174,7 +202,10 @@ func TestBuilderPrepare_DiskSize(t *testing.T) {
config := testConfig()
delete(config, "disk_size")
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("bad err: %s", err)
}
@ -185,7 +216,10 @@ func TestBuilderPrepare_DiskSize(t *testing.T) {
config["disk_size"] = 60000
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -200,7 +234,10 @@ func TestBuilderPrepare_FloppyFiles(t *testing.T) {
config := testConfig()
delete(config, "floppy_files")
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("bad err: %s", err)
}
@ -211,7 +248,10 @@ func TestBuilderPrepare_FloppyFiles(t *testing.T) {
config["floppy_files"] = []string{"foo", "bar"}
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -229,7 +269,10 @@ func TestBuilderPrepare_HTTPPort(t *testing.T) {
// Bad
config["http_port_min"] = 1000
config["http_port_max"] = 500
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -237,7 +280,10 @@ func TestBuilderPrepare_HTTPPort(t *testing.T) {
// Bad
config["http_port_min"] = -500
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -246,7 +292,10 @@ func TestBuilderPrepare_HTTPPort(t *testing.T) {
config["http_port_min"] = 500
config["http_port_max"] = 1000
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -258,7 +307,10 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) {
// Add a random key
config["i_should_not_be_valid"] = true
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -273,7 +325,10 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) {
// Test both epty
config["iso_url"] = ""
b = Builder{}
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -281,7 +336,10 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) {
// Test iso_url set
config["iso_url"] = "http://www.packer.io"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Errorf("should not have error: %s", err)
}
@ -295,7 +353,10 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) {
config["iso_url"] = "http://www.packer.io"
config["iso_urls"] = []string{"http://www.packer.io"}
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -308,7 +369,10 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) {
}
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Errorf("should not have error: %s", err)
}
@ -335,7 +399,10 @@ func TestBuilderPrepare_OutputDir(t *testing.T) {
config["output_directory"] = dir
b = Builder{}
err = b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -343,19 +410,40 @@ func TestBuilderPrepare_OutputDir(t *testing.T) {
// Test with a good one
config["output_directory"] = "i-hope-i-dont-exist"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
}
func TestBuilderPrepare_ShutdownCommand(t *testing.T) {
var b Builder
config := testConfig()
delete(config, "shutdown_command")
warns, err := b.Prepare(config)
if err != nil {
t.Fatalf("bad: %s", err)
}
if len(warns) != 1 {
t.Fatalf("bad: %#v", warns)
}
}
func TestBuilderPrepare_ShutdownTimeout(t *testing.T) {
var b Builder
config := testConfig()
// Test with a bad value
config["shutdown_timeout"] = "this is not good"
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -363,7 +451,10 @@ func TestBuilderPrepare_ShutdownTimeout(t *testing.T) {
// Test with a good one
config["shutdown_timeout"] = "5s"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -375,14 +466,20 @@ func TestBuilderPrepare_sshKeyPath(t *testing.T) {
config["ssh_key_path"] = ""
b = Builder{}
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
config["ssh_key_path"] = "/i/dont/exist"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -401,7 +498,10 @@ func TestBuilderPrepare_sshKeyPath(t *testing.T) {
config["ssh_key_path"] = tf.Name()
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -412,7 +512,10 @@ func TestBuilderPrepare_sshKeyPath(t *testing.T) {
tf.Write([]byte(testPem))
config["ssh_key_path"] = tf.Name()
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("err: %s", err)
}
@ -423,14 +526,20 @@ func TestBuilderPrepare_SSHUser(t *testing.T) {
config := testConfig()
config["ssh_username"] = ""
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
config["ssh_username"] = "exists"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -442,7 +551,10 @@ func TestBuilderPrepare_SSHPort(t *testing.T) {
// Test with a bad value
delete(config, "ssh_port")
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("bad err: %s", err)
}
@ -454,7 +566,10 @@ func TestBuilderPrepare_SSHPort(t *testing.T) {
// Test with a good one
config["ssh_port"] = 44
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -470,7 +585,10 @@ func TestBuilderPrepare_SSHWaitTimeout(t *testing.T) {
// Test with a bad value
config["ssh_wait_timeout"] = "this is not good"
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -478,7 +596,10 @@ func TestBuilderPrepare_SSHWaitTimeout(t *testing.T) {
// Test with a good one
config["ssh_wait_timeout"] = "5s"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -490,7 +611,10 @@ func TestBuilderPrepare_ToolsUploadPath(t *testing.T) {
// Test a default
delete(config, "tools_upload_path")
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("err: %s", err)
}
@ -502,7 +626,10 @@ func TestBuilderPrepare_ToolsUploadPath(t *testing.T) {
// Test with a bad value
config["tools_upload_path"] = "{{{nope}"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -510,7 +637,10 @@ func TestBuilderPrepare_ToolsUploadPath(t *testing.T) {
// Test with a good one
config["tools_upload_path"] = "hey"
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -522,7 +652,10 @@ func TestBuilderPrepare_VMXTemplatePath(t *testing.T) {
// Test bad
config["vmx_template_path"] = "/i/dont/exist/forreal"
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -541,7 +674,10 @@ func TestBuilderPrepare_VMXTemplatePath(t *testing.T) {
config["vmx_template_path"] = tf.Name()
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -560,7 +696,10 @@ func TestBuilderPrepare_VMXTemplatePath(t *testing.T) {
config["vmx_template_path"] = tf2.Name()
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -573,7 +712,10 @@ func TestBuilderPrepare_VNCPort(t *testing.T) {
// Bad
config["vnc_port_min"] = 1000
config["vnc_port_max"] = 500
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -581,7 +723,10 @@ func TestBuilderPrepare_VNCPort(t *testing.T) {
// Bad
config["vnc_port_min"] = -500
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
@ -590,7 +735,10 @@ func TestBuilderPrepare_VNCPort(t *testing.T) {
config["vnc_port_min"] = 500
config["vnc_port_max"] = 1000
b = Builder{}
err = b.Prepare(config)
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
@ -605,7 +753,10 @@ func TestBuilderPrepare_VMXData(t *testing.T) {
"two": "bar",
}
err := b.Prepare(config)
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}

View File

@ -113,11 +113,20 @@ func (c Command) Run(env packer.Environment, args []string) int {
log.Printf("Preparing build: %s", b.Name())
b.SetDebug(cfgDebug)
b.SetForce(cfgForce)
err := b.Prepare(userVars)
warnings, err := b.Prepare(userVars)
if err != nil {
env.Ui().Error(err.Error())
return 1
}
if len(warnings) > 0 {
ui := buildUis[b.Name()]
ui.Say(fmt.Sprintf("Warnings for build '%s':\n", b.Name()))
for _, warning := range warnings {
ui.Say(fmt.Sprintf("* %s", warning))
}
ui.Say("")
}
}
// Run all the builds in parallel and wait for them to complete

View File

@ -62,6 +62,7 @@ func (c Command) Run(env packer.Environment, args []string) int {
}
errs := make([]error, 0)
warnings := make(map[string][]string)
// The component finder for our builds
components := &packer.ComponentFinder{
@ -81,7 +82,10 @@ func (c Command) Run(env packer.Environment, args []string) int {
// Check the configuration of all builds
for _, b := range builds {
log.Printf("Preparing build: %s", b.Name())
err := b.Prepare(userVars)
warns, err := b.Prepare(userVars)
if len(warns) > 0 {
warnings[b.Name()] = warns
}
if err != nil {
errs = append(errs, fmt.Errorf("Errors validating build '%s'. %s", b.Name(), err))
}
@ -100,6 +104,21 @@ func (c Command) Run(env packer.Environment, args []string) int {
return 1
}
if len(warnings) > 0 {
env.Ui().Say("Template validation succeeded, but there were some warnings.")
env.Ui().Say("These are ONLY WARNINGS, and Packer will attempt to build the")
env.Ui().Say("template despite them, but they should be paid attention to.\n")
for build, warns := range warnings {
env.Ui().Say(fmt.Sprintf("Warnings for build '%s':\n", build))
for _, warning := range warns {
env.Ui().Say(fmt.Sprintf("* %s", warning))
}
}
return 0
}
env.Ui().Say("Template validated successfully.")
return 0
}

View File

@ -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

View File

@ -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")
}
}

View File

@ -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)

View File

@ -1,10 +1,17 @@
package packer
import (
"errors"
)
// MockBuilder is an implementation of Builder that can be used for tests.
// 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
RunErrResult bool
RunNilResult bool
PrepareCalled bool
PrepareConfig []interface{}
@ -15,10 +22,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) {
@ -26,6 +33,15 @@ func (tb *MockBuilder) Run(ui Ui, h Hook, c Cache) (Artifact, error) {
tb.RunHook = h
tb.RunUi = ui
tb.RunCache = c
if tb.RunErrResult {
return nil, errors.New("foo")
}
if tb.RunNilResult {
return nil, nil
}
return &MockArtifact{
IdValue: tb.ArtifactId,
}, nil

View File

@ -1,31 +1 @@
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
}

View File

@ -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

View File

@ -10,7 +10,7 @@ type cmdBuilder struct {
client *Client
}
func (b *cmdBuilder) Prepare(config ...interface{}) error {
func (b *cmdBuilder) Prepare(config ...interface{}) ([]string, error) {
defer func() {
r := recover()
b.checkExit(r, nil)

View File

@ -1,23 +1,10 @@
package plugin
import (
"github.com/mitchellh/packer/packer"
"os/exec"
"testing"
)
type helperBuilder byte
func (helperBuilder) Prepare(...interface{}) error {
return nil
}
func (helperBuilder) Run(packer.Ui, packer.Hook, packer.Cache) (packer.Artifact, error) {
return nil, nil
}
func (helperBuilder) Cancel() {}
func TestBuilder_NoExist(t *testing.T) {
c := NewClient(&ClientConfig{Cmd: exec.Command("i-should-not-exist")})
defer c.Kill()

View File

@ -54,7 +54,7 @@ func TestHelperProcess(*testing.T) {
fmt.Printf("%s1|:1234\n", APIVersion)
<-make(chan int)
case "builder":
ServeBuilder(new(helperBuilder))
ServeBuilder(new(packer.MockBuilder))
case "command":
ServeCommand(new(helperCommand))
case "hook":

View File

@ -21,6 +21,11 @@ type BuildRunArgs struct {
UiRPCAddress string
}
type BuildPrepareResponse struct {
Warnings []string
Error error
}
func Build(client *rpc.Client) *build {
return &build{client}
}
@ -30,12 +35,13 @@ func (b *build) Name() (result string) {
return
}
func (b *build) Prepare(v map[string]string) (err error) {
if cerr := b.client.Call("Build.Prepare", v, &err); cerr != nil {
return cerr
func (b *build) Prepare(v map[string]string) ([]string, error) {
var resp BuildPrepareResponse
if cerr := b.client.Call("Build.Prepare", v, &resp); cerr != nil {
return nil, cerr
}
return
return resp.Warnings, resp.Error
}
func (b *build) Run(ui packer.Ui, cache packer.Cache) ([]packer.Artifact, error) {
@ -86,8 +92,12 @@ func (b *BuildServer) Name(args *interface{}, reply *string) error {
return nil
}
func (b *BuildServer) Prepare(v map[string]string, reply *error) error {
*reply = b.build.Prepare(v)
func (b *BuildServer) Prepare(v map[string]string, resp *BuildPrepareResponse) error {
warnings, err := b.build.Prepare(v)
*resp = BuildPrepareResponse{
Warnings: warnings,
Error: err,
}
return nil
}

View File

@ -4,21 +4,23 @@ import (
"errors"
"github.com/mitchellh/packer/packer"
"net/rpc"
"reflect"
"testing"
)
var testBuildArtifact = &testArtifact{}
type testBuild struct {
nameCalled bool
prepareCalled bool
prepareVars map[string]string
runCalled bool
runCache packer.Cache
runUi packer.Ui
setDebugCalled bool
setForceCalled bool
cancelCalled bool
nameCalled bool
prepareCalled bool
prepareVars map[string]string
prepareWarnings []string
runCalled bool
runCache packer.Cache
runUi packer.Ui
setDebugCalled bool
setForceCalled bool
cancelCalled bool
errRunResult bool
}
@ -28,10 +30,10 @@ func (b *testBuild) Name() string {
return "name"
}
func (b *testBuild) Prepare(v map[string]string) error {
func (b *testBuild) Prepare(v map[string]string) ([]string, error) {
b.prepareCalled = true
b.prepareVars = v
return nil
return b.prepareWarnings, nil
}
func (b *testBuild) Run(ui packer.Ui, cache packer.Cache) ([]packer.Artifact, error) {
@ -58,7 +60,7 @@ func (b *testBuild) Cancel() {
b.cancelCalled = true
}
func TestBuildRPC(t *testing.T) {
func buildRPCClient(t *testing.T) (*testBuild, packer.Build) {
// Create the interface to test
b := new(testBuild)
@ -72,7 +74,11 @@ func TestBuildRPC(t *testing.T) {
if err != nil {
t.Fatalf("err: %s", err)
}
bClient := Build(client)
return b, Build(client)
}
func TestBuild(t *testing.T) {
b, bClient := buildRPCClient(t)
// Test Name
bClient.Name()
@ -157,6 +163,21 @@ func TestBuildRPC(t *testing.T) {
}
}
func TestBuildPrepare_Warnings(t *testing.T) {
b, bClient := buildRPCClient(t)
expected := []string{"foo"}
b.prepareWarnings = expected
warnings, err := bClient.Prepare(nil)
if err != nil {
t.Fatalf("err: %s", err)
}
if !reflect.DeepEqual(warnings, expected) {
t.Fatalf("bad: %#v", warnings)
}
}
func TestBuild_ImplementsBuild(t *testing.T) {
var _ packer.Build = Build(nil)
}

View File

@ -29,6 +29,11 @@ type BuilderRunArgs struct {
ResponseAddress string
}
type BuilderPrepareResponse struct {
Warnings []string
Error error
}
type BuilderRunResponse struct {
Err error
RPCAddress string
@ -38,13 +43,14 @@ func Builder(client *rpc.Client) *builder {
return &builder{client}
}
func (b *builder) Prepare(config ...interface{}) (err error) {
cerr := b.client.Call("Builder.Prepare", &BuilderPrepareArgs{config}, &err)
func (b *builder) Prepare(config ...interface{}) ([]string, error) {
var resp BuilderPrepareResponse
cerr := b.client.Call("Builder.Prepare", &BuilderPrepareArgs{config}, &resp)
if cerr != nil {
err = cerr
return nil, cerr
}
return
return resp.Warnings, resp.Error
}
func (b *builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
@ -108,12 +114,16 @@ func (b *builder) Cancel() {
}
}
func (b *BuilderServer) Prepare(args *BuilderPrepareArgs, reply *error) error {
err := b.builder.Prepare(args.Configs...)
func (b *BuilderServer) Prepare(args *BuilderPrepareArgs, reply *BuilderPrepareResponse) error {
warnings, err := b.builder.Prepare(args.Configs...)
if err != nil {
*reply = NewBasicError(err)
err = NewBasicError(err)
}
*reply = BuilderPrepareResponse{
Warnings: warnings,
Error: err,
}
return nil
}

View File

@ -1,7 +1,6 @@
package rpc
import (
"errors"
"github.com/mitchellh/packer/packer"
"net/rpc"
"reflect"
@ -10,47 +9,8 @@ import (
var testBuilderArtifact = &testArtifact{}
type testBuilder struct {
prepareCalled bool
prepareConfig []interface{}
runCalled bool
runCache packer.Cache
runHook packer.Hook
runUi packer.Ui
cancelCalled bool
errRunResult bool
nilRunResult bool
}
func (b *testBuilder) Prepare(config ...interface{}) error {
b.prepareCalled = true
b.prepareConfig = config
return nil
}
func (b *testBuilder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
b.runCache = cache
b.runCalled = true
b.runHook = hook
b.runUi = ui
if b.errRunResult {
return nil, errors.New("foo")
} else if b.nilRunResult {
return nil, nil
} else {
return testBuilderArtifact, nil
}
}
func (b *testBuilder) Cancel() {
b.cancelCalled = true
}
func TestBuilderRPC(t *testing.T) {
// Create the interface to test
b := new(testBuilder)
func builderRPCClient(t *testing.T) (*packer.MockBuilder, packer.Builder) {
b := new(packer.MockBuilder)
// Start the server
server := rpc.NewServer()
@ -62,18 +22,49 @@ func TestBuilderRPC(t *testing.T) {
if err != nil {
t.Fatalf("err: %s", err)
}
return b, Builder(client)
}
func TestBuilderPrepare(t *testing.T) {
b, bClient := builderRPCClient(t)
// Test Prepare
config := 42
bClient := Builder(client)
bClient.Prepare(config)
if !b.prepareCalled {
warnings, err := bClient.Prepare(config)
if err != nil {
t.Fatalf("bad: %s", err)
}
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if !b.PrepareCalled {
t.Fatal("should be called")
}
if !reflect.DeepEqual(b.prepareConfig, []interface{}{42}) {
t.Fatalf("bad: %#v", b.prepareConfig)
if !reflect.DeepEqual(b.PrepareConfig, []interface{}{42}) {
t.Fatalf("bad: %#v", b.PrepareConfig)
}
}
func TestBuilderPrepare_Warnings(t *testing.T) {
b, bClient := builderRPCClient(t)
expected := []string{"foo"}
b.PrepareWarnings = expected
// Test Prepare
warnings, err := bClient.Prepare(nil)
if err != nil {
t.Fatalf("bad: %s", err)
}
if !reflect.DeepEqual(warnings, expected) {
t.Fatalf("bad: %#v", warnings)
}
}
func TestBuilderRun(t *testing.T) {
b, bClient := builderRPCClient(t)
// Test Run
cache := new(testCache)
@ -84,59 +75,71 @@ func TestBuilderRPC(t *testing.T) {
t.Fatalf("err: %s", err)
}
if !b.runCalled {
if !b.RunCalled {
t.Fatal("run should be called")
}
if b.runCalled {
b.runCache.Lock("foo")
if !cache.lockCalled {
t.Fatal("should be called")
}
b.runHook.Run("foo", nil, nil, nil)
if !hook.RunCalled {
t.Fatal("should be called")
}
b.runUi.Say("format")
if !ui.sayCalled {
t.Fatal("say should be called")
}
if ui.sayMessage != "format" {
t.Fatalf("bad: %s", ui.sayMessage)
}
if artifact.Id() != testBuilderArtifact.Id() {
t.Fatalf("bad: %s", artifact.Id())
}
b.RunCache.Lock("foo")
if !cache.lockCalled {
t.Fatal("should be called")
}
// Test run with nil result
b.nilRunResult = true
artifact, err = bClient.Run(ui, hook, cache)
b.RunHook.Run("foo", nil, nil, nil)
if !hook.RunCalled {
t.Fatal("should be called")
}
b.RunUi.Say("format")
if !ui.sayCalled {
t.Fatal("say should be called")
}
if ui.sayMessage != "format" {
t.Fatalf("bad: %s", ui.sayMessage)
}
if artifact.Id() != testBuilderArtifact.Id() {
t.Fatalf("bad: %s", artifact.Id())
}
}
func TestBuilderRun_nilResult(t *testing.T) {
b, bClient := builderRPCClient(t)
b.RunNilResult = true
cache := new(testCache)
hook := &packer.MockHook{}
ui := &testUi{}
artifact, err := bClient.Run(ui, hook, cache)
if artifact != nil {
t.Fatalf("bad: %#v", artifact)
}
if err != nil {
t.Fatalf("bad: %#v", err)
}
}
// Test with an error
b.errRunResult = true
b.nilRunResult = false
artifact, err = bClient.Run(ui, hook, cache)
func TestBuilderRun_ErrResult(t *testing.T) {
b, bClient := builderRPCClient(t)
b.RunErrResult = true
cache := new(testCache)
hook := &packer.MockHook{}
ui := &testUi{}
artifact, err := bClient.Run(ui, hook, cache)
if artifact != nil {
t.Fatalf("bad: %#v", artifact)
}
if err == nil {
t.Fatal("should have error")
}
}
func TestBuilderCancel(t *testing.T) {
b, bClient := builderRPCClient(t)
// Test Cancel
bClient.Cancel()
if !b.cancelCalled {
if !b.CancelCalled {
t.Fatal("cancel should be called")
}
}

View File

@ -7,7 +7,7 @@ import (
"testing"
)
var testEnvBuilder = &testBuilder{}
var testEnvBuilder = &packer.MockBuilder{}
var testEnvCache = &testCache{}
var testEnvUi = &testUi{}
@ -90,7 +90,7 @@ func TestEnvironmentRPC(t *testing.T) {
}
builder.Prepare(nil)
if !testEnvBuilder.prepareCalled {
if !testEnvBuilder.PrepareCalled {
t.Fatal("should be called")
}

View File

@ -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,
}