From 0332901f637de373afda2f7d0402d36a670488b2 Mon Sep 17 00:00:00 2001 From: Ben Langfeld Date: Wed, 12 Mar 2014 10:12:20 -0300 Subject: [PATCH 1/7] builder/virtualbox: Add an `export_opts` option Allows arbitrary arguments to VBoxManage export, such as product info (--product, --vendor, etc). --- CHANGELOG.md | 2 ++ builder/virtualbox/common/export_opts.go | 27 +++++++++++++++++++ builder/virtualbox/common/export_opts_test.go | 18 +++++++++++++ builder/virtualbox/common/step_export.go | 6 +++-- builder/virtualbox/iso/builder.go | 7 +++-- builder/virtualbox/ovf/builder.go | 5 ++-- builder/virtualbox/ovf/config.go | 2 ++ .../builders/virtualbox-iso.html.markdown | 4 +++ .../builders/virtualbox-ovf.html.markdown | 4 +++ 9 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 builder/virtualbox/common/export_opts.go create mode 100644 builder/virtualbox/common/export_opts_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 265ccfade..925b7ab61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ FEATURES: IMPROVEMENTS: * builder/vmware: Workstation 10 support for Linux. [GH-900] +* builder/virtualbox: Support an `export_opts` option which allows + specifying arbitrary arguments when exporting the VM. BUG FIXES: diff --git a/builder/virtualbox/common/export_opts.go b/builder/virtualbox/common/export_opts.go new file mode 100644 index 000000000..1794823f4 --- /dev/null +++ b/builder/virtualbox/common/export_opts.go @@ -0,0 +1,27 @@ +package common + +import ( + "fmt" + "github.com/mitchellh/packer/packer" +) + +type ExportOpts struct { + ExportOpts string `mapstructure:"export_opts"` +} + +func (c *ExportOpts) Prepare(t *packer.ConfigTemplate) []error { + templates := map[string]*string{ + "export_opts": &c.ExportOpts, + } + + errs := make([]error, 0) + for n, ptr := range templates { + var err error + *ptr, err = t.Process(*ptr, nil) + if err != nil { + errs = append(errs, fmt.Errorf("Error processing %s: %s", n, err)) + } + } + + return errs +} diff --git a/builder/virtualbox/common/export_opts_test.go b/builder/virtualbox/common/export_opts_test.go new file mode 100644 index 000000000..b86d0eb40 --- /dev/null +++ b/builder/virtualbox/common/export_opts_test.go @@ -0,0 +1,18 @@ +package common + +import ( + "testing" +) + +func TestExportOptsPrepare_BootWait(t *testing.T) { + var c *ExportOpts + var errs []error + + // Good + c = new(ExportOpts) + c.ExportOpts = "ovf" + errs = c.Prepare(testConfigTemplate(t)) + if len(errs) > 0 { + t.Fatalf("should not have error: %s", errs) + } +} diff --git a/builder/virtualbox/common/step_export.go b/builder/virtualbox/common/step_export.go index c5dc208b2..c17f8cd0b 100644 --- a/builder/virtualbox/common/step_export.go +++ b/builder/virtualbox/common/step_export.go @@ -16,8 +16,9 @@ import ( // Produces: // exportPath string - The path to the resulting export. type StepExport struct { - Format string - OutputDir string + Format string + OutputDir string + ExportOpts string } func (s *StepExport) Run(state multistep.StateBag) multistep.StepAction { @@ -50,6 +51,7 @@ func (s *StepExport) Run(state multistep.StateBag) multistep.StepAction { vmName, "--output", outputPath, + s.ExportOpts, } ui.Say("Exporting virtual machine...") diff --git a/builder/virtualbox/iso/builder.go b/builder/virtualbox/iso/builder.go index 14e5daf65..31660a961 100644 --- a/builder/virtualbox/iso/builder.go +++ b/builder/virtualbox/iso/builder.go @@ -29,6 +29,7 @@ type Builder struct { type config struct { common.PackerConfig `mapstructure:",squash"` vboxcommon.ExportConfig `mapstructure:",squash"` + vboxcommon.ExportOpts `mapstructure:",squash"` vboxcommon.FloppyConfig `mapstructure:",squash"` vboxcommon.OutputConfig `mapstructure:",squash"` vboxcommon.RunConfig `mapstructure:",squash"` @@ -73,6 +74,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { // Accumulate any errors and warnings errs := common.CheckUnusedConfig(md) errs = packer.MultiErrorAppend(errs, b.config.ExportConfig.Prepare(b.config.tpl)...) + errs = packer.MultiErrorAppend(errs, b.config.ExportOpts.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.FloppyConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend( errs, b.config.OutputConfig.Prepare(b.config.tpl, &b.config.PackerConfig)...) @@ -317,8 +319,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe }, new(vboxcommon.StepRemoveDevices), &vboxcommon.StepExport{ - Format: b.config.Format, - OutputDir: b.config.OutputDir, + Format: b.config.Format, + OutputDir: b.config.OutputDir, + ExportOpts: b.config.ExportOpts.ExportOpts, }, } diff --git a/builder/virtualbox/ovf/builder.go b/builder/virtualbox/ovf/builder.go index daf1f0052..f2e6a92f5 100644 --- a/builder/virtualbox/ovf/builder.go +++ b/builder/virtualbox/ovf/builder.go @@ -95,8 +95,9 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe }, new(vboxcommon.StepRemoveDevices), &vboxcommon.StepExport{ - Format: b.config.Format, - OutputDir: b.config.OutputDir, + Format: b.config.Format, + OutputDir: b.config.OutputDir, + ExportOpts: b.config.ExportOpts.ExportOpts, }, } diff --git a/builder/virtualbox/ovf/config.go b/builder/virtualbox/ovf/config.go index 56f37f43f..054d09e3a 100644 --- a/builder/virtualbox/ovf/config.go +++ b/builder/virtualbox/ovf/config.go @@ -13,6 +13,7 @@ import ( type Config struct { common.PackerConfig `mapstructure:",squash"` vboxcommon.ExportConfig `mapstructure:",squash"` + vboxcommon.ExportOpts `mapstructure:",squash"` vboxcommon.FloppyConfig `mapstructure:",squash"` vboxcommon.OutputConfig `mapstructure:",squash"` vboxcommon.RunConfig `mapstructure:",squash"` @@ -49,6 +50,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { // Prepare the errors errs := common.CheckUnusedConfig(md) errs = packer.MultiErrorAppend(errs, c.ExportConfig.Prepare(c.tpl)...) + errs = packer.MultiErrorAppend(errs, c.ExportOpts.Prepare(c.tpl)...) errs = packer.MultiErrorAppend(errs, c.FloppyConfig.Prepare(c.tpl)...) errs = packer.MultiErrorAppend(errs, c.OutputConfig.Prepare(c.tpl, &c.PackerConfig)...) errs = packer.MultiErrorAppend(errs, c.RunConfig.Prepare(c.tpl)...) diff --git a/website/source/docs/builders/virtualbox-iso.html.markdown b/website/source/docs/builders/virtualbox-iso.html.markdown index 490fbeb65..2f417dca0 100644 --- a/website/source/docs/builders/virtualbox-iso.html.markdown +++ b/website/source/docs/builders/virtualbox-iso.html.markdown @@ -211,6 +211,10 @@ Optional: machine, without the file extension. By default this is "packer-BUILDNAME", where "BUILDNAME" is the name of the build. +* `export_opts` (string) - Additional options to pass to the `VBoxManage export`. + This can be useful for passing product information to include in the resulting + appliance file. + ## Boot Command The `boot_command` configuration is very important: it specifies the keys diff --git a/website/source/docs/builders/virtualbox-ovf.html.markdown b/website/source/docs/builders/virtualbox-ovf.html.markdown index 2112e276d..47378e6c2 100644 --- a/website/source/docs/builders/virtualbox-ovf.html.markdown +++ b/website/source/docs/builders/virtualbox-ovf.html.markdown @@ -151,6 +151,10 @@ Optional: This can be useful for passing "keepallmacs" or "keepnatmacs" options for existing ovf images. +* `export_opts` (string) - Additional options to pass to the `VBoxManage export`. + This can be useful for passing product information to include in the resulting + appliance file. + ## Guest Additions Packer will automatically download the proper guest additions for the From d1b41f2f146f3b9ab1836a01c9dc35bc0f891f84 Mon Sep 17 00:00:00 2001 From: Ben Langfeld Date: Thu, 13 Mar 2014 23:33:35 -0300 Subject: [PATCH 2/7] Pass export_options individually to VBoxManage export --- builder/virtualbox/common/step_export.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/builder/virtualbox/common/step_export.go b/builder/virtualbox/common/step_export.go index c17f8cd0b..6967af1fe 100644 --- a/builder/virtualbox/common/step_export.go +++ b/builder/virtualbox/common/step_export.go @@ -6,6 +6,7 @@ import ( "github.com/mitchellh/packer/packer" "log" "path/filepath" + "strings" "time" ) @@ -51,9 +52,10 @@ func (s *StepExport) Run(state multistep.StateBag) multistep.StepAction { vmName, "--output", outputPath, - s.ExportOpts, } + command = append(command, strings.Fields(s.ExportOpts)...) + ui.Say("Exporting virtual machine...") err := driver.VBoxManage(command...) if err != nil { From bfd675585975541fda5b1eb761be08c931f66962 Mon Sep 17 00:00:00 2001 From: Ben Langfeld Date: Fri, 14 Mar 2014 00:12:50 -0300 Subject: [PATCH 3/7] Move to an array of strings for a deterministic option separation --- builder/virtualbox/common/export_opts.go | 12 ++++++------ builder/virtualbox/common/step_export.go | 5 ++--- .../docs/builders/virtualbox-iso.html.markdown | 2 +- .../docs/builders/virtualbox-ovf.html.markdown | 2 +- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/builder/virtualbox/common/export_opts.go b/builder/virtualbox/common/export_opts.go index 1794823f4..4ae133dcd 100644 --- a/builder/virtualbox/common/export_opts.go +++ b/builder/virtualbox/common/export_opts.go @@ -6,20 +6,20 @@ import ( ) type ExportOpts struct { - ExportOpts string `mapstructure:"export_opts"` + ExportOpts []string `mapstructure:"export_opts"` } func (c *ExportOpts) Prepare(t *packer.ConfigTemplate) []error { - templates := map[string]*string{ - "export_opts": &c.ExportOpts, + if c.ExportOpts == nil { + c.ExportOpts = make([]string, 0) } errs := make([]error, 0) - for n, ptr := range templates { + for _, str := range c.ExportOpts { var err error - *ptr, err = t.Process(*ptr, nil) + str, err = t.Process(str, nil) if err != nil { - errs = append(errs, fmt.Errorf("Error processing %s: %s", n, err)) + errs = append(errs, fmt.Errorf("Error processing %s: %s", "export_opts", err)) } } diff --git a/builder/virtualbox/common/step_export.go b/builder/virtualbox/common/step_export.go index 6967af1fe..756530572 100644 --- a/builder/virtualbox/common/step_export.go +++ b/builder/virtualbox/common/step_export.go @@ -6,7 +6,6 @@ import ( "github.com/mitchellh/packer/packer" "log" "path/filepath" - "strings" "time" ) @@ -19,7 +18,7 @@ import ( type StepExport struct { Format string OutputDir string - ExportOpts string + ExportOpts []string } func (s *StepExport) Run(state multistep.StateBag) multistep.StepAction { @@ -54,7 +53,7 @@ func (s *StepExport) Run(state multistep.StateBag) multistep.StepAction { outputPath, } - command = append(command, strings.Fields(s.ExportOpts)...) + command = append(command, s.ExportOpts...) ui.Say("Exporting virtual machine...") err := driver.VBoxManage(command...) diff --git a/website/source/docs/builders/virtualbox-iso.html.markdown b/website/source/docs/builders/virtualbox-iso.html.markdown index 2f417dca0..49a16f3e2 100644 --- a/website/source/docs/builders/virtualbox-iso.html.markdown +++ b/website/source/docs/builders/virtualbox-iso.html.markdown @@ -211,7 +211,7 @@ Optional: machine, without the file extension. By default this is "packer-BUILDNAME", where "BUILDNAME" is the name of the build. -* `export_opts` (string) - Additional options to pass to the `VBoxManage export`. +* `export_opts` (array of strings) - Additional options to pass to the `VBoxManage export`. This can be useful for passing product information to include in the resulting appliance file. diff --git a/website/source/docs/builders/virtualbox-ovf.html.markdown b/website/source/docs/builders/virtualbox-ovf.html.markdown index 47378e6c2..6bf6e49d9 100644 --- a/website/source/docs/builders/virtualbox-ovf.html.markdown +++ b/website/source/docs/builders/virtualbox-ovf.html.markdown @@ -151,7 +151,7 @@ Optional: This can be useful for passing "keepallmacs" or "keepnatmacs" options for existing ovf images. -* `export_opts` (string) - Additional options to pass to the `VBoxManage export`. +* `export_opts` (array of strings) - Additional options to pass to the `VBoxManage export`. This can be useful for passing product information to include in the resulting appliance file. From 2cee7a5c10579d7d91c99d93f9759e842033bd2b Mon Sep 17 00:00:00 2001 From: Ben Langfeld Date: Fri, 14 Mar 2014 00:26:26 -0300 Subject: [PATCH 4/7] Log export command being executed --- builder/virtualbox/common/step_export.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/builder/virtualbox/common/step_export.go b/builder/virtualbox/common/step_export.go index 756530572..5c5d4c887 100644 --- a/builder/virtualbox/common/step_export.go +++ b/builder/virtualbox/common/step_export.go @@ -7,6 +7,7 @@ import ( "log" "path/filepath" "time" + "strings" ) // This step cleans up forwarded ports and exports the VM to an OVF. @@ -56,6 +57,7 @@ func (s *StepExport) Run(state multistep.StateBag) multistep.StepAction { command = append(command, s.ExportOpts...) ui.Say("Exporting virtual machine...") + ui.Message(fmt.Sprintf("Executing: %s", strings.Join(command, " "))) err := driver.VBoxManage(command...) if err != nil { err := fmt.Errorf("Error exporting virtual machine: %s", err) From 8cf0e53b197daed3f525852eba48a2759469e4fa Mon Sep 17 00:00:00 2001 From: Ben Langfeld Date: Fri, 14 Mar 2014 13:22:32 -0300 Subject: [PATCH 5/7] Properly apply templates to export opts --- builder/virtualbox/common/export_opts.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/builder/virtualbox/common/export_opts.go b/builder/virtualbox/common/export_opts.go index 4ae133dcd..36006aec6 100644 --- a/builder/virtualbox/common/export_opts.go +++ b/builder/virtualbox/common/export_opts.go @@ -15,9 +15,9 @@ func (c *ExportOpts) Prepare(t *packer.ConfigTemplate) []error { } errs := make([]error, 0) - for _, str := range c.ExportOpts { + for i, str := range c.ExportOpts { var err error - str, err = t.Process(str, nil) + c.ExportOpts[i], err = t.Process(str, nil) if err != nil { errs = append(errs, fmt.Errorf("Error processing %s: %s", "export_opts", err)) } From 5b07e2604c7dd1e9ca9a5bdae6df529b260c08f1 Mon Sep 17 00:00:00 2001 From: Ben Langfeld Date: Fri, 14 Mar 2014 13:22:44 -0300 Subject: [PATCH 6/7] Fix export opts tests --- builder/virtualbox/common/export_opts_test.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/builder/virtualbox/common/export_opts_test.go b/builder/virtualbox/common/export_opts_test.go index b86d0eb40..16703633d 100644 --- a/builder/virtualbox/common/export_opts_test.go +++ b/builder/virtualbox/common/export_opts_test.go @@ -10,7 +10,9 @@ func TestExportOptsPrepare_BootWait(t *testing.T) { // Good c = new(ExportOpts) - c.ExportOpts = "ovf" + c.ExportOpts = []string{ + "--options", + } errs = c.Prepare(testConfigTemplate(t)) if len(errs) > 0 { t.Fatalf("should not have error: %s", errs) From 128f555a2c1415ae5a8c7129404f9b21f8c8c026 Mon Sep 17 00:00:00 2001 From: Ben Langfeld Date: Fri, 14 Mar 2014 13:22:49 -0300 Subject: [PATCH 7/7] Formatting --- builder/virtualbox/common/step_export.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/virtualbox/common/step_export.go b/builder/virtualbox/common/step_export.go index 5c5d4c887..e4e860155 100644 --- a/builder/virtualbox/common/step_export.go +++ b/builder/virtualbox/common/step_export.go @@ -6,8 +6,8 @@ import ( "github.com/mitchellh/packer/packer" "log" "path/filepath" - "time" "strings" + "time" ) // This step cleans up forwarded ports and exports the VM to an OVF.