Compare commits

..

53 Commits

Author SHA1 Message Date
Mitchell Hashimoto b85913b9a7 v0.3.11 2013-11-04 14:43:39 -08:00
Mitchell Hashimoto be9f245810 Update CHANGELOG 2013-11-04 14:36:32 -08:00
Mitchell Hashimoto fe0b1aa75b Merge pull request #589 from mitchellh/f-do-droplet-name
builder/digitalocean: add a droplet_name configuration value
2013-11-04 14:35:44 -08:00
Mitchell Hashimoto d740015ef4 builder/vmware: check for ifconfig in /sbin [GH-591] 2013-11-04 14:34:51 -08:00
Mitchell Hashimoto dd6b5f0d85 builder/vmware: force LANG=C for ifconfig [GH-592] 2013-11-04 14:26:18 -08:00
Mitchell Hashimoto 8f50d2dd9a builder/virtualbox: no panic if ssh host port min/max is same [GH-594] 2013-11-04 14:20:26 -08:00
Jack Pearkes 4f6f9e1639 builder/digitalocean: add a droplet_name configuration value
Practically, this lets you set the hostname of the droplet
used for provisioning.
2013-11-03 17:35:58 +01:00
Mitchell Hashimoto cb5f645c4c Update CHANGELOG 2013-11-02 23:25:48 -05:00
Mitchell Hashimoto 46cb972776 Update CHANGELOG 2013-11-02 23:24:42 -05:00
Mitchell Hashimoto 0d822745a1 Merge branch 'f-builder-warnings' 2013-11-02 23:23:39 -05:00
Mitchell Hashimoto 4b76b8f0a7 command/build: output warnings 2013-11-02 23:21:12 -05:00
Mitchell Hashimoto f40a6e21aa builder/virtualbox,vmware: warning if shutdown_command is not specified 2013-11-02 23:17:21 -05:00
Mitchell Hashimoto 908678423e command/build: get command passing 2013-11-02 23:09:58 -05:00
Mitchell Hashimoto e23411ad24 command/validate: output warnings 2013-11-02 23:09:30 -05:00
Mitchell Hashimoto f9747ad110 builder/all: update to warnings 2013-11-02 23:03:59 -05:00
Mitchell Hashimoto 2d221c5947 builder/amazon/*: warnings 2013-11-02 22:56:54 -05:00
Mitchell Hashimoto 58e8d9ac56 packer/plugin: new Builder interface 2013-11-02 22:51:26 -05:00
Mitchell Hashimoto af7b8d1e15 packer/rpc: test warnings with builders 2013-11-02 22:49:10 -05:00
Mitchell Hashimoto a4077c9d8a packer/rpc: use packer.MockBuilder for tests 2013-11-02 22:47:23 -05:00
Mitchell Hashimoto 623706676b packer/rpc: implement new warnings interfaces 2013-11-02 22:40:06 -05:00
Mitchell Hashimoto 833f80b282 packer: builder prepare can return warnings 2013-11-02 22:31:12 -05:00
Mitchell Hashimoto 4856300f62 common: downloads can be HTTPS [GH-587] 2013-11-02 22:10:48 -05:00
Mitchell Hashimoto a5812670a8 Merge pull request #542 from phyrex1an/patch-1
website: propose additional IAM Role Actions
2013-11-02 03:56:38 -07:00
Mitchell Hashimoto b3c2ee3a67 command/fix: add synopsis option to fixers
This will be used in help output and such later
2013-11-02 11:34:54 +01:00
Mitchell Hashimoto 7abfed7a7a update CHANGELOG 2013-11-02 11:34:54 +01:00
Mitchell Hashimoto 3a9ea41dca command/fix: add fixer to auto set guest_additions_mode 2013-11-02 11:34:54 +01:00
Mitchell Hashimoto fcbc2e7ff2 website: docs on disabling guest additions 2013-11-02 11:34:54 +01:00
Mitchell Hashimoto 6dea765ba4 builder/virtualbox: allow disabling guest addition uploading 2013-11-02 11:34:54 +01:00
Mitchell Hashimoto d17605bd1f communicator/ssh: buffer file on disk to read length [GH-561] 2013-11-02 11:34:54 +01:00
Mitchell Hashimoto 2964f27cc5 builder/amazon/*,builder/openstack: properly scrub sensitive [GH-554] 2013-11-02 11:34:54 +01:00
Matthew Hooker 1d87e98c32 Merge pull request #575 from ciarand/feature/fix-typo
Fix typo in documentation
2013-10-29 20:08:38 -07:00
Ciaran Downey fbfed8a0eb s/extremely to/extremely easy to/ 2013-10-29 19:20:34 -07:00
Matthew Hooker 7fbd3f1ad4 Merge pull request #572 from ktruong7/format-issues1
Spelling mistake in comments
2013-10-28 06:52:57 -07:00
Matthew Hooker 83b96325aa Merge pull request #564 from mmercer-appneta/master
Added missing close-curly-brace to default value of execute_command in Chef Solo docs
2013-10-24 23:32:01 -07:00
mmercer-appneta 88f8e4d079 Added missing close-curly-brace to default value of execute_command. 2013-10-24 18:33:06 -07:00
ktruong7 bdd4294a41 spelling mistake in comments 2013-10-24 14:46:54 -04:00
Matthew Hooker d68e723a04 website: remove extra period. 2013-10-24 01:48:35 -07:00
Mitchell Hashimoto d9aaf49234 builder/amazon/instance: support AZ here too 2013-10-23 20:44:38 -07:00
Mitchell Hashimoto 8b7e258829 builder/amazon: rename availzone to availability zone 2013-10-23 20:44:11 -07:00
Mitchell Hashimoto 60bb158bf1 Merge pull request #550 from mitchellh/fix#536
builder/amazon/ebs: Add config for target AZ.
2013-10-23 20:42:15 -07:00
Mitchell Hashimoto 412d0d6607 Merge pull request #558 from fabiang/virtualbox-sata
builder/virtualbox: arguments Prefix (--) was missing for (sata)portconfig
2013-10-23 20:33:01 -07:00
Mitchell Hashimoto 9fa9cae9b3 packer: don't panic if can't write to UI 2013-10-23 20:32:20 -07:00
Matthew Hooker 402b38e779 Merge branch 'master' of github.com:mitchellh/packer into fix#536
Conflicts:
	CHANGELOG.md
2013-10-23 15:40:35 -07:00
Matthew Hooker 8df4c991df Update CHANGELOG 2013-10-23 15:26:35 -07:00
Matthew Hooker e0a96e968a Merge pull request #557 from zimbatm/unique-uuids
Fixes missing entropy in the uuid package.
2013-10-23 15:23:46 -07:00
Jonas Pfenniger 19b1bdee98 Simplifies the implementation of common/uuid 2013-10-23 23:05:02 +01:00
Fabian Grutschus 5bc3150bb5 Arguments Prefix (--) was missing for (data)portconfig 2013-10-23 15:05:00 +02:00
Jonas Pfenniger d094cb7c5c Fixes missing entropy in the uuid package.
math/crypto is seeded with 1 and thus will create predictable UUIDs. Because
amazon-instance and amazon-ebs in the same second when building both targets
the timestamp in front doesn't help either. See #552
2013-10-23 10:58:48 +01:00
Matthew Hooker 831621ea8b builder/amazon/common: Add AvailZone to StepRunSourceInstance struct
[GH-536]
2013-10-21 08:08:00 -07:00
Matthew Hooker 73a638749a builder/amazon/ebs: Add config for target AZ.
Fixes [GH-536]
2013-10-21 08:01:34 -07:00
Mitchell Hashimoto 50f65ad2c2 website: update Gemfile 2013-10-20 21:01:51 -07:00
Mitchell Hashimoto 07bd414ce5 Up version for dev 2013-10-20 19:07:29 -07:00
Mikael Bung 640d2e9432 Propose additional IAM Role Actions
Depending on what settings you use for the amazon-chroot builder additional actions needs to be allowed in the IAM role for the aws instance.

This patch does not include an exhaustive list of all alternatives, but only the changes I needed to do to get stuff working for me.
2013-10-17 09:12:33 +02:00
60 changed files with 1469 additions and 471 deletions
+32
View File
@@ -1,3 +1,35 @@
## 0.3.11 (November 4, 2013)
FEATURES:
* builder/amazon/ebs: Ability to specify which availability zone to create
instance in. [GH-536]
IMPROVEMENTS:
* core: builders can now give warnings during validation. warnings won't
fail the build but may hint at potential future problems.
* builder/digitalocean: Can now specify a droplet name
* builder/virtualbox: Can now disable guest addition download entirely
by setting "guest_additions_mode" to "disable" [GH-580]
* builder/virtualbox,vmware: ISO urls can now be https [GH-587]
* builder/virtualbox,vmware: Warning if shutdown command is not specified,
since it is a common case of data loss.
BUG FIXES:
* core: Won't panic when writing to a bad pipe. [GH-560]
* builder/amazon/all: Properly scrub access key and secret key from logs.
[GH-554]
* builder/openstack: Properly scrub password from logs [GH-554]
* builder/virtualbox: No panic if SSH host port min/max is the same. [GH-594]
* builder/vmware: checks if `ifconfig` is in `/sbin` [GH-591]
* builder/vmware: Host IP lookup works for non-C locales. [GH-592]
* common/uuid: Use cryptographically secure PRNG when generating
UUIDs. [GH-552]
* communicator/ssh: File uploads that exceed the size of memory no longer
cause crashes. [GH-561]
## 0.3.10 (October 20, 2013)
FEATURES:
+6 -6
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
log.Println(common.ScrubConfig(b.config, b.config.AccessKey, b.config.SecretKey))
return nil, nil
}
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
+32 -8
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)
}
+2
View File
@@ -23,6 +23,7 @@ type RunConfig struct {
SubnetId string `mapstructure:"subnet_id"`
TemporaryKeyPairName string `mapstructure:"temporary_key_pair_name"`
VpcId string `mapstructure:"vpc_id"`
AvailabilityZone string `mapstructure:"availability_zone"`
// Unexported fields that are calculated from others
sshTimeout time.Duration
@@ -83,6 +84,7 @@ func (c *RunConfig) Prepare(t *packer.ConfigTemplate) []error {
"subnet_id": &c.SubnetId,
"temporary_key_pair_name": &c.TemporaryKeyPairName,
"vpc_id": &c.VpcId,
"availability_zone": &c.AvailabilityZone,
}
for n, ptr := range templates {
@@ -18,6 +18,7 @@ type StepRunSourceInstance struct {
SourceAMI string
IamInstanceProfile string
SubnetId string
AvailabilityZone string
BlockDevices BlockDevices
instance *ec2.Instance
@@ -51,6 +52,7 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi
IamInstanceProfile: s.IamInstanceProfile,
SubnetId: s.SubnetId,
BlockDevices: s.BlockDevices.BuildLaunchDevices(),
AvailZone: s.AvailabilityZone,
}
ui.Say("Launching a source AWS instance...")
+7 -6
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
log.Println(common.ScrubConfig(b.config, b.config.AccessKey, b.config.SecretKey))
return nil, nil
}
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
@@ -101,6 +101,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
SourceAMI: b.config.SourceAmi,
IamInstanceProfile: b.config.IamInstanceProfile,
SubnetId: b.config.SubnetId,
AvailabilityZone: b.config.AvailabilityZone,
BlockDevices: b.config.BlockDevices,
},
&common.StepConnectSSH{
+20 -5
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")
}
+7 -6
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
log.Println(common.ScrubConfig(b.config, b.config.AccessKey, b.config.SecretKey))
return nil, nil
}
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
@@ -204,6 +204,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
UserDataFile: b.config.UserDataFile,
SourceAMI: b.config.SourceAmi,
SubnetId: b.config.SubnetId,
AvailabilityZone: b.config.AvailabilityZone,
BlockDevices: b.config.BlockDevices,
},
&common.StepConnectSSH{
+72 -18
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)
}
+13 -5
View File
@@ -8,6 +8,7 @@ import (
"fmt"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/common/uuid"
"github.com/mitchellh/packer/packer"
"log"
"os"
@@ -30,6 +31,7 @@ type config struct {
ImageID uint `mapstructure:"image_id"`
SnapshotName string `mapstructure:"snapshot_name"`
DropletName string `mapstructure:"droplet_name"`
SSHUsername string `mapstructure:"ssh_username"`
SSHPort uint `mapstructure:"ssh_port"`
@@ -49,15 +51,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
@@ -95,6 +97,11 @@ func (b *Builder) Prepare(raws ...interface{}) error {
b.config.SnapshotName = "packer-{{timestamp}}"
}
if b.config.DropletName == "" {
// Default to packer-[time-ordered-uuid]
b.config.DropletName = fmt.Sprintf("packer-%s", uuid.TimeOrderedUUID())
}
if b.config.SSHUsername == "" {
// Default to "root". You can override this if your
// SourceImage has a different user account then the DO default
@@ -121,6 +128,7 @@ func (b *Builder) Prepare(raws ...interface{}) error {
"client_id": &b.config.ClientID,
"api_key": &b.config.APIKey,
"snapshot_name": &b.config.SnapshotName,
"droplet_name": &b.config.DropletName,
"ssh_username": &b.config.SSHUsername,
"ssh_timeout": &b.config.RawSSHTimeout,
"state_timeout": &b.config.RawStateTimeout,
@@ -161,11 +169,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) {
+152 -25
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)
}
@@ -326,3 +401,55 @@ func TestBuilderPrepare_SnapshotName(t *testing.T) {
}
}
func TestBuilderPrepare_DropletName(t *testing.T) {
var b Builder
config := testConfig()
// Test default
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)
}
if b.config.DropletName == "" {
t.Errorf("invalid: %s", b.config.DropletName)
}
// Test normal set
config["droplet_name"] = "foobar"
b = Builder{}
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)
}
// Test with template
config["droplet_name"] = "foobar-{{timestamp}}"
b = Builder{}
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)
}
// Test with bad template
config["droplet_name"] = "foobar-{{"
b = Builder{}
warnings, err = b.Prepare(config)
if len(warnings) > 0 {
t.Fatalf("bad: %#v", warnings)
}
if err == nil {
t.Fatal("should have error")
}
}
+2 -5
View File
@@ -3,7 +3,6 @@ package digitalocean
import (
"fmt"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/common/uuid"
"github.com/mitchellh/packer/packer"
)
@@ -19,11 +18,9 @@ func (s *stepCreateDroplet) Run(state multistep.StateBag) multistep.StepAction {
ui.Say("Creating droplet...")
// Some random droplet name as it's temporary
name := fmt.Sprintf("packer-%s", uuid.TimeOrderedUUID())
// Create the droplet based on configuration
dropletId, err := client.CreateDroplet(name, c.SizeID, c.ImageID, c.RegionID, sshKeyId)
dropletId, err := client.CreateDroplet(c.DropletName, c.SizeID, c.ImageID, c.RegionID, sshKeyId)
if err != nil {
err := fmt.Errorf("Error creating droplet: %s", err)
state.Put("error", err)
+6 -6
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
log.Println(common.ScrubConfig(b.config, b.config.Password))
return nil, nil
}
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
+20 -5
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")
}
+48 -8
View File
@@ -16,6 +16,14 @@ import (
const BuilderId = "mitchellh.virtualbox"
// These are the different valid mode values for "guest_additions_mode" which
// determine how guest additions are delivered to the guest.
const (
GuestAdditionsModeDisable string = "disable"
GuestAdditionsModeAttach = "attach"
GuestAdditionsModeUpload = "upload"
)
type Builder struct {
config config
runner multistep.Runner
@@ -28,7 +36,7 @@ type config struct {
DiskSize uint `mapstructure:"disk_size"`
FloppyFiles []string `mapstructure:"floppy_files"`
Format string `mapstructure:"format"`
GuestAdditionsAttach bool `mapstructure:"guest_additions_attach"`
GuestAdditionsMode string `mapstructure:"guest_additions_mode"`
GuestAdditionsPath string `mapstructure:"guest_additions_path"`
GuestAdditionsURL string `mapstructure:"guest_additions_url"`
GuestAdditionsSHA256 string `mapstructure:"guest_additions_sha256"`
@@ -64,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
@@ -87,6 +96,10 @@ func (b *Builder) Prepare(raws ...interface{}) error {
b.config.FloppyFiles = make([]string, 0)
}
if b.config.GuestAdditionsMode == "" {
b.config.GuestAdditionsMode = "upload"
}
if b.config.GuestAdditionsPath == "" {
b.config.GuestAdditionsPath = "VBoxGuestAdditions.iso"
}
@@ -145,6 +158,7 @@ func (b *Builder) Prepare(raws ...interface{}) error {
// Errors
templates := map[string]*string{
"guest_additions_mode": &b.config.GuestAdditionsMode,
"guest_additions_sha256": &b.config.GuestAdditionsSHA256,
"guest_os_type": &b.config.GuestOSType,
"hard_drive_interface": &b.config.HardDriveInterface,
@@ -264,6 +278,25 @@ func (b *Builder) Prepare(raws ...interface{}) error {
}
}
validMode := false
validModes := []string{
GuestAdditionsModeDisable,
GuestAdditionsModeAttach,
GuestAdditionsModeUpload,
}
for _, mode := range validModes {
if b.config.GuestAdditionsMode == mode {
validMode = true
break
}
}
if !validMode {
errs = packer.MultiErrorAppend(errs,
fmt.Errorf("guest_additions_mode is invalid. Must be one of: %v", validModes))
}
if b.config.GuestAdditionsSHA256 != "" {
b.config.GuestAdditionsSHA256 = strings.ToLower(b.config.GuestAdditionsSHA256)
}
@@ -331,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) {
+273 -53
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,11 +61,18 @@ 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)
}
if b.config.GuestAdditionsMode != GuestAdditionsModeUpload {
t.Errorf("bad guest additions mode: %s", b.config.GuestAdditionsMode)
}
if b.config.GuestOSType != "Other" {
t.Errorf("bad guest OS type: %s", b.config.GuestOSType)
}
@@ -100,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)
}
@@ -111,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")
}
@@ -119,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)
}
@@ -130,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)
}
@@ -141,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)
}
@@ -156,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)
}
@@ -167,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)
}
@@ -178,12 +207,56 @@ func TestBuilderPrepare_FloppyFiles(t *testing.T) {
}
}
func TestBuilderPrepare_GuestAdditionsMode(t *testing.T) {
var b Builder
config := testConfig()
// test default mode
delete(config, "guest_additions_mode")
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("bad err: %s", err)
}
// Test another mode
config["guest_additions_mode"] = "attach"
b = Builder{}
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)
}
if b.config.GuestAdditionsMode != GuestAdditionsModeAttach {
t.Fatalf("bad: %s", b.config.GuestAdditionsMode)
}
// Test bad mode
config["guest_additions_mode"] = "teleport"
b = Builder{}
warns, err = b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should error")
}
}
func TestBuilderPrepare_GuestAdditionsPath(t *testing.T) {
var b Builder
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)
}
@@ -194,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)
}
@@ -209,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)
}
@@ -220,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)
}
@@ -235,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)
}
@@ -246,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)
}
@@ -258,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)
}
@@ -270,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")
}
@@ -278,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)
}
@@ -291,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")
}
@@ -299,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")
}
@@ -308,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)
}
@@ -320,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")
}
@@ -328,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)
}
@@ -336,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)
}
@@ -348,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")
}
@@ -360,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")
}
@@ -368,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)
}
@@ -384,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")
}
@@ -392,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)
}
@@ -404,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")
}
@@ -419,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")
}
@@ -427,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)
}
@@ -441,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")
}
@@ -454,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)
}
@@ -481,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")
}
@@ -489,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")
}
@@ -509,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)
}
@@ -523,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")
}
@@ -531,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")
}
@@ -540,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)
}
@@ -552,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")
}
@@ -578,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")
}
@@ -589,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)
}
@@ -601,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)
}
@@ -620,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)
}
@@ -632,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")
}
@@ -640,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)
}
@@ -652,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)
}
@@ -667,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)
}
@@ -687,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)
}
@@ -699,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)
}
+2 -2
View File
@@ -53,9 +53,9 @@ func (d *VBox42Driver) CreateSATAController(vmName string, name string) error {
return err
}
portCountArg := "sataportcount"
portCountArg := "--sataportcount"
if strings.HasPrefix(version, "4.3") {
portCountArg = "portcount"
portCountArg = "--portcount"
}
command := []string{
@@ -30,7 +30,7 @@ func (s *stepAttachGuestAdditions) Run(state multistep.StateBag) multistep.StepA
vmName := state.Get("vmName").(string)
// If we're not attaching the guest additions then just return
if !config.GuestAdditionsAttach {
if config.GuestAdditionsMode != GuestAdditionsModeAttach {
log.Println("Not attaching guest additions since we're uploading.")
return multistep.ActionContinue
}
+1 -1
View File
@@ -43,7 +43,7 @@ func (s *stepCreateVM) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionHalt
}
// Set the VM name propery on the first command
// Set the VM name property on the first command
if s.vmName == "" {
s.vmName = name
}
+8 -1
View File
@@ -25,9 +25,16 @@ func (s *stepForwardSSH) Run(state multistep.StateBag) multistep.StepAction {
log.Printf("Looking for available SSH port between %d and %d", config.SSHHostPortMin, config.SSHHostPortMax)
var sshHostPort uint
var offset uint = 0
portRange := int(config.SSHHostPortMax - config.SSHHostPortMin)
if portRange > 0 {
// Have to check if > 0 to avoid a panic
offset = uint(rand.Intn(portRange))
}
for {
sshHostPort = uint(rand.Intn(portRange)) + config.SSHHostPortMin
sshHostPort = offset + config.SSHHostPortMin
log.Printf("Trying port: %d", sshHostPort)
l, err := net.Listen("tcp", fmt.Sprintf(":%d", sshHostPort))
if err == nil {
@@ -23,8 +23,8 @@ func (s *stepUploadGuestAdditions) Run(state multistep.StateBag) multistep.StepA
ui := state.Get("ui").(packer.Ui)
// If we're attaching then don't do this, since we attached.
if config.GuestAdditionsAttach {
log.Println("Not uploading guest additions since we're attaching.")
if config.GuestAdditionsMode != GuestAdditionsModeUpload {
log.Println("Not uploading guest additions since mode is not upload")
return multistep.ActionContinue
}
+14 -6
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) {
+196 -45
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)
}
+21 -3
View File
@@ -3,6 +3,7 @@ package vmware
import (
"bytes"
"errors"
"os"
"os/exec"
"regexp"
)
@@ -13,14 +14,31 @@ type IfconfigIPFinder struct {
}
func (f *IfconfigIPFinder) HostIP() (string, error) {
ifconfigPath, err := exec.LookPath("ifconfig")
if err != nil {
return "", err
var ifconfigPath string
// On some systems, ifconfig is in /sbin which is generally not
// on the PATH for a standard user, so we just check that first.
if _, err := os.Stat("/sbin/ifconfig"); err == nil {
ifconfigPath = "/sbin/ifconfig"
}
if ifconfigPath == "" {
var err error
ifconfigPath, err = exec.LookPath("ifconfig")
if err != nil {
return "", err
}
}
stdout := new(bytes.Buffer)
cmd := exec.Command(ifconfigPath, f.Device)
cmd.Env = append(cmd.Env, os.Environ()...)
// Force LANG=C so that the output is what we expect it to be
// despite the locale.
cmd.Env = append(cmd.Env, "LANG=C")
cmd.Stdout = stdout
cmd.Stderr = new(bytes.Buffer)
if err := cmd.Run(); err != nil {
+10 -1
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
+1
View File
@@ -53,6 +53,7 @@ func (c Command) Run(env packer.Environment, args []string) int {
fixers := []string{
"iso-md5",
"createtime",
"virtualbox-gaattach",
}
input := templateData
+7 -2
View File
@@ -6,6 +6,10 @@ type Fixer interface {
// in some way, and returns the new, transformed structure. The
// Fix method is allowed to mutate the input.
Fix(input map[string]interface{}) (map[string]interface{}, error)
// Synopsis returns a string description of what the fixer actually
// does.
Synopsis() string
}
// Fixers is the map of all available fixers, by name.
@@ -13,7 +17,8 @@ var Fixers map[string]Fixer
func init() {
Fixers = map[string]Fixer{
"iso-md5": new(FixerISOMD5),
"createtime": new(FixerCreateTime),
"iso-md5": new(FixerISOMD5),
"createtime": new(FixerCreateTime),
"virtualbox-gaattach": new(FixerVirtualBoxGAAttach),
}
}
+4
View File
@@ -49,3 +49,7 @@ func (FixerCreateTime) Fix(input map[string]interface{}) (map[string]interface{}
input["builders"] = tpl.Builders
return input, nil
}
func (FixerCreateTime) Synopsis() string {
return `Replaces ".CreateTime" in builder configs with "{{timestamp}}"`
}
+4
View File
@@ -41,3 +41,7 @@ func (FixerISOMD5) Fix(input map[string]interface{}) (map[string]interface{}, er
input["builders"] = tpl.Builders
return input, nil
}
func (FixerISOMD5) Synopsis() string {
return `Replaces "iso_md5" in builders with "iso_checksum"`
}
+63
View File
@@ -0,0 +1,63 @@
package fix
import (
"github.com/mitchellh/mapstructure"
)
// FixerVirtualBoxGAAttach changes the "guest_additions_attach" of a template
// to "guest_additions_mode".
type FixerVirtualBoxGAAttach struct{}
func (FixerVirtualBoxGAAttach) Fix(input map[string]interface{}) (map[string]interface{}, error) {
// The type we'll decode into; we only care about builders
type template struct {
Builders []map[string]interface{}
}
// Decode the input into our structure, if we can
var tpl template
if err := mapstructure.Decode(input, &tpl); err != nil {
return nil, err
}
for _, builder := range tpl.Builders {
builderTypeRaw, ok := builder["type"]
if !ok {
continue
}
builderType, ok := builderTypeRaw.(string)
if !ok {
continue
}
if builderType != "virtualbox" {
continue
}
gaAttachRaw, ok := builder["guest_additions_attach"]
if !ok {
continue
}
gaAttach, ok := gaAttachRaw.(bool)
if !ok {
continue
}
gaMode := "upload"
if gaAttach {
gaMode = "attach"
}
delete(builder, "guest_additions_attach")
builder["guest_additions_mode"] = gaMode
}
input["builders"] = tpl.Builders
return input, nil
}
func (FixerVirtualBoxGAAttach) Synopsis() string {
return `Updates VirtualBox builders using "guest_additions_attach" to use "guest_additions_mode"`
}
@@ -0,0 +1,88 @@
package fix
import (
"reflect"
"testing"
)
func TestFixerVirtualBoxGAAttach_Impl(t *testing.T) {
var _ Fixer = new(FixerVirtualBoxGAAttach)
}
func TestFixerVirtualBoxGAAttach_Fix(t *testing.T) {
cases := []struct {
Input map[string]interface{}
Expected map[string]interface{}
}{
// No attach field
{
Input: map[string]interface{}{
"type": "virtualbox",
},
Expected: map[string]interface{}{
"type": "virtualbox",
},
},
// Attach field == false
{
Input: map[string]interface{}{
"type": "virtualbox",
"guest_additions_attach": false,
},
Expected: map[string]interface{}{
"type": "virtualbox",
"guest_additions_mode": "upload",
},
},
// Attach field == true
{
Input: map[string]interface{}{
"type": "virtualbox",
"guest_additions_attach": true,
},
Expected: map[string]interface{}{
"type": "virtualbox",
"guest_additions_mode": "attach",
},
},
// Attach field is not a bool
{
Input: map[string]interface{}{
"type": "virtualbox",
"guest_additions_attach": "what",
},
Expected: map[string]interface{}{
"type": "virtualbox",
"guest_additions_attach": "what",
},
},
}
for _, tc := range cases {
var f FixerVirtualBoxGAAttach
input := map[string]interface{}{
"builders": []map[string]interface{}{tc.Input},
}
expected := map[string]interface{}{
"builders": []map[string]interface{}{tc.Expected},
}
output, err := f.Fix(input)
if err != nil {
t.Fatalf("err: %s", err)
}
if !reflect.DeepEqual(output, expected) {
t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected)
}
}
}
+20 -1
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
}
+2 -1
View File
@@ -73,7 +73,8 @@ func HashForType(t string) hash.Hash {
func NewDownloadClient(c *DownloadConfig) *DownloadClient {
if c.DownloaderMap == nil {
c.DownloaderMap = map[string]Downloader{
"http": new(HTTPDownloader),
"http": new(HTTPDownloader),
"https": new(HTTPDownloader),
}
}
+11 -10
View File
@@ -1,8 +1,8 @@
package uuid
import (
"crypto/rand"
"fmt"
"math/rand"
"time"
)
@@ -10,14 +10,15 @@ import (
// bottom 96 are random.
func TimeOrderedUUID() string {
unix := uint32(time.Now().UTC().Unix())
rand1 := rand.Uint32()
rand2 := rand.Uint32()
rand3 := rand.Uint32()
b := make([]byte, 12)
n, err := rand.Read(b)
if n != len(b) {
err = fmt.Errorf("Not enough entropy available")
}
if err != nil {
panic(err)
}
return fmt.Sprintf("%08x-%04x-%04x-%04x-%04x%08x",
unix,
uint16(rand1>>16),
uint16(rand1&0xffff),
uint16(rand2>>16),
uint16(rand2&0xffff),
rand3)
unix, b[0:2], b[2:4], b[4:6], b[6:8], b[8:])
}
+32 -12
View File
@@ -8,6 +8,7 @@ import (
"fmt"
"github.com/mitchellh/packer/packer"
"io"
"io/ioutil"
"log"
"net"
"os"
@@ -362,30 +363,49 @@ func checkSCPStatus(r *bufio.Reader) error {
}
func scpUploadFile(dst string, src io.Reader, w io.Writer, r *bufio.Reader) error {
// Determine the length of the upload content by copying it
// into an in-memory buffer. Note that this means what we upload
// must fit into memory.
log.Println("Copying input data into in-memory buffer so we can get the length")
inputBuf := new(bytes.Buffer)
if _, err := io.Copy(inputBuf, src); err != nil {
// Create a temporary file where we can copy the contents of the src
// so that we can determine the length, since SCP is length-prefixed.
tf, err := ioutil.TempFile("", "packer-upload")
if err != nil {
return fmt.Errorf("Error creating temporary file for upload: %s", err)
}
defer os.Remove(tf.Name())
defer tf.Close()
log.Println("Copying input data into temporary file so we can read the length")
if _, err := io.Copy(tf, src); err != nil {
return err
}
// Sync the file so that the contents are definitely on disk, then
// read the length of it.
if err := tf.Sync(); err != nil {
return fmt.Errorf("Error creating temporary file for upload: %s", err)
}
// Seek the file to the beginning so we can re-read all of it
if _, err := tf.Seek(0, 0); err != nil {
return fmt.Errorf("Error creating temporary file for upload: %s", err)
}
fi, err := tf.Stat()
if err != nil {
return fmt.Errorf("Error creating temporary file for upload: %s", err)
}
// Start the protocol
log.Println("Beginning file upload...")
fmt.Fprintln(w, "C0644", inputBuf.Len(), dst)
err := checkSCPStatus(r)
if err != nil {
fmt.Fprintln(w, "C0644", fi.Size(), dst)
if err := checkSCPStatus(r); err != nil {
return err
}
if _, err := io.Copy(w, inputBuf); err != nil {
if _, err := io.Copy(w, tf); err != nil {
return err
}
fmt.Fprint(w, "\x00")
err = checkSCPStatus(r)
if err != nil {
if err := checkSCPStatus(r); err != nil {
return err
}
+6 -5
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
+63 -32
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")
}
}
+4 -1
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)
+19 -3
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
-30
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
}
+2 -2
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
+1 -1
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)
-13
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()
+1 -1
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":
+16 -6
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
}
+34 -13
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)
}
+17 -7
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
}
+83 -80
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")
}
}
+2 -2
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")
}
+3 -3
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,
}
+3 -3
View File
@@ -210,7 +210,7 @@ func (rw *BasicUi) Say(message string) {
log.Printf("ui: %s", message)
_, err := fmt.Fprint(rw.Writer, message+"\n")
if err != nil {
panic(err)
log.Printf("[ERR] Failed to write to UI: %s", err)
}
}
@@ -221,7 +221,7 @@ func (rw *BasicUi) Message(message string) {
log.Printf("ui: %s", message)
_, err := fmt.Fprint(rw.Writer, message+"\n")
if err != nil {
panic(err)
log.Printf("[ERR] Failed to write to UI: %s", err)
}
}
@@ -232,7 +232,7 @@ func (rw *BasicUi) Error(message string) {
log.Printf("ui error: %s", message)
_, err := fmt.Fprint(rw.Writer, message+"\n")
if err != nil {
panic(err)
log.Printf("[ERR] Failed to write to UI: %s", err)
}
}
+1 -1
View File
@@ -10,7 +10,7 @@ import (
var GitCommit string
// The version of packer.
const Version = "0.3.10"
const Version = "0.3.11"
// Any pre-release marker for the version. If this is "" (empty string),
// then it means that it is a final release. Otherwise, this is the
-2
View File
@@ -1,7 +1,5 @@
source 'https://rubygems.org'
ruby '1.9.3'
gem "middleman", "~> 3.1.5"
gem "middleman-minify-html", "~> 3.1.1"
gem "rack-contrib", "~> 1.1.0"
+15 -15
View File
@@ -1,10 +1,10 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (3.2.14)
activesupport (3.2.15)
i18n (~> 0.6, >= 0.6.4)
multi_json (~> 1.0)
chunky_png (1.2.8)
chunky_png (1.2.9)
coffee-script (2.2.0)
coffee-script-source
execjs
@@ -21,45 +21,45 @@ GEM
fssm (0.2.10)
haml (4.0.3)
tilt
highline (1.6.19)
highline (1.6.20)
hike (1.2.3)
i18n (0.6.5)
kramdown (1.1.0)
kramdown (1.2.0)
libv8 (3.16.14.3)
listen (1.2.3)
listen (1.3.1)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9)
rb-kqueue (>= 0.2)
middleman (3.1.5)
middleman (3.1.6)
coffee-script (~> 2.2.0)
compass (>= 0.12.2)
execjs (~> 1.4.0)
haml (>= 3.1.6)
kramdown (~> 1.1.0)
middleman-core (= 3.1.5)
middleman-more (= 3.1.5)
kramdown (~> 1.2)
middleman-core (= 3.1.6)
middleman-more (= 3.1.6)
middleman-sprockets (>= 3.1.2)
sass (>= 3.1.20)
uglifier (~> 2.1.0)
middleman-core (3.1.5)
middleman-core (3.1.6)
activesupport (~> 3.2.6)
bundler (~> 1.1)
i18n (~> 0.6.1)
listen (~> 1.2.2)
listen (~> 1.1)
rack (>= 1.4.5)
rack-test (~> 0.6.1)
thor (>= 0.15.2, < 2.0)
tilt (~> 1.3.6)
middleman-minify-html (3.1.1)
middleman-core (~> 3.0)
middleman-more (3.1.5)
middleman-more (3.1.6)
middleman-sprockets (3.1.4)
middleman-core (>= 3.0.14)
middleman-more (>= 3.0.14)
sprockets (~> 2.1)
sprockets-helpers (~> 1.0.0)
sprockets-sass (~> 1.0.0)
multi_json (1.8.0)
multi_json (1.8.2)
rack (1.5.2)
rack-contrib (1.1.0)
rack (>= 0.9.1)
@@ -72,7 +72,7 @@ GEM
ffi (>= 0.5.0)
redcarpet (3.0.0)
ref (1.0.5)
sass (3.2.10)
sass (3.2.12)
sprockets (2.10.0)
hike (~> 1.2)
multi_json (~> 1.0)
@@ -80,7 +80,7 @@ GEM
tilt (~> 1.1, != 1.3.0)
sprockets-helpers (1.0.1)
sprockets (~> 2.0)
sprockets-sass (1.0.1)
sprockets-sass (1.0.2)
sprockets (~> 2.0)
tilt (~> 1.1)
therubyracer (0.12.0)
@@ -217,3 +217,6 @@ The following policy document provides the minimal set permissions necessary for
}]
}
</pre>
Depending on what setting you use the following Actions might have to be allowed as well:
* `ec2:ModifyImageAttribute` when using `ami_description`
@@ -120,6 +120,9 @@ Optional:
* `vpc_id` (string) - If launching into a VPC subnet, Packer needs the
VPC ID in order to create a temporary security group within the VPC.
* `avail_zone` (string) - Destination availability zone to launch instance in.
Leave this empty to allow Amazon to auto-assign.
## Basic Example
Here is a basic example. It is completely valid except for the access keys:
@@ -51,6 +51,9 @@ Optional:
To help make this unique, use a function like `timestamp` (see
[configuration templates](/docs/templates/configuration-templates.html) for more info)
* `droplet_name` (string) - The name assigned to the droplet. DigitalOcean
sets the hostname of the machine to this value.
* `ssh_port` (int) - The port that SSH will be available on. Defaults to port
22.
@@ -34,8 +34,8 @@ Ubuntu to self-install. Still, the example serves to show the basic configuratio
}
</pre>
It is important to add a `shutdown_command`. By default Packer halts the
virtual machine and the file system may not be sync'd. Thus, changes made in a
It is important to add a `shutdown_command`. By default Packer halts the
virtual machine and the file system may not be sync'd. Thus, changes made in a
provisioner might not be saved.
## Configuration Reference
@@ -90,9 +90,11 @@ Optional:
* `format` (string) - Either "ovf" or "ova", this specifies the output
format of the exported virtual machine. This defaults to "ovf".
* `guest_additions_attach` (bool) - If this is true (defaults to "false"),
the guest additions ISO will be attached to the virtual machine as a CD
rather than uploaded as a raw ISO.
* `guest_additions_mode` (string) - The method by which guest additions
are made available to the guest for installation. Valid options are
"upload", "attach", or "disable". The functions of each of these should be
self-explanatory. The default value is "upload". If "disable" is used,
guest additions won't be downloaded, either.
* `guest_additions_path` (string) - The path on the guest virtual machine
where the VirtualBox guest additions ISO will be uploaded. By default this
@@ -37,7 +37,7 @@ with the `-machine-readable` flag to see!
## Format
The machine readable format is a line-oriented, comma-delimeted text
format. This makes it extremely to parse using standard Unix tools such
format. This makes it extremely easy to parse using standard Unix tools such
as awk or grep in addition to full programming languages like Ruby or
Python.
@@ -110,7 +110,7 @@ By default, Packer uses the following command (broken across multiple lines
for readability) to execute Chef:
```
{{if .Sudo}sudo {{end}}chef-solo \
{{if .Sudo}}sudo {{end}}chef-solo \
--no-color \
-c {{.ConfigPath}} \
-j {{.JsonPath}}