builder/virtualbox: iso_urls for multiple ISO urls [GH-110]

This commit is contained in:
Mitchell Hashimoto 2013-08-15 14:57:29 -04:00
parent b872448758
commit c0265d108a
3 changed files with 85 additions and 8 deletions

View File

@ -7,6 +7,8 @@ FEATURES:
parse out components of a template.
* Packer will detect its own crashes (always a bug) and save a "crash.log"
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:

View File

@ -37,7 +37,7 @@ type config struct {
HTTPPortMax uint `mapstructure:"http_port_max"`
ISOChecksum string `mapstructure:"iso_checksum"`
ISOChecksumType string `mapstructure:"iso_checksum_type"`
ISOUrl string `mapstructure:"iso_url"`
ISOUrls []string `mapstructure:"iso_urls"`
OutputDir string `mapstructure:"output_directory"`
ShutdownCommand string `mapstructure:"shutdown_command"`
SSHHostPortMin uint `mapstructure:"ssh_host_port_min"`
@ -50,6 +50,7 @@ type config struct {
VMName string `mapstructure:"vm_name"`
RawBootWait string `mapstructure:"boot_wait"`
RawSingleISOUrl string `mapstructure:"iso_url"`
RawShutdownTimeout string `mapstructure:"shutdown_timeout"`
RawSSHWaitTimeout string `mapstructure:"ssh_wait_timeout"`
@ -137,7 +138,7 @@ func (b *Builder) Prepare(raws ...interface{}) error {
"http_directory": &b.config.HTTPDir,
"iso_checksum": &b.config.ISOChecksum,
"iso_checksum_type": &b.config.ISOChecksumType,
"iso_url": &b.config.ISOUrl,
"iso_url": &b.config.RawSingleISOUrl,
"output_directory": &b.config.OutputDir,
"shutdown_command": &b.config.ShutdownCommand,
"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{
"guest_additions_path": &b.config.GuestAdditionsPath,
"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, errors.New("An iso_url must be specified."))
} else {
b.config.ISOUrl, err = common.DownloadableURL(b.config.ISOUrl)
errs, errors.New("One of iso_url or iso_urls must be specified."))
} else if b.config.RawSingleISOUrl != "" && len(b.config.ISOUrls) > 0 {
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 {
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,
Description: "ISO",
ResultKey: "iso_path",
Url: []string{b.config.ISOUrl},
Url: b.config.ISOUrls,
},
new(stepPrepareOutputDir),
&common.StepCreateFloppy{

View File

@ -84,6 +84,7 @@ func TestBuilderPrepare_BootWait(t *testing.T) {
// Test with a good one
config["boot_wait"] = "5s"
b = Builder{}
err = b.Prepare(config)
if err != nil {
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"
b = Builder{}
err = b.Prepare(config)
if err != nil {
t.Errorf("should not have error: %s", err)
@ -230,6 +232,7 @@ func TestBuilderPrepare_HTTPPort(t *testing.T) {
// Bad
config["http_port_min"] = -500
b = Builder{}
err = b.Prepare(config)
if err == nil {
t.Fatal("should have error")
@ -238,6 +241,7 @@ func TestBuilderPrepare_HTTPPort(t *testing.T) {
// Good
config["http_port_min"] = 500
config["http_port_max"] = 1000
b = Builder{}
err = b.Prepare(config)
if err != nil {
t.Fatalf("should not have error: %s", err)
@ -269,6 +273,7 @@ func TestBuilderPrepare_ISOChecksum(t *testing.T) {
// Test good
config["iso_checksum"] = "FOo"
b = Builder{}
err = b.Prepare(config)
if err != nil {
t.Fatalf("should not have error: %s", err)
@ -292,6 +297,7 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) {
// Test good
config["iso_checksum_type"] = "mD5"
b = Builder{}
err = b.Prepare(config)
if err != nil {
t.Fatalf("should not have error: %s", err)
@ -303,6 +309,7 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) {
// Test unknown
config["iso_checksum_type"] = "fake"
b = Builder{}
err = b.Prepare(config)
if err == nil {
t.Fatal("should have error")
@ -312,18 +319,59 @@ func TestBuilderPrepare_ISOChecksumType(t *testing.T) {
func TestBuilderPrepare_ISOUrl(t *testing.T) {
var b Builder
config := testConfig()
delete(config, "iso_url")
delete(config, "iso_urls")
// Test both epty
config["iso_url"] = ""
b = Builder{}
err := b.Prepare(config)
if err == nil {
t.Fatal("should have error")
}
// Test iso_url set
config["iso_url"] = "http://www.packer.io"
b = Builder{}
err = b.Prepare(config)
if err != nil {
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) {
@ -338,6 +386,7 @@ func TestBuilderPrepare_OutputDir(t *testing.T) {
defer os.RemoveAll(dir)
config["output_directory"] = dir
b = Builder{}
err = b.Prepare(config)
if err == nil {
t.Fatal("should have error")
@ -345,6 +394,7 @@ func TestBuilderPrepare_OutputDir(t *testing.T) {
// Test with a good one
config["output_directory"] = "i-hope-i-dont-exist"
b = Builder{}
err = b.Prepare(config)
if err != nil {
t.Fatalf("should not have error: %s", err)
@ -364,6 +414,7 @@ func TestBuilderPrepare_ShutdownTimeout(t *testing.T) {
// Test with a good one
config["shutdown_timeout"] = "5s"
b = Builder{}
err = b.Prepare(config)
if err != nil {
t.Fatalf("should not have error: %s", err)
@ -377,6 +428,7 @@ func TestBuilderPrepare_SSHHostPort(t *testing.T) {
// Bad
config["ssh_host_port_min"] = 1000
config["ssh_host_port_max"] = 500
b = Builder{}
err := b.Prepare(config)
if err == nil {
t.Fatal("should have error")
@ -384,6 +436,7 @@ func TestBuilderPrepare_SSHHostPort(t *testing.T) {
// Bad
config["ssh_host_port_min"] = -500
b = Builder{}
err = b.Prepare(config)
if err == nil {
t.Fatal("should have error")
@ -392,6 +445,7 @@ func TestBuilderPrepare_SSHHostPort(t *testing.T) {
// Good
config["ssh_host_port_min"] = 500
config["ssh_host_port_max"] = 1000
b = Builder{}
err = b.Prepare(config)
if err != nil {
t.Fatalf("should not have error: %s", err)
@ -403,12 +457,14 @@ func TestBuilderPrepare_SSHUser(t *testing.T) {
config := testConfig()
config["ssh_username"] = ""
b = Builder{}
err := b.Prepare(config)
if err == nil {
t.Fatal("should have error")
}
config["ssh_username"] = "exists"
b = Builder{}
err = b.Prepare(config)
if err != nil {
t.Fatalf("should not have error: %s", err)
@ -432,6 +488,7 @@ func TestBuilderPrepare_SSHWaitTimeout(t *testing.T) {
// Test with a bad value
config["ssh_wait_timeout"] = "this is not good"
b = Builder{}
err = b.Prepare(config)
if err == nil {
t.Fatal("should have error")
@ -439,6 +496,7 @@ func TestBuilderPrepare_SSHWaitTimeout(t *testing.T) {
// Test with a good one
config["ssh_wait_timeout"] = "5s"
b = Builder{}
err = b.Prepare(config)
if err != nil {
t.Fatalf("should not have error: %s", err)