From 1365627e3139792b59a042b21950891836ff1575 Mon Sep 17 00:00:00 2001 From: Rickard von Essen Date: Sun, 3 May 2015 11:18:48 +0200 Subject: [PATCH] Fixes #2080 Add prlctl_post in builder Parallels This adds config option prlctl_post for builder parallels-iso/pvm. It allows additional prlctl commands to run after the VM has been shutdown just before being exported. --- .../parallels/common/prlctl_post_config.go | 28 ++++++++++++++ .../common/prlctl_post_config_test.go | 37 +++++++++++++++++++ builder/parallels/iso/builder.go | 6 +++ builder/parallels/pvm/builder.go | 4 ++ builder/parallels/pvm/config.go | 2 + .../docs/builders/parallels-iso.html.markdown | 4 ++ .../docs/builders/parallels-pvm.html.markdown | 4 ++ 7 files changed, 85 insertions(+) create mode 100644 builder/parallels/common/prlctl_post_config.go create mode 100644 builder/parallels/common/prlctl_post_config_test.go diff --git a/builder/parallels/common/prlctl_post_config.go b/builder/parallels/common/prlctl_post_config.go new file mode 100644 index 000000000..23c2d5520 --- /dev/null +++ b/builder/parallels/common/prlctl_post_config.go @@ -0,0 +1,28 @@ +package common + +import ( + "fmt" + "github.com/mitchellh/packer/packer" +) + +type PrlctlPostConfig struct { + PrlctlPost [][]string `mapstructure:"prlctl_post"` +} + +func (c *PrlctlPostConfig) Prepare(t *packer.ConfigTemplate) []error { + if c.PrlctlPost == nil { + c.PrlctlPost = make([][]string, 0) + } + + errs := make([]error, 0) + for i, args := range c.PrlctlPost { + for j, arg := range args { + if err := t.Validate(arg); err != nil { + errs = append(errs, + fmt.Errorf("Error processing prlctl_post[%d][%d]: %s", i, j, err)) + } + } + } + + return errs +} diff --git a/builder/parallels/common/prlctl_post_config_test.go b/builder/parallels/common/prlctl_post_config_test.go new file mode 100644 index 000000000..c091a1a92 --- /dev/null +++ b/builder/parallels/common/prlctl_post_config_test.go @@ -0,0 +1,37 @@ +package common + +import ( + "reflect" + "testing" +) + +func TestPrlctlPostConfigPrepare_PrlctlPost(t *testing.T) { + // Test with empty + c := new(PrlctlPostConfig) + errs := c.Prepare(testConfigTemplate(t)) + if len(errs) > 0 { + t.Fatalf("err: %#v", errs) + } + + if !reflect.DeepEqual(c.PrlctlPost, [][]string{}) { + t.Fatalf("bad: %#v", c.PrlctlPost) + } + + // Test with a good one + c = new(PrlctlPostConfig) + c.PrlctlPost = [][]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.PrlctlPost, expected) { + t.Fatalf("bad: %#v", c.PrlctlPost) + } +} diff --git a/builder/parallels/iso/builder.go b/builder/parallels/iso/builder.go index e5e42e8e7..da3615dd3 100644 --- a/builder/parallels/iso/builder.go +++ b/builder/parallels/iso/builder.go @@ -23,6 +23,7 @@ type config struct { parallelscommon.FloppyConfig `mapstructure:",squash"` parallelscommon.OutputConfig `mapstructure:",squash"` parallelscommon.PrlctlConfig `mapstructure:",squash"` + parallelscommon.PrlctlPostConfig `mapstructure:",squash"` parallelscommon.PrlctlVersionConfig `mapstructure:",squash"` parallelscommon.RunConfig `mapstructure:",squash"` parallelscommon.ShutdownConfig `mapstructure:",squash"` @@ -71,6 +72,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { errs, b.config.OutputConfig.Prepare(b.config.tpl, &b.config.PackerConfig)...) errs = packer.MultiErrorAppend(errs, b.config.RunConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.PrlctlConfig.Prepare(b.config.tpl)...) + errs = packer.MultiErrorAppend(errs, b.config.PrlctlPostConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.PrlctlVersionConfig.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)...) @@ -295,6 +297,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe Command: b.config.ShutdownCommand, Timeout: b.config.ShutdownTimeout, }, + ¶llelscommon.StepPrlctl{ + Commands: b.config.PrlctlPost, + Tpl: b.config.tpl, + }, } // Setup the state bag diff --git a/builder/parallels/pvm/builder.go b/builder/parallels/pvm/builder.go index 037641619..e1b003406 100644 --- a/builder/parallels/pvm/builder.go +++ b/builder/parallels/pvm/builder.go @@ -99,6 +99,10 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe Command: b.config.ShutdownCommand, Timeout: b.config.ShutdownTimeout, }, + ¶llelscommon.StepPrlctl{ + Commands: b.config.PrlctlPost, + Tpl: b.config.tpl, + }, } // Run the steps. diff --git a/builder/parallels/pvm/config.go b/builder/parallels/pvm/config.go index 83e643111..dcd47fa82 100644 --- a/builder/parallels/pvm/config.go +++ b/builder/parallels/pvm/config.go @@ -15,6 +15,7 @@ type Config struct { parallelscommon.FloppyConfig `mapstructure:",squash"` parallelscommon.OutputConfig `mapstructure:",squash"` parallelscommon.PrlctlConfig `mapstructure:",squash"` + parallelscommon.PrlctlPostConfig `mapstructure:",squash"` parallelscommon.PrlctlVersionConfig `mapstructure:",squash"` parallelscommon.RunConfig `mapstructure:",squash"` parallelscommon.SSHConfig `mapstructure:",squash"` @@ -51,6 +52,7 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { 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.PrlctlConfig.Prepare(c.tpl)...) + errs = packer.MultiErrorAppend(errs, c.PrlctlPostConfig.Prepare(c.tpl)...) errs = packer.MultiErrorAppend(errs, c.PrlctlVersionConfig.Prepare(c.tpl)...) errs = packer.MultiErrorAppend(errs, c.RunConfig.Prepare(c.tpl)...) errs = packer.MultiErrorAppend(errs, c.ShutdownConfig.Prepare(c.tpl)...) diff --git a/website/source/docs/builders/parallels-iso.html.markdown b/website/source/docs/builders/parallels-iso.html.markdown index e0b1083be..46bf96b8a 100644 --- a/website/source/docs/builders/parallels-iso.html.markdown +++ b/website/source/docs/builders/parallels-iso.html.markdown @@ -170,6 +170,10 @@ each category, the available options are alphabetized and described. where the `Name` variable is replaced with the VM name. More details on how to use `prlctl` are below. +* `prlctl_post` (array of array of strings) - Identical to `prlctl`, + except that it is run after the virtual machine is shutdown, and before the + virtual machine is exported. + * `prlctl_version_file` (string) - The path within the virtual machine to upload a file that contains the `prlctl` version that was used to create the machine. This information can be useful for provisioning. By default this is diff --git a/website/source/docs/builders/parallels-pvm.html.markdown b/website/source/docs/builders/parallels-pvm.html.markdown index 9243d1f10..2a79c6b6b 100644 --- a/website/source/docs/builders/parallels-pvm.html.markdown +++ b/website/source/docs/builders/parallels-pvm.html.markdown @@ -113,6 +113,10 @@ each category, the available options are alphabetized and described. where the `Name` variable is replaced with the VM name. More details on how to use `prlctl` are below. +* `prlctl_post` (array of array of strings) - Identical to `prlctl`, + except that it is run after the virtual machine is shutdown, and before the + virtual machine is exported. + * `prlctl_version_file` (string) - The path within the virtual machine to upload a file that contains the `prlctl` version that was used to create the machine. This information can be useful for provisioning. By default this is