builder/virtualbox: iso_urls for multiple ISO urls [GH-110]
This commit is contained in:
parent
b872448758
commit
c0265d108a
|
@ -7,6 +7,8 @@ FEATURES:
|
||||||
parse out components of a template.
|
parse out components of a template.
|
||||||
* Packer will detect its own crashes (always a bug) and save a "crash.log"
|
* Packer will detect its own crashes (always a bug) and save a "crash.log"
|
||||||
file.
|
file.
|
||||||
|
* builder/virtualbox: You may now specify multiple URLs for an ISO
|
||||||
|
using "iso_url" in a template. The URLs will be tried in order.
|
||||||
|
|
||||||
IMPROVEMENTS:
|
IMPROVEMENTS:
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ type config struct {
|
||||||
HTTPPortMax uint `mapstructure:"http_port_max"`
|
HTTPPortMax uint `mapstructure:"http_port_max"`
|
||||||
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"`
|
||||||
OutputDir string `mapstructure:"output_directory"`
|
OutputDir string `mapstructure:"output_directory"`
|
||||||
ShutdownCommand string `mapstructure:"shutdown_command"`
|
ShutdownCommand string `mapstructure:"shutdown_command"`
|
||||||
SSHHostPortMin uint `mapstructure:"ssh_host_port_min"`
|
SSHHostPortMin uint `mapstructure:"ssh_host_port_min"`
|
||||||
|
@ -50,6 +50,7 @@ type config struct {
|
||||||
VMName string `mapstructure:"vm_name"`
|
VMName string `mapstructure:"vm_name"`
|
||||||
|
|
||||||
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"`
|
||||||
|
|
||||||
|
@ -137,7 +138,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,
|
||||||
|
@ -158,6 +159,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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
validates := map[string]*string{
|
validates := map[string]*string{
|
||||||
"guest_additions_path": &b.config.GuestAdditionsPath,
|
"guest_additions_path": &b.config.GuestAdditionsPath,
|
||||||
"guest_additions_url": &b.config.GuestAdditionsURL,
|
"guest_additions_url": &b.config.GuestAdditionsURL,
|
||||||
|
@ -211,14 +221,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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +317,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,
|
||||||
},
|
},
|
||||||
new(stepPrepareOutputDir),
|
new(stepPrepareOutputDir),
|
||||||
&common.StepCreateFloppy{
|
&common.StepCreateFloppy{
|
||||||
|
|
|
@ -84,6 +84,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)
|
||||||
|
@ -210,6 +211,7 @@ func TestBuilderPrepare_GuestAdditionsURL(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
config["guest_additions_url"] = "http://www.packer.io"
|
config["guest_additions_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)
|
||||||
|
@ -230,6 +232,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")
|
||||||
|
@ -238,6 +241,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)
|
||||||
|
@ -269,6 +273,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)
|
||||||
|
@ -292,6 +297,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)
|
||||||
|
@ -303,6 +309,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")
|
||||||
|
@ -312,18 +319,59 @@ func TestBuilderPrepare_ISOChecksumType(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) {
|
||||||
|
@ -338,6 +386,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")
|
||||||
|
@ -345,6 +394,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)
|
||||||
|
@ -364,6 +414,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)
|
||||||
|
@ -377,6 +428,7 @@ func TestBuilderPrepare_SSHHostPort(t *testing.T) {
|
||||||
// Bad
|
// Bad
|
||||||
config["ssh_host_port_min"] = 1000
|
config["ssh_host_port_min"] = 1000
|
||||||
config["ssh_host_port_max"] = 500
|
config["ssh_host_port_max"] = 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")
|
||||||
|
@ -384,6 +436,7 @@ func TestBuilderPrepare_SSHHostPort(t *testing.T) {
|
||||||
|
|
||||||
// Bad
|
// Bad
|
||||||
config["ssh_host_port_min"] = -500
|
config["ssh_host_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")
|
||||||
|
@ -392,6 +445,7 @@ func TestBuilderPrepare_SSHHostPort(t *testing.T) {
|
||||||
// Good
|
// Good
|
||||||
config["ssh_host_port_min"] = 500
|
config["ssh_host_port_min"] = 500
|
||||||
config["ssh_host_port_max"] = 1000
|
config["ssh_host_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)
|
||||||
|
@ -403,12 +457,14 @@ func TestBuilderPrepare_SSHUser(t *testing.T) {
|
||||||
config := testConfig()
|
config := testConfig()
|
||||||
|
|
||||||
config["ssh_username"] = ""
|
config["ssh_username"] = ""
|
||||||
|
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")
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
|
@ -432,6 +488,7 @@ func TestBuilderPrepare_SSHWaitTimeout(t *testing.T) {
|
||||||
|
|
||||||
// Test with a bad value
|
// Test with a bad value
|
||||||
config["ssh_wait_timeout"] = "this is not good"
|
config["ssh_wait_timeout"] = "this is not good"
|
||||||
|
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")
|
||||||
|
@ -439,6 +496,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)
|
||||||
|
|
Loading…
Reference in New Issue