Add ability to run vboxmanage commands just before exporting [GH-664]

This commit is contained in:
Jacob Helwig 2014-03-12 16:14:44 -07:00
parent bb8d0a5e7a
commit 38e880a187
7 changed files with 105 additions and 20 deletions

View File

@ -0,0 +1,28 @@
package common
import (
"fmt"
"github.com/mitchellh/packer/packer"
)
type VBoxManagePostConfig struct {
VBoxManagePost [][]string `mapstructure:"vboxmanage_post"`
}
func (c *VBoxManagePostConfig) Prepare(t *packer.ConfigTemplate) []error {
if c.VBoxManagePost == nil {
c.VBoxManagePost = make([][]string, 0)
}
errs := make([]error, 0)
for i, args := range c.VBoxManagePost {
for j, arg := range args {
if err := t.Validate(arg); err != nil {
errs = append(errs,
fmt.Errorf("Error processing vboxmanage_post[%d][%d]: %s", i, j, err))
}
}
}
return errs
}

View File

@ -0,0 +1,37 @@
package common
import (
"reflect"
"testing"
)
func TestVBoxManagePostConfigPrepare_VBoxManage(t *testing.T) {
// Test with empty
c := new(VBoxManagePostConfig)
errs := c.Prepare(testConfigTemplate(t))
if len(errs) > 0 {
t.Fatalf("err: %#v", errs)
}
if !reflect.DeepEqual(c.VBoxManagePost, [][]string{}) {
t.Fatalf("bad: %#v", c.VBoxManagePost)
}
// Test with a good one
c = new(VBoxManagePostConfig)
c.VBoxManagePost = [][]string{
{"foo", "bar", "baz"},
}
errs = c.Prepare(testConfigTemplate(t))
if len(errs) > 0 {
t.Fatalf("err: %#v", errs)
}
expected := [][]string{
[]string{"foo", "bar", "baz"},
}
if !reflect.DeepEqual(c.VBoxManagePost, expected) {
t.Fatalf("bad: %#v", c.VBoxManagePost)
}
}

View File

@ -27,16 +27,17 @@ type Builder struct {
} }
type config struct { type config struct {
common.PackerConfig `mapstructure:",squash"` common.PackerConfig `mapstructure:",squash"`
vboxcommon.ExportConfig `mapstructure:",squash"` vboxcommon.ExportConfig `mapstructure:",squash"`
vboxcommon.ExportOpts `mapstructure:",squash"` vboxcommon.ExportOpts `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"`
vboxcommon.ShutdownConfig `mapstructure:",squash"` vboxcommon.ShutdownConfig `mapstructure:",squash"`
vboxcommon.SSHConfig `mapstructure:",squash"` vboxcommon.SSHConfig `mapstructure:",squash"`
vboxcommon.VBoxManageConfig `mapstructure:",squash"` vboxcommon.VBoxManageConfig `mapstructure:",squash"`
vboxcommon.VBoxVersionConfig `mapstructure:",squash"` vboxcommon.VBoxManagePostConfig `mapstructure:",squash"`
vboxcommon.VBoxVersionConfig `mapstructure:",squash"`
BootCommand []string `mapstructure:"boot_command"` BootCommand []string `mapstructure:"boot_command"`
DiskSize uint `mapstructure:"disk_size"` DiskSize uint `mapstructure:"disk_size"`
@ -82,6 +83,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
errs = packer.MultiErrorAppend(errs, b.config.ShutdownConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.ShutdownConfig.Prepare(b.config.tpl)...)
errs = packer.MultiErrorAppend(errs, b.config.SSHConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.SSHConfig.Prepare(b.config.tpl)...)
errs = packer.MultiErrorAppend(errs, b.config.VBoxManageConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.VBoxManageConfig.Prepare(b.config.tpl)...)
errs = packer.MultiErrorAppend(errs, b.config.VBoxManagePostConfig.Prepare(b.config.tpl)...)
errs = packer.MultiErrorAppend(errs, b.config.VBoxVersionConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.VBoxVersionConfig.Prepare(b.config.tpl)...)
warnings := make([]string, 0) warnings := make([]string, 0)
@ -318,6 +320,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.StepVBoxManage{
Commands: b.config.VBoxManagePost,
Tpl: b.config.tpl,
},
&vboxcommon.StepExport{ &vboxcommon.StepExport{
Format: b.config.Format, Format: b.config.Format,
OutputDir: b.config.OutputDir, OutputDir: b.config.OutputDir,

View File

@ -94,6 +94,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.StepVBoxManage{
Commands: b.config.VBoxManagePost,
Tpl: b.config.tpl,
},
&vboxcommon.StepExport{ &vboxcommon.StepExport{
Format: b.config.Format, Format: b.config.Format,
OutputDir: b.config.OutputDir, OutputDir: b.config.OutputDir,

View File

@ -11,16 +11,17 @@ 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.ExportConfig `mapstructure:",squash"`
vboxcommon.ExportOpts `mapstructure:",squash"` vboxcommon.ExportOpts `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"`
vboxcommon.SSHConfig `mapstructure:",squash"` vboxcommon.SSHConfig `mapstructure:",squash"`
vboxcommon.ShutdownConfig `mapstructure:",squash"` vboxcommon.ShutdownConfig `mapstructure:",squash"`
vboxcommon.VBoxManageConfig `mapstructure:",squash"` vboxcommon.VBoxManageConfig `mapstructure:",squash"`
vboxcommon.VBoxVersionConfig `mapstructure:",squash"` vboxcommon.VBoxManagePostConfig `mapstructure:",squash"`
vboxcommon.VBoxVersionConfig `mapstructure:",squash"`
SourcePath string `mapstructure:"source_path"` SourcePath string `mapstructure:"source_path"`
VMName string `mapstructure:"vm_name"` VMName string `mapstructure:"vm_name"`
@ -57,6 +58,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
errs = packer.MultiErrorAppend(errs, c.ShutdownConfig.Prepare(c.tpl)...) errs = packer.MultiErrorAppend(errs, c.ShutdownConfig.Prepare(c.tpl)...)
errs = packer.MultiErrorAppend(errs, c.SSHConfig.Prepare(c.tpl)...) errs = packer.MultiErrorAppend(errs, c.SSHConfig.Prepare(c.tpl)...)
errs = packer.MultiErrorAppend(errs, c.VBoxManageConfig.Prepare(c.tpl)...) errs = packer.MultiErrorAppend(errs, c.VBoxManageConfig.Prepare(c.tpl)...)
errs = packer.MultiErrorAppend(errs, c.VBoxManagePostConfig.Prepare(c.tpl)...)
errs = packer.MultiErrorAppend(errs, c.VBoxVersionConfig.Prepare(c.tpl)...) errs = packer.MultiErrorAppend(errs, c.VBoxVersionConfig.Prepare(c.tpl)...)
templates := map[string]*string{ templates := map[string]*string{

View File

@ -201,6 +201,10 @@ Optional:
where the `Name` variable is replaced with the VM name. More details on how where the `Name` variable is replaced with the VM name. More details on how
to use `VBoxManage` are below. to use `VBoxManage` are below.
* `vboxmanage_post` (array of array of strings) - Identical to `vboxmanage`,
except that it is run after the virtual machine is shutdown, and before the
virtual machine is exported.
* `virtualbox_version_file` (string) - The path within the virtual machine * `virtualbox_version_file` (string) - The path within the virtual machine
to upload a file that contains the VirtualBox version that was used to to upload a file that contains the VirtualBox version that was used to
create the machine. This information can be useful for provisioning. create the machine. This information can be useful for provisioning.

View File

@ -136,6 +136,10 @@ Optional:
where the `Name` variable is replaced with the VM name. More details on how where the `Name` variable is replaced with the VM name. More details on how
to use `VBoxManage` are below. to use `VBoxManage` are below.
* `vboxmanage_post` (array of array of strings) - Identical to `vboxmanage`,
except that it is run after the virtual machine is shutdown, and before the
virtual machine is exported.
* `virtualbox_version_file` (string) - The path within the virtual machine * `virtualbox_version_file` (string) - The path within the virtual machine
to upload a file that contains the VirtualBox version that was used to to upload a file that contains the VirtualBox version that was used to
create the machine. This information can be useful for provisioning. create the machine. This information can be useful for provisioning.