Commit 5feb7bce authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

builder/virtualbox/common: Export

parent 026bcd33
package common
import (
"errors"
"fmt"
"github.com/mitchellh/packer/packer"
)
type ExportConfig struct {
Format string `mapstruture:"format"`
}
func (c *ExportConfig) Prepare(t *packer.ConfigTemplate) []error {
if c.Format == "" {
c.Format = "ovf"
}
templates := map[string]*string{
"format": &c.Format,
}
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))
}
}
if c.Format != "ovf" && c.Format != "ova" {
errs = append(errs,
errors.New("invalid format, only 'ovf' or 'ova' are allowed"))
}
return errs
}
package common
import (
"testing"
)
func TestExportConfigPrepare_BootWait(t *testing.T) {
var c *ExportConfig
var errs []error
// Bad
c = new(ExportConfig)
c.Format = "illega"
errs = c.Prepare(testConfigTemplate(t))
if len(errs) == 0 {
t.Fatalf("bad: %#v", errs)
}
// Good
c = new(ExportConfig)
c.Format = "ova"
errs = c.Prepare(testConfigTemplate(t))
if len(errs) > 0 {
t.Fatalf("should not have error: %s", errs)
}
// Good
c = new(ExportConfig)
c.Format = "ovf"
errs = c.Prepare(testConfigTemplate(t))
if len(errs) > 0 {
t.Fatalf("should not have error: %s", errs)
}
}
package iso package common
import ( import (
"fmt" "fmt"
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
vboxcommon "github.com/mitchellh/packer/builder/virtualbox/common"
"github.com/mitchellh/packer/packer" "github.com/mitchellh/packer/packer"
"log" "log"
"path/filepath" "path/filepath"
...@@ -16,11 +15,13 @@ import ( ...@@ -16,11 +15,13 @@ import (
// //
// Produces: // Produces:
// exportPath string - The path to the resulting export. // exportPath string - The path to the resulting export.
type stepExport struct{} type StepExport struct {
Format string
OutputDir string
}
func (s *stepExport) Run(state multistep.StateBag) multistep.StepAction { func (s *StepExport) Run(state multistep.StateBag) multistep.StepAction {
config := state.Get("config").(*config) driver := state.Get("driver").(Driver)
driver := state.Get("driver").(vboxcommon.Driver)
ui := state.Get("ui").(packer.Ui) ui := state.Get("ui").(packer.Ui)
vmName := state.Get("vmName").(string) vmName := state.Get("vmName").(string)
...@@ -42,7 +43,7 @@ func (s *stepExport) Run(state multistep.StateBag) multistep.StepAction { ...@@ -42,7 +43,7 @@ func (s *stepExport) Run(state multistep.StateBag) multistep.StepAction {
} }
// Export the VM to an OVF // Export the VM to an OVF
outputPath := filepath.Join(config.OutputDir, vmName+"."+config.Format) outputPath := filepath.Join(s.OutputDir, vmName+"."+s.Format)
command = []string{ command = []string{
"export", "export",
...@@ -65,4 +66,4 @@ func (s *stepExport) Run(state multistep.StateBag) multistep.StepAction { ...@@ -65,4 +66,4 @@ func (s *stepExport) Run(state multistep.StateBag) multistep.StepAction {
return multistep.ActionContinue return multistep.ActionContinue
} }
func (s *stepExport) Cleanup(state multistep.StateBag) {} func (s *StepExport) Cleanup(state multistep.StateBag) {}
package common
import (
"github.com/mitchellh/multistep"
"testing"
)
func TestStepExport_impl(t *testing.T) {
var _ multistep.Step = new(StepExport)
}
func TestStepExport(t *testing.T) {
state := testState(t)
step := new(StepExport)
state.Put("vmName", "foo")
driver := state.Get("driver").(*DriverMock)
// Test the run
if action := step.Run(state); action != multistep.ActionContinue {
t.Fatalf("bad action: %#v", action)
}
if _, ok := state.GetOk("error"); ok {
t.Fatal("should NOT have error")
}
// Test output state
if _, ok := state.GetOk("exportPath"); !ok {
t.Fatal("should set exportPath")
}
// Test driver
if len(driver.VBoxManageCalls) != 2 {
t.Fatal("should call vboxmanage")
}
if driver.VBoxManageCalls[0][0] != "modifyvm" {
t.Fatal("bad")
}
if driver.VBoxManageCalls[1][0] != "export" {
t.Fatal("bad")
}
}
...@@ -28,6 +28,7 @@ type Builder struct { ...@@ -28,6 +28,7 @@ type Builder struct {
type config struct { type config struct {
common.PackerConfig `mapstructure:",squash"` common.PackerConfig `mapstructure:",squash"`
vboxcommon.ExportConfig `mapstructure:",squash"`
vboxcommon.FloppyConfig `mapstructure:",squash"` vboxcommon.FloppyConfig `mapstructure:",squash"`
vboxcommon.OutputConfig `mapstructure:",squash"` vboxcommon.OutputConfig `mapstructure:",squash"`
vboxcommon.RunConfig `mapstructure:",squash"` vboxcommon.RunConfig `mapstructure:",squash"`
...@@ -37,7 +38,6 @@ type config struct { ...@@ -37,7 +38,6 @@ type config struct {
BootCommand []string `mapstructure:"boot_command"` BootCommand []string `mapstructure:"boot_command"`
DiskSize uint `mapstructure:"disk_size"` DiskSize uint `mapstructure:"disk_size"`
Format string `mapstructure:"format"`
GuestAdditionsMode string `mapstructure:"guest_additions_mode"` GuestAdditionsMode string `mapstructure:"guest_additions_mode"`
GuestAdditionsPath string `mapstructure:"guest_additions_path"` GuestAdditionsPath string `mapstructure:"guest_additions_path"`
GuestAdditionsURL string `mapstructure:"guest_additions_url"` GuestAdditionsURL string `mapstructure:"guest_additions_url"`
...@@ -72,6 +72,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { ...@@ -72,6 +72,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
// Accumulate any errors and warnings // Accumulate any errors and warnings
errs := common.CheckUnusedConfig(md) errs := common.CheckUnusedConfig(md)
errs = packer.MultiErrorAppend(errs, b.config.ExportConfig.Prepare(b.config.tpl)...)
errs = packer.MultiErrorAppend(errs, b.config.FloppyConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.FloppyConfig.Prepare(b.config.tpl)...)
errs = packer.MultiErrorAppend( errs = packer.MultiErrorAppend(
errs, b.config.OutputConfig.Prepare(b.config.tpl, &b.config.PackerConfig)...) errs, b.config.OutputConfig.Prepare(b.config.tpl, &b.config.PackerConfig)...)
...@@ -116,10 +117,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { ...@@ -116,10 +117,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName) b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName)
} }
if b.config.Format == "" {
b.config.Format = "ovf"
}
// Errors // Errors
templates := map[string]*string{ templates := map[string]*string{
"guest_additions_mode": &b.config.GuestAdditionsMode, "guest_additions_mode": &b.config.GuestAdditionsMode,
...@@ -132,7 +129,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { ...@@ -132,7 +129,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
"iso_url": &b.config.RawSingleISOUrl, "iso_url": &b.config.RawSingleISOUrl,
"virtualbox_version_file": &b.config.VBoxVersionFile, "virtualbox_version_file": &b.config.VBoxVersionFile,
"vm_name": &b.config.VMName, "vm_name": &b.config.VMName,
"format": &b.config.Format,
} }
for n, ptr := range templates { for n, ptr := range templates {
...@@ -172,11 +168,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { ...@@ -172,11 +168,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
} }
} }
if !(b.config.Format == "ovf" || b.config.Format == "ova") {
errs = packer.MultiErrorAppend(
errs, errors.New("invalid format, only 'ovf' or 'ova' are allowed"))
}
if b.config.HardDriveInterface != "ide" && b.config.HardDriveInterface != "sata" { if b.config.HardDriveInterface != "ide" && b.config.HardDriveInterface != "sata" {
errs = packer.MultiErrorAppend( errs = packer.MultiErrorAppend(
errs, errors.New("hard_drive_interface can only be ide or sata")) errs, errors.New("hard_drive_interface can only be ide or sata"))
...@@ -317,7 +308,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe ...@@ -317,7 +308,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
Timeout: b.config.ShutdownTimeout, Timeout: b.config.ShutdownTimeout,
}, },
new(vboxcommon.StepRemoveDevices), new(vboxcommon.StepRemoveDevices),
new(stepExport), &vboxcommon.StepExport{
Format: b.config.Format,
OutputDir: b.config.OutputDir,
},
} }
// Setup the state bag // Setup the state bag
......
...@@ -299,43 +299,6 @@ func TestBuilderPrepare_HTTPPort(t *testing.T) { ...@@ -299,43 +299,6 @@ func TestBuilderPrepare_HTTPPort(t *testing.T) {
} }
} }
func TestBuilderPrepare_Format(t *testing.T) {
var b Builder
config := testConfig()
// Bad
config["format"] = "illegal value"
warns, err := b.Prepare(config)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err == nil {
t.Fatal("should have error")
}
// Good
config["format"] = "ova"
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)
}
// Good
config["format"] = "ovf"
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)
}
}
func TestBuilderPrepare_InvalidKey(t *testing.T) { func TestBuilderPrepare_InvalidKey(t *testing.T) {
var b Builder var b Builder
config := testConfig() config := testConfig()
......
...@@ -81,9 +81,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe ...@@ -81,9 +81,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
Timeout: b.config.ShutdownTimeout, Timeout: b.config.ShutdownTimeout,
}, },
new(vboxcommon.StepRemoveDevices), new(vboxcommon.StepRemoveDevices),
/* &vboxcommon.StepExport{
new(stepExport), Format: b.config.Format,
*/ OutputDir: b.config.OutputDir,
},
} }
// Run the steps. // Run the steps.
......
...@@ -9,6 +9,7 @@ import ( ...@@ -9,6 +9,7 @@ import (
// Config is the configuration structure for the builder. // Config is the configuration structure for the builder.
type Config struct { type Config struct {
common.PackerConfig `mapstructure:",squash"` common.PackerConfig `mapstructure:",squash"`
vboxcommon.ExportConfig `mapstructure:",squash"`
vboxcommon.FloppyConfig `mapstructure:",squash"` vboxcommon.FloppyConfig `mapstructure:",squash"`
vboxcommon.OutputConfig `mapstructure:",squash"` vboxcommon.OutputConfig `mapstructure:",squash"`
vboxcommon.RunConfig `mapstructure:",squash"` vboxcommon.RunConfig `mapstructure:",squash"`
...@@ -34,6 +35,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { ...@@ -34,6 +35,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
// Prepare the errors // Prepare the errors
errs := common.CheckUnusedConfig(md) errs := common.CheckUnusedConfig(md)
errs = packer.MultiErrorAppend(errs, c.ExportConfig.Prepare(c.tpl)...)
errs = packer.MultiErrorAppend(errs, c.FloppyConfig.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.OutputConfig.Prepare(c.tpl, &c.PackerConfig)...)
errs = packer.MultiErrorAppend(errs, c.RunConfig.Prepare(c.tpl)...) errs = packer.MultiErrorAppend(errs, c.RunConfig.Prepare(c.tpl)...)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment