diff --git a/builder/parallels/common/tools_config.go b/builder/parallels/common/tools_config.go new file mode 100644 index 000000000..19993fb77 --- /dev/null +++ b/builder/parallels/common/tools_config.go @@ -0,0 +1,78 @@ +package common + +import ( + "errors" + "fmt" + "github.com/mitchellh/packer/packer" + "text/template" +) + +// These are the different valid mode values for "parallels_tools_mode" which +// determine how guest additions are delivered to the guest. +const ( + ParallelsToolsModeDisable string = "disable" + ParallelsToolsModeAttach = "attach" + ParallelsToolsModeUpload = "upload" +) + +type ToolsConfig struct { + ParallelsToolsFlavor string `mapstructure:"parallels_tools_flavor"` + ParallelsToolsGuestPath string `mapstructure:"parallels_tools_guest_path"` + ParallelsToolsMode string `mapstructure:"parallels_tools_mode"` +} + +func (c *ToolsConfig) Prepare(t *packer.ConfigTemplate) []error { + if c.ParallelsToolsMode == "" { + c.ParallelsToolsMode = ParallelsToolsModeUpload + } + + if c.ParallelsToolsGuestPath == "" { + c.ParallelsToolsGuestPath = "prl-tools-{{.Flavor}}.iso" + } + + templates := map[string]*string{ + "parallels_tools_flavor": &c.ParallelsToolsFlavor, + "parallels_tools_mode": &c.ParallelsToolsMode, + } + + var err error + errs := make([]error, 0) + for n, ptr := range templates { + *ptr, err = t.Process(*ptr, nil) + if err != nil { + errs = append(errs, fmt.Errorf("Error processing %s: %s", n, err)) + } + } + + if _, err := template.New("path").Parse(c.ParallelsToolsGuestPath); err != nil { + errs = append(errs, fmt.Errorf("parallels_tools_guest_path invalid: %s", err)) + } + + validMode := false + validModes := []string{ + ParallelsToolsModeDisable, + ParallelsToolsModeAttach, + ParallelsToolsModeUpload, + } + + for _, mode := range validModes { + if c.ParallelsToolsMode == mode { + validMode = true + break + } + } + + if !validMode { + errs = append(errs, + fmt.Errorf("parallels_tools_mode is invalid. Must be one of: %v", + validModes)) + } + + if c.ParallelsToolsFlavor == "" { + if c.ParallelsToolsMode != ParallelsToolsModeDisable { + errs = append(errs, errors.New("parallels_tools_flavor must be specified.")) + } + } + + return errs +} diff --git a/builder/parallels/common/tools_config_test.go b/builder/parallels/common/tools_config_test.go new file mode 100644 index 000000000..5f5a8a35d --- /dev/null +++ b/builder/parallels/common/tools_config_test.go @@ -0,0 +1,123 @@ +package common + +import ( + "testing" +) + +func testToolsConfig() *ToolsConfig { + return &ToolsConfig{ + ParallelsToolsFlavor: "foo", + ParallelsToolsGuestPath: "foo", + ParallelsToolsMode: "attach", + } +} + +func TestToolsConfigPrepare(t *testing.T) { + c := testToolsConfig() + errs := c.Prepare(testConfigTemplate(t)) + if len(errs) > 0 { + t.Fatalf("bad err: %#v", errs) + } +} + +func TestToolsConfigPrepare_ParallelsToolsMode(t *testing.T) { + var c *ToolsConfig + var errs []error + + // Test default mode + c = testToolsConfig() + c.ParallelsToolsMode = "" + errs = c.Prepare(testConfigTemplate(t)) + if len(errs) > 0 { + t.Fatalf("should not have error: %#v", errs) + } + if c.ParallelsToolsMode != ParallelsToolsModeUpload { + t.Errorf("bad parallels tools mode: %s", c.ParallelsToolsMode) + } + + // Test another mode + c = testToolsConfig() + c.ParallelsToolsMode = "attach" + errs = c.Prepare(testConfigTemplate(t)) + if len(errs) > 0 { + t.Fatalf("should not have error: %#v", errs) + } + if c.ParallelsToolsMode != ParallelsToolsModeAttach { + t.Fatalf("bad mode: %s", c.ParallelsToolsMode) + } + + // Test invalid mode + c = testToolsConfig() + c.ParallelsToolsMode = "invalid_mode" + errs = c.Prepare(testConfigTemplate(t)) + if len(errs) == 0 { + t.Fatal("should have error") + } +} + +func TestToolsConfigPrepare_ParallelsToolsGuestPath(t *testing.T) { + var c *ToolsConfig + var errs []error + + // Test default path + c = testToolsConfig() + c.ParallelsToolsGuestPath = "" + errs = c.Prepare(testConfigTemplate(t)) + if len(errs) > 0 { + t.Fatalf("should not have error: %#v", errs) + } + if c.ParallelsToolsGuestPath == "" { + t.Fatal("should not be empty") + } + + // Test with a bad value + c = testToolsConfig() + c.ParallelsToolsGuestPath = "{{{nope}" + errs = c.Prepare(testConfigTemplate(t)) + if len(errs) == 0 { + t.Fatal("should have error") + } + + // Test with a good one + c = testToolsConfig() + c.ParallelsToolsGuestPath = "foo" + errs = c.Prepare(testConfigTemplate(t)) + if len(errs) > 0 { + t.Fatalf("should not have error: %s", errs) + } + + if c.ParallelsToolsGuestPath != "foo" { + t.Fatalf("bad guest path: %s", c.ParallelsToolsGuestPath) + } +} + +func TestToolsConfigPrepare_ParallelsToolsFlavor(t *testing.T) { + var c *ToolsConfig + var errs []error + + // Test with a default value + c = testToolsConfig() + c.ParallelsToolsFlavor = "" + errs = c.Prepare(testConfigTemplate(t)) + if len(errs) == 0 { + t.Fatal("should have error") + } + + // Test with an bad value + c = testToolsConfig() + c.ParallelsToolsMode = "attach" + c.ParallelsToolsFlavor = "" + errs = c.Prepare(testConfigTemplate(t)) + if len(errs) == 0 { + t.Fatal("should have error") + } + + // Test with a good one + c = testToolsConfig() + c.ParallelsToolsMode = "disable" + c.ParallelsToolsFlavor = "" + errs = c.Prepare(testConfigTemplate(t)) + if len(errs) > 0 { + t.Fatalf("should not have error: %s", errs) + } +} diff --git a/builder/parallels/common/tools_modes.go b/builder/parallels/common/tools_modes.go deleted file mode 100644 index 3523fbca7..000000000 --- a/builder/parallels/common/tools_modes.go +++ /dev/null @@ -1,9 +0,0 @@ -package common - -// These are the different valid mode values for "parallels_tools_mode" which -// determine how guest additions are delivered to the guest. -const ( - ParallelsToolsModeDisable string = "disable" - ParallelsToolsModeAttach = "attach" - ParallelsToolsModeUpload = "upload" -) diff --git a/builder/parallels/iso/builder.go b/builder/parallels/iso/builder.go index 0fa38d5fb..79022a0a7 100644 --- a/builder/parallels/iso/builder.go +++ b/builder/parallels/iso/builder.go @@ -22,32 +22,31 @@ type config struct { common.PackerConfig `mapstructure:",squash"` parallelscommon.FloppyConfig `mapstructure:",squash"` parallelscommon.OutputConfig `mapstructure:",squash"` + parallelscommon.PrlctlConfig `mapstructure:",squash"` + parallelscommon.PrlctlVersionConfig `mapstructure:",squash"` parallelscommon.RunConfig `mapstructure:",squash"` parallelscommon.ShutdownConfig `mapstructure:",squash"` parallelscommon.SSHConfig `mapstructure:",squash"` - parallelscommon.PrlctlConfig `mapstructure:",squash"` - parallelscommon.PrlctlVersionConfig `mapstructure:",squash"` + parallelscommon.ToolsConfig `mapstructure:",squash"` - BootCommand []string `mapstructure:"boot_command"` - DiskSize uint `mapstructure:"disk_size"` - ParallelsToolsMode string `mapstructure:"parallels_tools_mode"` - ParallelsToolsGuestPath string `mapstructure:"parallels_tools_guest_path"` - ParallelsToolsHostPath string `mapstructure:"parallels_tools_host_path"` - GuestOSDistribution string `mapstructure:"guest_os_distribution"` - HardDriveInterface string `mapstructure:"hard_drive_interface"` - HostInterfaces []string `mapstructure:"host_interfaces"` - HTTPDir string `mapstructure:"http_directory"` - HTTPPortMin uint `mapstructure:"http_port_min"` - HTTPPortMax uint `mapstructure:"http_port_max"` - ISOChecksum string `mapstructure:"iso_checksum"` - ISOChecksumType string `mapstructure:"iso_checksum_type"` - ISOUrls []string `mapstructure:"iso_urls"` - VMName string `mapstructure:"vm_name"` + BootCommand []string `mapstructure:"boot_command"` + DiskSize uint `mapstructure:"disk_size"` + GuestOSDistribution string `mapstructure:"guest_os_distribution"` + HardDriveInterface string `mapstructure:"hard_drive_interface"` + HostInterfaces []string `mapstructure:"host_interfaces"` + HTTPDir string `mapstructure:"http_directory"` + HTTPPortMin uint `mapstructure:"http_port_min"` + HTTPPortMax uint `mapstructure:"http_port_max"` + ISOChecksum string `mapstructure:"iso_checksum"` + ISOChecksumType string `mapstructure:"iso_checksum_type"` + ISOUrls []string `mapstructure:"iso_urls"` + VMName string `mapstructure:"vm_name"` RawSingleISOUrl string `mapstructure:"iso_url"` // Deprecated parameters - GuestOSType string `mapstructure:"guest_os_type"` + GuestOSType string `mapstructure:"guest_os_type"` + ParallelsToolsHostPath string `mapstructure:"parallels_tools_host_path"` tpl *packer.ConfigTemplate } @@ -71,28 +70,17 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { errs = packer.MultiErrorAppend( 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.ShutdownConfig.Prepare(b.config.tpl)...) - errs = packer.MultiErrorAppend(errs, b.config.SSHConfig.Prepare(b.config.tpl)...) errs = packer.MultiErrorAppend(errs, b.config.PrlctlConfig.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)...) + errs = packer.MultiErrorAppend(errs, b.config.ToolsConfig.Prepare(b.config.tpl)...) warnings := make([]string, 0) if b.config.DiskSize == 0 { b.config.DiskSize = 40000 } - if b.config.ParallelsToolsMode == "" { - b.config.ParallelsToolsMode = "upload" - } - - if b.config.ParallelsToolsGuestPath == "" { - b.config.ParallelsToolsGuestPath = "prl-tools.iso" - } - - if b.config.ParallelsToolsHostPath == "" { - b.config.ParallelsToolsHostPath = "/Applications/Parallels Desktop.app/Contents/Resources/Tools/prl-tools-other.iso" - } - if b.config.HardDriveInterface == "" { b.config.HardDriveInterface = "sata" } @@ -120,16 +108,13 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { // Errors templates := map[string]*string{ - "parallels_tools_mode": &b.config.ParallelsToolsMode, - "parallels_tools_host_path": &b.config.ParallelsToolsHostPath, - "parallels_tools_guest_path": &b.config.ParallelsToolsGuestPath, - "guest_os_distribution": &b.config.GuestOSDistribution, - "hard_drive_interface": &b.config.HardDriveInterface, - "http_directory": &b.config.HTTPDir, - "iso_checksum": &b.config.ISOChecksum, - "iso_checksum_type": &b.config.ISOChecksumType, - "iso_url": &b.config.RawSingleISOUrl, - "vm_name": &b.config.VMName, + "guest_os_distribution": &b.config.GuestOSDistribution, + "hard_drive_interface": &b.config.HardDriveInterface, + "http_directory": &b.config.HTTPDir, + "iso_checksum": &b.config.ISOChecksum, + "iso_checksum_type": &b.config.ISOChecksumType, + "iso_url": &b.config.RawSingleISOUrl, + "vm_name": &b.config.VMName, } for n, ptr := range templates { @@ -150,17 +135,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } } - validates := map[string]*string{ - "parallels_tools_guest_path": &b.config.ParallelsToolsGuestPath, - } - - for n, ptr := range validates { - if err := b.config.tpl.Validate(*ptr); err != nil { - errs = packer.MultiErrorAppend( - errs, fmt.Errorf("Error parsing %s: %s", n, err)) - } - } - for i, command := range b.config.BootCommand { if err := b.config.tpl.Validate(command); err != nil { errs = packer.MultiErrorAppend(errs, @@ -217,25 +191,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { } } - validMode := false - validModes := []string{ - parallelscommon.ParallelsToolsModeDisable, - parallelscommon.ParallelsToolsModeAttach, - parallelscommon.ParallelsToolsModeUpload, - } - - for _, mode := range validModes { - if b.config.ParallelsToolsMode == mode { - validMode = true - break - } - } - - if !validMode { - errs = packer.MultiErrorAppend(errs, - fmt.Errorf("parallels_tools_mode is invalid. Must be one of: %v", validModes)) - } - // Warnings if b.config.ISOChecksumType == "none" { warnings = append(warnings, @@ -249,6 +204,12 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { "will forcibly halt the virtual machine, which may result in data loss.") } + if b.config.ParallelsToolsHostPath != "" { + warnings = append(warnings, + "A 'parallels_tools_host_path' has been deprecated and not in use anymore\n"+ + "You can remove it from your Packer template.") + } + if errs != nil && len(errs.Errors) > 0 { return warnings, errs } diff --git a/builder/parallels/iso/builder_test.go b/builder/parallels/iso/builder_test.go index f20f544d6..ac5a3a87c 100644 --- a/builder/parallels/iso/builder_test.go +++ b/builder/parallels/iso/builder_test.go @@ -1,7 +1,6 @@ package iso import ( - "github.com/mitchellh/packer/builder/parallels/common" "github.com/mitchellh/packer/packer" "reflect" "testing" @@ -38,10 +37,6 @@ func TestBuilderPrepare_Defaults(t *testing.T) { t.Fatalf("should not have error: %s", err) } - if b.config.ParallelsToolsMode != common.ParallelsToolsModeUpload { - t.Errorf("bad parallels tools mode: %s", b.config.ParallelsToolsMode) - } - if b.config.GuestOSDistribution != "other" { t.Errorf("bad guest OS distribution: %s", b.config.GuestOSDistribution) } @@ -83,107 +78,6 @@ func TestBuilderPrepare_DiskSize(t *testing.T) { } } -func TestBuilderPrepare_ParallelsToolsMode(t *testing.T) { - var b Builder - config := testConfig() - - // test default mode - delete(config, "parallels_tools_mode") - warns, err := b.Prepare(config) - if len(warns) > 0 { - t.Fatalf("bad: %#v", warns) - } - if err != nil { - t.Fatalf("bad err: %s", err) - } - - // Test another mode - config["parallels_tools_mode"] = "attach" - 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) - } - - if b.config.ParallelsToolsMode != common.ParallelsToolsModeAttach { - t.Fatalf("bad: %s", b.config.ParallelsToolsMode) - } - - // Test bad mode - config["parllels_tools_mode"] = "teleport" - b = Builder{} - warns, err = b.Prepare(config) - if len(warns) > 0 { - t.Fatalf("bad: %#v", warns) - } - if err == nil { - t.Fatal("should error") - } -} - -func TestBuilderPrepare_ParallelsToolsGuestPath(t *testing.T) { - var b Builder - config := testConfig() - - delete(config, "parallesl_tools_guest_path") - warns, err := b.Prepare(config) - if len(warns) > 0 { - t.Fatalf("bad: %#v", warns) - } - if err != nil { - t.Fatalf("bad err: %s", err) - } - - if b.config.ParallelsToolsGuestPath != "prl-tools.iso" { - t.Fatalf("bad: %s", b.config.ParallelsToolsGuestPath) - } - - config["parallels_tools_guest_path"] = "foo" - 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) - } - - if b.config.ParallelsToolsGuestPath != "foo" { - t.Fatalf("bad size: %s", b.config.ParallelsToolsGuestPath) - } -} - -func TestBuilderPrepare_ParallelsToolsHostPath(t *testing.T) { - var b Builder - config := testConfig() - - config["parallels_tools_host_path"] = "" - warns, err := b.Prepare(config) - if len(warns) > 0 { - t.Fatalf("bad: %#v", warns) - } - if err != nil { - t.Fatalf("err: %s", err) - } - - if b.config.ParallelsToolsHostPath != "/Applications/Parallels Desktop.app/Contents/Resources/Tools/prl-tools-other.iso" { - t.Fatalf("bad: %s", b.config.ParallelsToolsHostPath) - } - - config["parallels_tools_host_path"] = "./prl-tools-lin.iso" - b = Builder{} - warns, err = b.Prepare(config) - if len(warns) > 0 { - t.Fatalf("bad: %#v", warns) - } - if err != nil { - t.Errorf("should not have error: %s", err) - } -} - func TestBuilderPrepare_HardDriveInterface(t *testing.T) { var b Builder config := testConfig() @@ -434,3 +328,19 @@ func TestBuilderPrepare_ISOUrl(t *testing.T) { t.Fatalf("bad: %#v", b.config.ISOUrls) } } + +func TestBuilderPrepare_ParallelsToolsHostPath(t *testing.T) { + var b Builder + config := testConfig() + delete(config, "parallels_tools_host_path") + + // Test that it is deprecated + config["parallels_tools_host_path"] = "/path/to/iso" + warns, err := b.Prepare(config) + if len(warns) == 0 { + t.Fatalf("should have warning") + } + if err != nil { + t.Fatalf("should not have error: %s", err) + } +} diff --git a/builder/parallels/pvm/config.go b/builder/parallels/pvm/config.go index 84bc7fbdd..a3c20bb5d 100644 --- a/builder/parallels/pvm/config.go +++ b/builder/parallels/pvm/config.go @@ -13,18 +13,16 @@ type Config struct { common.PackerConfig `mapstructure:",squash"` parallelscommon.FloppyConfig `mapstructure:",squash"` parallelscommon.OutputConfig `mapstructure:",squash"` + parallelscommon.PrlctlConfig `mapstructure:",squash"` + parallelscommon.PrlctlVersionConfig `mapstructure:",squash"` parallelscommon.RunConfig `mapstructure:",squash"` parallelscommon.SSHConfig `mapstructure:",squash"` parallelscommon.ShutdownConfig `mapstructure:",squash"` - parallelscommon.PrlctlConfig `mapstructure:",squash"` - parallelscommon.PrlctlVersionConfig `mapstructure:",squash"` + parallelscommon.ToolsConfig `mapstructure:",squash"` - BootCommand []string `mapstructure:"boot_command"` - ParallelsToolsMode string `mapstructure:"parallels_tools_mode"` - ParallelsToolsGuestPath string `mapstructure:"parallels_tools_guest_path"` - ParallelsToolsHostPath string `mapstructure:"parallels_tools_host_path"` - SourcePath string `mapstructure:"source_path"` - VMName string `mapstructure:"vm_name"` + BootCommand []string `mapstructure:"boot_command"` + SourcePath string `mapstructure:"source_path"` + VMName string `mapstructure:"vm_name"` tpl *packer.ConfigTemplate } @@ -42,19 +40,6 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { } c.tpl.UserVars = c.PackerUserVars - // Defaults - if c.ParallelsToolsMode == "" { - c.ParallelsToolsMode = "disable" - } - - if c.ParallelsToolsGuestPath == "" { - c.ParallelsToolsGuestPath = "prl-tools.iso" - } - - if c.ParallelsToolsHostPath == "" { - c.ParallelsToolsHostPath = "/Applications/Parallels Desktop.app/Contents/Resources/Tools/prl-tools-other.iso" - } - if c.VMName == "" { c.VMName = fmt.Sprintf("packer-%s-{{timestamp}}", c.PackerBuildName) } @@ -63,18 +48,16 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { errs := common.CheckUnusedConfig(md) 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.PrlctlVersionConfig.Prepare(c.tpl)...) errs = packer.MultiErrorAppend(errs, c.RunConfig.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.PrlctlConfig.Prepare(c.tpl)...) - errs = packer.MultiErrorAppend(errs, c.PrlctlVersionConfig.Prepare(c.tpl)...) + errs = packer.MultiErrorAppend(errs, c.ToolsConfig.Prepare(c.tpl)...) templates := map[string]*string{ - "parallels_tools_mode": &c.ParallelsToolsMode, - "parallels_tools_host_paht": &c.ParallelsToolsHostPath, - "parallels_tools_guest_path": &c.ParallelsToolsGuestPath, - "source_path": &c.SourcePath, - "vm_name": &c.VMName, + "source_path": &c.SourcePath, + "vm_name": &c.VMName, } for n, ptr := range templates { @@ -93,25 +76,6 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) { } } - validMode := false - validModes := []string{ - parallelscommon.ParallelsToolsModeDisable, - parallelscommon.ParallelsToolsModeAttach, - parallelscommon.ParallelsToolsModeUpload, - } - - for _, mode := range validModes { - if c.ParallelsToolsMode == mode { - validMode = true - break - } - } - - if !validMode { - errs = packer.MultiErrorAppend(errs, - fmt.Errorf("parallels_tools_mode is invalid. Must be one of: %v", validModes)) - } - if c.SourcePath == "" { errs = packer.MultiErrorAppend(errs, fmt.Errorf("source_path is required")) } else {