builder/virtualbox: support generic hash types [GH-175]

This commit is contained in:
Mitchell Hashimoto 2013-07-14 15:50:34 +09:00
parent c62d7e2a3d
commit 3007498282
5 changed files with 88 additions and 15 deletions

View File

@ -2,6 +2,7 @@ package common
import (
"bytes"
"crypto/md5"
"encoding/hex"
"errors"
"fmt"
@ -46,6 +47,17 @@ type DownloadClient struct {
downloader Downloader
}
// HashForType returns the Hash implementation for the given string
// type, or nil if the type is not supported.
func HashForType(t string) hash.Hash {
switch t {
case "md5":
return md5.New()
default:
return nil
}
}
// NewDownloadClient returns a new DownloadClient for the given
// configuration.
func NewDownloadClient(c *DownloadConfig) *DownloadClient {

View File

@ -40,3 +40,22 @@ func TestDownloadClient_VerifyChecksum(t *testing.T) {
t.Fatal("didn't verify")
}
}
func TestHashForType(t *testing.T) {
if h := HashForType("md5"); h == nil {
t.Fatalf("md5 hash is nil")
} else {
h.Write([]byte("foo"))
result := h.Sum(nil)
expected := "acbd18db4cc2f85cedef654fccc4a4d8"
actual := hex.EncodeToString(result)
if actual != expected {
t.Fatalf("bad hash: %s", actual)
}
}
if HashForType("fake") != nil {
t.Fatalf("fake hash is not nil")
}
}

View File

@ -38,7 +38,8 @@ type config struct {
HTTPDir string `mapstructure:"http_directory"`
HTTPPortMin uint `mapstructure:"http_port_min"`
HTTPPortMax uint `mapstructure:"http_port_max"`
ISOMD5 string `mapstructure:"iso_md5"`
ISOChecksum string `mapstructure:"iso_checksum"`
ISOChecksumType string `mapstructure:"iso_checksum_type"`
ISOUrl string `mapstructure:"iso_url"`
OutputDir string `mapstructure:"output_directory"`
ShutdownCommand string `mapstructure:"shutdown_command"`
@ -155,10 +156,21 @@ func (b *Builder) Prepare(raws ...interface{}) error {
errs = append(errs, errors.New("http_port_min must be less than http_port_max"))
}
if b.config.ISOMD5 == "" {
errs = append(errs, errors.New("Due to large file sizes, an iso_md5 is required"))
if b.config.ISOChecksum == "" {
errs = append(errs, errors.New("Due to large file sizes, an iso_checksum is required"))
} else {
b.config.ISOMD5 = strings.ToLower(b.config.ISOMD5)
b.config.ISOChecksum = strings.ToLower(b.config.ISOChecksum)
}
if b.config.ISOChecksumType == "" {
errs = append(errs, errors.New("The iso_checksum_type must be specified."))
} else {
b.config.ISOChecksumType = strings.ToLower(b.config.ISOChecksumType)
if h := common.HashForType(b.config.ISOChecksumType); h == nil {
errs = append(
errs,
fmt.Errorf("Unsupported checksum type: %s", b.config.ISOChecksumType))
}
}
if b.config.ISOUrl == "" {

View File

@ -10,9 +10,10 @@ import (
func testConfig() map[string]interface{} {
return map[string]interface{}{
"iso_md5": "foo",
"iso_url": "http://www.google.com/",
"ssh_username": "foo",
"iso_checksum": "foo",
"iso_checksum_type": "md5",
"iso_url": "http://www.google.com/",
"ssh_username": "foo",
packer.BuildNameConfigKey: "foo",
}
@ -283,26 +284,56 @@ func TestBuilderPrepare_InvalidKey(t *testing.T) {
}
}
func TestBuilderPrepare_ISOMD5(t *testing.T) {
func TestBuilderPrepare_ISOChecksum(t *testing.T) {
var b Builder
config := testConfig()
// Test bad
config["iso_md5"] = ""
config["iso_checksum"] = ""
err := b.Prepare(config)
if err == nil {
t.Fatal("should have error")
}
// Test good
config["iso_md5"] = "FOo"
config["iso_checksum"] = "FOo"
err = b.Prepare(config)
if err != nil {
t.Fatalf("should not have error: %s", err)
}
if b.config.ISOMD5 != "foo" {
t.Fatalf("should've lowercased: %s", b.config.ISOMD5)
if b.config.ISOChecksum != "foo" {
t.Fatalf("should've lowercased: %s", b.config.ISOChecksum)
}
}
func TestBuilderPrepare_ISOChecksumType(t *testing.T) {
var b Builder
config := testConfig()
// Test bad
config["iso_checksum_type"] = ""
err := b.Prepare(config)
if err == nil {
t.Fatal("should have error")
}
// Test good
config["iso_checksum_type"] = "mD5"
err = b.Prepare(config)
if err != nil {
t.Fatalf("should not have error: %s", err)
}
if b.config.ISOChecksumType != "md5" {
t.Fatalf("should've lowercased: %s", b.config.ISOChecksumType)
}
// Test unknown
config["iso_checksum_type"] = "fake"
err = b.Prepare(config)
if err == nil {
t.Fatal("should have error")
}
}

View File

@ -1,7 +1,6 @@
package virtualbox
import (
"crypto/md5"
"encoding/hex"
"fmt"
"github.com/mitchellh/multistep"
@ -33,7 +32,7 @@ func (s *stepDownloadISO) Run(state map[string]interface{}) multistep.StepAction
config := state["config"].(*config)
ui := state["ui"].(packer.Ui)
checksum, err := hex.DecodeString(config.ISOMD5)
checksum, err := hex.DecodeString(config.ISOChecksum)
if err != nil {
state["error"] = fmt.Errorf("Error parsing checksum: %s", err)
return multistep.ActionHalt
@ -47,7 +46,7 @@ func (s *stepDownloadISO) Run(state map[string]interface{}) multistep.StepAction
Url: config.ISOUrl,
TargetPath: cachePath,
CopyFile: false,
Hash: md5.New(),
Hash: common.HashForType(config.ISOChecksumType),
Checksum: checksum,
}