Commit 334cf37f authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

builder/vmware: support iso_urls for multiple URLs [GH-110]

parent c0265d10
...@@ -9,6 +9,8 @@ FEATURES: ...@@ -9,6 +9,8 @@ FEATURES:
file. file.
* builder/virtualbox: You may now specify multiple URLs for an ISO * builder/virtualbox: You may now specify multiple URLs for an ISO
using "iso_url" in a template. The URLs will be tried in order. using "iso_url" in a template. The URLs will be tried in order.
* builder/vmware: You may now specify multiple URLs for an ISO
using "iso_url" in a template. The URLs will be tried in order.
IMPROVEMENTS: IMPROVEMENTS:
......
...@@ -31,7 +31,7 @@ type config struct { ...@@ -31,7 +31,7 @@ type config struct {
GuestOSType string `mapstructure:"guest_os_type"` GuestOSType string `mapstructure:"guest_os_type"`
ISOChecksum string `mapstructure:"iso_checksum"` ISOChecksum string `mapstructure:"iso_checksum"`
ISOChecksumType string `mapstructure:"iso_checksum_type"` ISOChecksumType string `mapstructure:"iso_checksum_type"`
ISOUrl string `mapstructure:"iso_url"` ISOUrls []string `mapstructure:"iso_urls"`
VMName string `mapstructure:"vm_name"` VMName string `mapstructure:"vm_name"`
OutputDir string `mapstructure:"output_directory"` OutputDir string `mapstructure:"output_directory"`
Headless bool `mapstructure:"headless"` Headless bool `mapstructure:"headless"`
...@@ -51,6 +51,7 @@ type config struct { ...@@ -51,6 +51,7 @@ type config struct {
VNCPortMax uint `mapstructure:"vnc_port_max"` VNCPortMax uint `mapstructure:"vnc_port_max"`
RawBootWait string `mapstructure:"boot_wait"` RawBootWait string `mapstructure:"boot_wait"`
RawSingleISOUrl string `mapstructure:"iso_url"`
RawShutdownTimeout string `mapstructure:"shutdown_timeout"` RawShutdownTimeout string `mapstructure:"shutdown_timeout"`
RawSSHWaitTimeout string `mapstructure:"ssh_wait_timeout"` RawSSHWaitTimeout string `mapstructure:"ssh_wait_timeout"`
...@@ -134,7 +135,7 @@ func (b *Builder) Prepare(raws ...interface{}) error { ...@@ -134,7 +135,7 @@ func (b *Builder) Prepare(raws ...interface{}) error {
"http_directory": &b.config.HTTPDir, "http_directory": &b.config.HTTPDir,
"iso_checksum": &b.config.ISOChecksum, "iso_checksum": &b.config.ISOChecksum,
"iso_checksum_type": &b.config.ISOChecksumType, "iso_checksum_type": &b.config.ISOChecksumType,
"iso_url": &b.config.ISOUrl, "iso_url": &b.config.RawSingleISOUrl,
"output_directory": &b.config.OutputDir, "output_directory": &b.config.OutputDir,
"shutdown_command": &b.config.ShutdownCommand, "shutdown_command": &b.config.ShutdownCommand,
"ssh_password": &b.config.SSHPassword, "ssh_password": &b.config.SSHPassword,
...@@ -155,6 +156,15 @@ func (b *Builder) Prepare(raws ...interface{}) error { ...@@ -155,6 +156,15 @@ func (b *Builder) Prepare(raws ...interface{}) error {
} }
} }
for i, url := range b.config.ISOUrls {
var err error
b.config.ISOUrls[i], err = b.config.tpl.Process(url, nil)
if err != nil {
errs = packer.MultiErrorAppend(
errs, fmt.Errorf("Error processing iso_urls[%d]: %s", i, err))
}
}
for i, command := range b.config.BootCommand { for i, command := range b.config.BootCommand {
if err := b.config.tpl.Validate(command); err != nil { if err := b.config.tpl.Validate(command); err != nil {
errs = packer.MultiErrorAppend(errs, errs = packer.MultiErrorAppend(errs,
...@@ -217,14 +227,21 @@ func (b *Builder) Prepare(raws ...interface{}) error { ...@@ -217,14 +227,21 @@ func (b *Builder) Prepare(raws ...interface{}) error {
} }
} }
if b.config.ISOUrl == "" { if b.config.RawSingleISOUrl == "" && len(b.config.ISOUrls) == 0 {
errs = packer.MultiErrorAppend( errs = packer.MultiErrorAppend(
errs, errors.New("An iso_url must be specified.")) errs, errors.New("One of iso_url or iso_urls must be specified."))
} else { } else if b.config.RawSingleISOUrl != "" && len(b.config.ISOUrls) > 0 {
b.config.ISOUrl, err = common.DownloadableURL(b.config.ISOUrl) errs = packer.MultiErrorAppend(
errs, errors.New("Only one of iso_url or iso_urls may be specified."))
} else if b.config.RawSingleISOUrl != "" {
b.config.ISOUrls = []string{b.config.RawSingleISOUrl}
}
for i, url := range b.config.ISOUrls {
b.config.ISOUrls[i], err = common.DownloadableURL(url)
if err != nil { if err != nil {
errs = packer.MultiErrorAppend( errs = packer.MultiErrorAppend(
errs, fmt.Errorf("iso_url: %s", err)) errs, fmt.Errorf("Failed to parse iso_url %d: %s", i+1, err))
} }
} }
...@@ -303,7 +320,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe ...@@ -303,7 +320,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
ChecksumType: b.config.ISOChecksumType, ChecksumType: b.config.ISOChecksumType,
Description: "ISO", Description: "ISO",
ResultKey: "iso_path", ResultKey: "iso_path",
Url: []string{b.config.ISOUrl}, Url: b.config.ISOUrls,
}, },
&stepPrepareOutputDir{}, &stepPrepareOutputDir{},
&common.StepCreateFloppy{ &common.StepCreateFloppy{
......
...@@ -52,6 +52,7 @@ func TestBuilderPrepare_BootWait(t *testing.T) { ...@@ -52,6 +52,7 @@ func TestBuilderPrepare_BootWait(t *testing.T) {
// Test with a good one // Test with a good one
config["boot_wait"] = "5s" config["boot_wait"] = "5s"
b = Builder{}
err = b.Prepare(config) err = b.Prepare(config)
if err != nil { if err != nil {
t.Fatalf("should not have error: %s", err) t.Fatalf("should not have error: %s", err)
...@@ -71,6 +72,7 @@ func TestBuilderPrepare_ISOChecksum(t *testing.T) { ...@@ -71,6 +72,7 @@ func TestBuilderPrepare_ISOChecksum(t *testing.T) {
// Test good // Test good
config["iso_checksum"] = "FOo" config["iso_checksum"] = "FOo"
b = Builder{}
err = b.Prepare(config) err = b.Prepare(config)
if err != nil { if err != nil {
t.Fatalf("should not have error: %s", err) t.Fatalf("should not have error: %s", err)
...@@ -94,6 +96,7 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) { ...@@ -94,6 +96,7 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) {
// Test good // Test good
config["iso_checksum_type"] = "mD5" config["iso_checksum_type"] = "mD5"
b = Builder{}
err = b.Prepare(config) err = b.Prepare(config)
if err != nil { if err != nil {
t.Fatalf("should not have error: %s", err) t.Fatalf("should not have error: %s", err)
...@@ -105,6 +108,7 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) { ...@@ -105,6 +108,7 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) {
// Test unknown // Test unknown
config["iso_checksum_type"] = "fake" config["iso_checksum_type"] = "fake"
b = Builder{}
err = b.Prepare(config) err = b.Prepare(config)
if err == nil { if err == nil {
t.Fatal("should have error") t.Fatal("should have error")
...@@ -202,6 +206,7 @@ func TestBuilderPrepare_HTTPPort(t *testing.T) { ...@@ -202,6 +206,7 @@ func TestBuilderPrepare_HTTPPort(t *testing.T) {
// Bad // Bad
config["http_port_min"] = -500 config["http_port_min"] = -500
b = Builder{}
err = b.Prepare(config) err = b.Prepare(config)
if err == nil { if err == nil {
t.Fatal("should have error") t.Fatal("should have error")
...@@ -210,6 +215,7 @@ func TestBuilderPrepare_HTTPPort(t *testing.T) { ...@@ -210,6 +215,7 @@ func TestBuilderPrepare_HTTPPort(t *testing.T) {
// Good // Good
config["http_port_min"] = 500 config["http_port_min"] = 500
config["http_port_max"] = 1000 config["http_port_max"] = 1000
b = Builder{}
err = b.Prepare(config) err = b.Prepare(config)
if err != nil { if err != nil {
t.Fatalf("should not have error: %s", err) t.Fatalf("should not have error: %s", err)
...@@ -231,18 +237,59 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) { ...@@ -231,18 +237,59 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) {
func TestBuilderPrepare_ISOUrl(t *testing.T) { func TestBuilderPrepare_ISOUrl(t *testing.T) {
var b Builder var b Builder
config := testConfig() config := testConfig()
delete(config, "iso_url")
delete(config, "iso_urls")
// Test both epty
config["iso_url"] = "" config["iso_url"] = ""
b = Builder{}
err := b.Prepare(config) err := b.Prepare(config)
if err == nil { if err == nil {
t.Fatal("should have error") t.Fatal("should have error")
} }
// Test iso_url set
config["iso_url"] = "http://www.packer.io" config["iso_url"] = "http://www.packer.io"
b = Builder{}
err = b.Prepare(config) err = b.Prepare(config)
if err != nil { if err != nil {
t.Errorf("should not have error: %s", err) t.Errorf("should not have error: %s", err)
} }
expected := []string{"http://www.packer.io"}
if !reflect.DeepEqual(b.config.ISOUrls, expected) {
t.Fatalf("bad: %#v", b.config.ISOUrls)
}
// Test both set
config["iso_url"] = "http://www.packer.io"
config["iso_urls"] = []string{"http://www.packer.io"}
b = Builder{}
err = b.Prepare(config)
if err == nil {
t.Fatal("should have error")
}
// Test just iso_urls set
delete(config, "iso_url")
config["iso_urls"] = []string{
"http://www.packer.io",
"http://www.hashicorp.com",
}
b = Builder{}
err = b.Prepare(config)
if err != nil {
t.Errorf("should not have error: %s", err)
}
expected = []string{
"http://www.packer.io",
"http://www.hashicorp.com",
}
if !reflect.DeepEqual(b.config.ISOUrls, expected) {
t.Fatalf("bad: %#v", b.config.ISOUrls)
}
} }
func TestBuilderPrepare_OutputDir(t *testing.T) { func TestBuilderPrepare_OutputDir(t *testing.T) {
...@@ -257,6 +304,7 @@ func TestBuilderPrepare_OutputDir(t *testing.T) { ...@@ -257,6 +304,7 @@ func TestBuilderPrepare_OutputDir(t *testing.T) {
defer os.RemoveAll(dir) defer os.RemoveAll(dir)
config["output_directory"] = dir config["output_directory"] = dir
b = Builder{}
err = b.Prepare(config) err = b.Prepare(config)
if err == nil { if err == nil {
t.Fatal("should have error") t.Fatal("should have error")
...@@ -264,6 +312,7 @@ func TestBuilderPrepare_OutputDir(t *testing.T) { ...@@ -264,6 +312,7 @@ func TestBuilderPrepare_OutputDir(t *testing.T) {
// Test with a good one // Test with a good one
config["output_directory"] = "i-hope-i-dont-exist" config["output_directory"] = "i-hope-i-dont-exist"
b = Builder{}
err = b.Prepare(config) err = b.Prepare(config)
if err != nil { if err != nil {
t.Fatalf("should not have error: %s", err) t.Fatalf("should not have error: %s", err)
...@@ -283,6 +332,7 @@ func TestBuilderPrepare_ShutdownTimeout(t *testing.T) { ...@@ -283,6 +332,7 @@ func TestBuilderPrepare_ShutdownTimeout(t *testing.T) {
// Test with a good one // Test with a good one
config["shutdown_timeout"] = "5s" config["shutdown_timeout"] = "5s"
b = Builder{}
err = b.Prepare(config) err = b.Prepare(config)
if err != nil { if err != nil {
t.Fatalf("should not have error: %s", err) t.Fatalf("should not have error: %s", err)
...@@ -300,6 +350,7 @@ func TestBuilderPrepare_SSHUser(t *testing.T) { ...@@ -300,6 +350,7 @@ func TestBuilderPrepare_SSHUser(t *testing.T) {
} }
config["ssh_username"] = "exists" config["ssh_username"] = "exists"
b = Builder{}
err = b.Prepare(config) err = b.Prepare(config)
if err != nil { if err != nil {
t.Fatalf("should not have error: %s", err) t.Fatalf("should not have error: %s", err)
...@@ -347,6 +398,7 @@ func TestBuilderPrepare_SSHWaitTimeout(t *testing.T) { ...@@ -347,6 +398,7 @@ func TestBuilderPrepare_SSHWaitTimeout(t *testing.T) {
// Test with a good one // Test with a good one
config["ssh_wait_timeout"] = "5s" config["ssh_wait_timeout"] = "5s"
b = Builder{}
err = b.Prepare(config) err = b.Prepare(config)
if err != nil { if err != nil {
t.Fatalf("should not have error: %s", err) t.Fatalf("should not have error: %s", err)
...@@ -370,6 +422,7 @@ func TestBuilderPrepare_ToolsUploadPath(t *testing.T) { ...@@ -370,6 +422,7 @@ func TestBuilderPrepare_ToolsUploadPath(t *testing.T) {
// Test with a bad value // Test with a bad value
config["tools_upload_path"] = "{{{nope}" config["tools_upload_path"] = "{{{nope}"
b = Builder{}
err = b.Prepare(config) err = b.Prepare(config)
if err == nil { if err == nil {
t.Fatal("should have error") t.Fatal("should have error")
...@@ -377,6 +430,7 @@ func TestBuilderPrepare_ToolsUploadPath(t *testing.T) { ...@@ -377,6 +430,7 @@ func TestBuilderPrepare_ToolsUploadPath(t *testing.T) {
// Test with a good one // Test with a good one
config["tools_upload_path"] = "hey" config["tools_upload_path"] = "hey"
b = Builder{}
err = b.Prepare(config) err = b.Prepare(config)
if err != nil { if err != nil {
t.Fatalf("should not have error: %s", err) t.Fatalf("should not have error: %s", err)
...@@ -397,6 +451,7 @@ func TestBuilderPrepare_VNCPort(t *testing.T) { ...@@ -397,6 +451,7 @@ func TestBuilderPrepare_VNCPort(t *testing.T) {
// Bad // Bad
config["vnc_port_min"] = -500 config["vnc_port_min"] = -500
b = Builder{}
err = b.Prepare(config) err = b.Prepare(config)
if err == nil { if err == nil {
t.Fatal("should have error") t.Fatal("should have error")
...@@ -405,6 +460,7 @@ func TestBuilderPrepare_VNCPort(t *testing.T) { ...@@ -405,6 +460,7 @@ func TestBuilderPrepare_VNCPort(t *testing.T) {
// Good // Good
config["vnc_port_min"] = 500 config["vnc_port_min"] = 500
config["vnc_port_max"] = 1000 config["vnc_port_max"] = 1000
b = Builder{}
err = b.Prepare(config) err = b.Prepare(config)
if err != nil { if err != nil {
t.Fatalf("should not have error: %s", err) t.Fatalf("should not have error: %s", err)
......
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