From 73eda085400b63463a144f92de5194707390c286 Mon Sep 17 00:00:00 2001 From: Megan Marsh Date: Tue, 5 May 2020 16:09:05 -0700 Subject: [PATCH 1/4] allow user defined output filename --- builder/virtualbox/common/output_config.go | 4 ++++ builder/virtualbox/common/step_export.go | 6 +++++- builder/virtualbox/iso/builder.go | 1 + builder/virtualbox/ovf/builder.go | 1 + builder/virtualbox/vm/builder.go | 1 + 5 files changed, 12 insertions(+), 1 deletion(-) diff --git a/builder/virtualbox/common/output_config.go b/builder/virtualbox/common/output_config.go index e99919dcb..aedfa5cf7 100644 --- a/builder/virtualbox/common/output_config.go +++ b/builder/virtualbox/common/output_config.go @@ -17,6 +17,10 @@ type OutputConfig struct { // the builder. By default this is output-BUILDNAME where "BUILDNAME" is the // name of the build. OutputDir string `mapstructure:"output_directory" required:"false"` + // This is the base name of the file (excluding the file extension) where + // the resulting virtual machine will be created. By default this is the + // `vm_name`. + OutputFilename string `mapstructure:"output_filename" required:"false"` } func (c *OutputConfig) Prepare(ctx *interpolate.Context, pc *common.PackerConfig) []error { diff --git a/builder/virtualbox/common/step_export.go b/builder/virtualbox/common/step_export.go index 57e5bed2f..7a3dd13f4 100644 --- a/builder/virtualbox/common/step_export.go +++ b/builder/virtualbox/common/step_export.go @@ -19,6 +19,7 @@ import ( type StepExport struct { Format string OutputDir string + OutputFilename string ExportOpts []string Bundling VBoxBundleConfig SkipNatMapping bool @@ -37,6 +38,9 @@ func (s *StepExport) Run(ctx context.Context, state multistep.StateBag) multiste driver := state.Get("driver").(Driver) ui := state.Get("ui").(packer.Ui) vmName := state.Get("vmName").(string) + if s.OutputFilename == "" { + s.OutputFilename = vmName + } // Skip export if requested if s.SkipExport { @@ -61,7 +65,7 @@ func (s *StepExport) Run(ctx context.Context, state multistep.StateBag) multiste } // Export the VM to an OVF - outputPath := filepath.Join(s.OutputDir, vmName+"."+s.Format) + outputPath := filepath.Join(s.OutputDir, s.OutputFilename+"."+s.Format) command := []string{ "export", diff --git a/builder/virtualbox/iso/builder.go b/builder/virtualbox/iso/builder.go index a52837203..805e4a287 100644 --- a/builder/virtualbox/iso/builder.go +++ b/builder/virtualbox/iso/builder.go @@ -396,6 +396,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack &vboxcommon.StepExport{ Format: b.config.Format, OutputDir: b.config.OutputDir, + OutputFilename: b.config.OutputFilename, ExportOpts: b.config.ExportConfig.ExportOpts, Bundling: b.config.VBoxBundleConfig, SkipNatMapping: b.config.SkipNatMapping, diff --git a/builder/virtualbox/ovf/builder.go b/builder/virtualbox/ovf/builder.go index ab4b524cc..9ee156748 100644 --- a/builder/virtualbox/ovf/builder.go +++ b/builder/virtualbox/ovf/builder.go @@ -158,6 +158,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack &vboxcommon.StepExport{ Format: b.config.Format, OutputDir: b.config.OutputDir, + OutputFilename: b.config.OutputFilename, ExportOpts: b.config.ExportConfig.ExportOpts, SkipNatMapping: b.config.SkipNatMapping, SkipExport: b.config.SkipExport, diff --git a/builder/virtualbox/vm/builder.go b/builder/virtualbox/vm/builder.go index f8f493d60..2efa4d37a 100644 --- a/builder/virtualbox/vm/builder.go +++ b/builder/virtualbox/vm/builder.go @@ -141,6 +141,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack &vboxcommon.StepExport{ Format: b.config.Format, OutputDir: b.config.OutputDir, + OutputFilename: b.config.OutputFilename, ExportOpts: b.config.ExportOpts, SkipNatMapping: b.config.SkipNatMapping, SkipExport: b.config.SkipExport, From 2e2374b6be16edc6811c71abfa15bfcc73e46d36 Mon Sep 17 00:00:00 2001 From: Megan Marsh Date: Tue, 5 May 2020 18:52:31 -0700 Subject: [PATCH 2/4] add tests --- builder/virtualbox/common/step_export_test.go | 68 +++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/builder/virtualbox/common/step_export_test.go b/builder/virtualbox/common/step_export_test.go index 6d37b3150..366515d07 100644 --- a/builder/virtualbox/common/step_export_test.go +++ b/builder/virtualbox/common/step_export_test.go @@ -43,3 +43,71 @@ func TestStepExport(t *testing.T) { t.Fatal("bad") } } + +func TestStepExport_OutputPath(t *testing.T) { + type testCase struct { + Step *StepExport + Expected string + Reason string + } + tcs := []testCase{ + { + Step: &StepExport{ + Format: "ova", + OutputDir: "output-dir", + OutputFilename: "output-filename", + }, + Expected: "output-dir/output-filename.ova", + Reason: "output_filename should not be vmName if set.", + }, + { + Step: &StepExport{ + Format: "ovf", + OutputDir: "output-dir", + OutputFilename: "", + }, + Expected: "output-dir/foo.ovf", + Reason: "output_filename should default to vmName.", + }, + } + for _, tc := range tcs { + state := testState(t) + state.Put("vmName", "foo") + + // Test the run + if action := tc.Step.Run(context.Background(), state); action != multistep.ActionContinue { + t.Fatalf("bad action: %#v", action) + } + + // Test output state + path, ok := state.GetOk("exportPath") + if !ok { + t.Fatal("should set exportPath") + } + if path != tc.Expected { + t.Fatalf("Expected %s didn't match received %s: %s", tc.Expected, path, tc.Reason) + } + } +} + +func TestStepExport_SkipExport(t *testing.T) { + state := testState(t) + step := StepExport{SkipExport: true} + + state.Put("vmName", "foo") + + driver := state.Get("driver").(*DriverMock) + + // Test the run + if action := step.Run(context.Background(), state); action != multistep.ActionContinue { + t.Fatalf("bad action: %#v", action) + } + if _, ok := state.GetOk("error"); ok { + t.Fatal("should NOT have error") + } + // Test driver + if len(driver.VBoxManageCalls) != 0 { + t.Fatal("shouldn't have called vboxmanage; skip_export was set.") + } + +} From aa09c5205950ed02e227951c0335cd8f6c4da7f4 Mon Sep 17 00:00:00 2001 From: Megan Marsh Date: Wed, 6 May 2020 09:23:15 -0700 Subject: [PATCH 3/4] generated docs --- builder/virtualbox/iso/builder.hcl2spec.go | 2 ++ builder/virtualbox/ovf/config.hcl2spec.go | 2 ++ builder/virtualbox/vm/config.hcl2spec.go | 2 ++ .../builder/virtualbox/common/OutputConfig-not-required.mdx | 4 ++++ 4 files changed, 10 insertions(+) diff --git a/builder/virtualbox/iso/builder.hcl2spec.go b/builder/virtualbox/iso/builder.hcl2spec.go index 017359cdb..c633840f4 100644 --- a/builder/virtualbox/iso/builder.hcl2spec.go +++ b/builder/virtualbox/iso/builder.hcl2spec.go @@ -35,6 +35,7 @@ type FlatConfig struct { Format *string `mapstructure:"format" required:"false" cty:"format"` ExportOpts []string `mapstructure:"export_opts" required:"false" cty:"export_opts"` OutputDir *string `mapstructure:"output_directory" required:"false" cty:"output_directory"` + OutputFilename *string `mapstructure:"output_filename" required:"false" cty:"output_filename"` Headless *bool `mapstructure:"headless" required:"false" cty:"headless"` VRDPBindAddress *string `mapstructure:"vrdp_bind_address" required:"false" cty:"vrdp_bind_address"` VRDPPortMin *int `mapstructure:"vrdp_port_min" required:"false" cty:"vrdp_port_min"` @@ -156,6 +157,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "format": &hcldec.AttrSpec{Name: "format", Type: cty.String, Required: false}, "export_opts": &hcldec.AttrSpec{Name: "export_opts", Type: cty.List(cty.String), Required: false}, "output_directory": &hcldec.AttrSpec{Name: "output_directory", Type: cty.String, Required: false}, + "output_filename": &hcldec.AttrSpec{Name: "output_filename", Type: cty.String, Required: false}, "headless": &hcldec.AttrSpec{Name: "headless", Type: cty.Bool, Required: false}, "vrdp_bind_address": &hcldec.AttrSpec{Name: "vrdp_bind_address", Type: cty.String, Required: false}, "vrdp_port_min": &hcldec.AttrSpec{Name: "vrdp_port_min", Type: cty.Number, Required: false}, diff --git a/builder/virtualbox/ovf/config.hcl2spec.go b/builder/virtualbox/ovf/config.hcl2spec.go index f24a40a8f..d38495a9b 100644 --- a/builder/virtualbox/ovf/config.hcl2spec.go +++ b/builder/virtualbox/ovf/config.hcl2spec.go @@ -28,6 +28,7 @@ type FlatConfig struct { Format *string `mapstructure:"format" required:"false" cty:"format"` ExportOpts []string `mapstructure:"export_opts" required:"false" cty:"export_opts"` OutputDir *string `mapstructure:"output_directory" required:"false" cty:"output_directory"` + OutputFilename *string `mapstructure:"output_filename" required:"false" cty:"output_filename"` Headless *bool `mapstructure:"headless" required:"false" cty:"headless"` VRDPBindAddress *string `mapstructure:"vrdp_bind_address" required:"false" cty:"vrdp_bind_address"` VRDPPortMin *int `mapstructure:"vrdp_port_min" required:"false" cty:"vrdp_port_min"` @@ -135,6 +136,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "format": &hcldec.AttrSpec{Name: "format", Type: cty.String, Required: false}, "export_opts": &hcldec.AttrSpec{Name: "export_opts", Type: cty.List(cty.String), Required: false}, "output_directory": &hcldec.AttrSpec{Name: "output_directory", Type: cty.String, Required: false}, + "output_filename": &hcldec.AttrSpec{Name: "output_filename", Type: cty.String, Required: false}, "headless": &hcldec.AttrSpec{Name: "headless", Type: cty.Bool, Required: false}, "vrdp_bind_address": &hcldec.AttrSpec{Name: "vrdp_bind_address", Type: cty.String, Required: false}, "vrdp_port_min": &hcldec.AttrSpec{Name: "vrdp_port_min", Type: cty.Number, Required: false}, diff --git a/builder/virtualbox/vm/config.hcl2spec.go b/builder/virtualbox/vm/config.hcl2spec.go index ede4b52ef..94d0e1a54 100644 --- a/builder/virtualbox/vm/config.hcl2spec.go +++ b/builder/virtualbox/vm/config.hcl2spec.go @@ -28,6 +28,7 @@ type FlatConfig struct { Format *string `mapstructure:"format" required:"false" cty:"format"` ExportOpts []string `mapstructure:"export_opts" required:"false" cty:"export_opts"` OutputDir *string `mapstructure:"output_directory" required:"false" cty:"output_directory"` + OutputFilename *string `mapstructure:"output_filename" required:"false" cty:"output_filename"` Headless *bool `mapstructure:"headless" required:"false" cty:"headless"` VRDPBindAddress *string `mapstructure:"vrdp_bind_address" required:"false" cty:"vrdp_bind_address"` VRDPPortMin *int `mapstructure:"vrdp_port_min" required:"false" cty:"vrdp_port_min"` @@ -131,6 +132,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "format": &hcldec.AttrSpec{Name: "format", Type: cty.String, Required: false}, "export_opts": &hcldec.AttrSpec{Name: "export_opts", Type: cty.List(cty.String), Required: false}, "output_directory": &hcldec.AttrSpec{Name: "output_directory", Type: cty.String, Required: false}, + "output_filename": &hcldec.AttrSpec{Name: "output_filename", Type: cty.String, Required: false}, "headless": &hcldec.AttrSpec{Name: "headless", Type: cty.Bool, Required: false}, "vrdp_bind_address": &hcldec.AttrSpec{Name: "vrdp_bind_address", Type: cty.String, Required: false}, "vrdp_port_min": &hcldec.AttrSpec{Name: "vrdp_port_min", Type: cty.Number, Required: false}, diff --git a/website/pages/partials/builder/virtualbox/common/OutputConfig-not-required.mdx b/website/pages/partials/builder/virtualbox/common/OutputConfig-not-required.mdx index 5794e6900..6fd36c64f 100644 --- a/website/pages/partials/builder/virtualbox/common/OutputConfig-not-required.mdx +++ b/website/pages/partials/builder/virtualbox/common/OutputConfig-not-required.mdx @@ -6,4 +6,8 @@ is executed. This directory must not exist or be empty prior to running the builder. By default this is output-BUILDNAME where "BUILDNAME" is the name of the build. + +- `output_filename` (string) - This is the base name of the file (excluding the file extension) where + the resulting virtual machine will be created. By default this is the + `vm_name`. \ No newline at end of file From 5b4de6b16f57050585998f8f282479e2e6e60101 Mon Sep 17 00:00:00 2001 From: Megan Marsh Date: Wed, 6 May 2020 09:27:20 -0700 Subject: [PATCH 4/4] fix tests --- builder/virtualbox/common/step_export_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/builder/virtualbox/common/step_export_test.go b/builder/virtualbox/common/step_export_test.go index 366515d07..c5adc0a45 100644 --- a/builder/virtualbox/common/step_export_test.go +++ b/builder/virtualbox/common/step_export_test.go @@ -2,6 +2,7 @@ package common import ( "context" + "path/filepath" "testing" "github.com/hashicorp/packer/helper/multistep" @@ -57,7 +58,7 @@ func TestStepExport_OutputPath(t *testing.T) { OutputDir: "output-dir", OutputFilename: "output-filename", }, - Expected: "output-dir/output-filename.ova", + Expected: filepath.Join("output-dir", "output-filename.ova"), Reason: "output_filename should not be vmName if set.", }, { @@ -66,7 +67,7 @@ func TestStepExport_OutputPath(t *testing.T) { OutputDir: "output-dir", OutputFilename: "", }, - Expected: "output-dir/foo.ovf", + Expected: filepath.Join("output-dir", "foo.ovf"), Reason: "output_filename should default to vmName.", }, }