Commit 38e880a1 authored by Jacob Helwig's avatar Jacob Helwig

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

parent bb8d0a5e
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
}
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)
}
}
...@@ -27,16 +27,17 @@ type Builder struct { ...@@ -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) { ...@@ -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 ...@@ -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,
......
...@@ -94,6 +94,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe ...@@ -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,
......
...@@ -11,16 +11,17 @@ import ( ...@@ -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) { ...@@ -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{
......
...@@ -201,6 +201,10 @@ Optional: ...@@ -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.
......
...@@ -136,6 +136,10 @@ Optional: ...@@ -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.
......
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