Added "iso_checksum_url" and keep the functionality of "iso_checksum"

Added support for file shema in "iso_checksum_url".
Added some unit tests and updated the docs accordingly.
This commit is contained in:
Rickard von Essen 2016-02-08 15:51:43 +01:00
parent 00fcc3dfdc
commit bbade5d8ae
6 changed files with 175 additions and 62 deletions

View File

@ -4,8 +4,10 @@ import (
"bufio"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"os"
"path/filepath"
"strings"
@ -15,6 +17,7 @@ import (
// ISOConfig contains configuration for downloading ISO images.
type ISOConfig struct {
ISOChecksum string `mapstructure:"iso_checksum"`
ISOChecksumURL string `mapstructure:"iso_checksum_url"`
ISOChecksumType string `mapstructure:"iso_checksum_type"`
ISOUrls []string `mapstructure:"iso_urls"`
TargetPath string `mapstructure:"iso_target_path"`
@ -43,7 +46,7 @@ func (c *ISOConfig) Prepare(ctx *interpolate.Context) ([]string, []error) {
} else {
c.ISOChecksumType = strings.ToLower(c.ISOChecksumType)
if c.ISOChecksumType != "none" {
if c.ISOChecksum == "" {
if c.ISOChecksum == "" && c.ISOChecksumURL == "" {
errs = append(
errs, errors.New("Due to large file sizes, an iso_checksum is required"))
return warnings, errs
@ -54,59 +57,48 @@ func (c *ISOConfig) Prepare(ctx *interpolate.Context) ([]string, []error) {
return warnings, errs
}
u, err := url.Parse(c.ISOChecksum)
if err != nil {
errs = append(errs,
fmt.Errorf("Error parsing checksum: %s", err))
return warnings, errs
}
switch u.Scheme {
case "http", "https", "ftp", "ftps":
res, err := http.Get(c.ISOChecksum)
c.ISOChecksum = ""
// If iso_checksum has no value use iso_checksum_url instead.
if c.ISOChecksum == "" {
u, err := url.Parse(c.ISOChecksumURL)
if err != nil {
errs = append(errs,
fmt.Errorf("Error getting checksum from url: %s", c.ISOChecksum))
fmt.Errorf("Error parsing checksum: %s", err))
return warnings, errs
}
defer res.Body.Close()
rd := bufio.NewReader(res.Body)
for {
line, err := rd.ReadString('\n')
switch u.Scheme {
case "http", "https", "ftp", "ftps":
res, err := http.Get(c.ISOChecksumURL)
c.ISOChecksum = ""
if err != nil {
errs = append(errs,
fmt.Errorf("Error getting checksum from url: %s , %s", c.ISOChecksum, err.Error()))
fmt.Errorf("Error getting checksum from url: %s", c.ISOChecksumURL))
return warnings, errs
}
parts := strings.Fields(line)
if len(parts) < 2 {
continue
defer res.Body.Close()
err = c.parseCheckSumFile(bufio.NewReader(res.Body))
if err != nil {
errs = append(errs, err)
return warnings, errs
}
if strings.ToLower(parts[0]) == c.ISOChecksumType {
// BSD-style checksum
if parts[1] == fmt.Sprintf("(%s)", filepath.Base(c.ISOUrls[0])) {
c.ISOChecksum = parts[3]
break
}
} else {
// Standard checksum
if parts[1][0] == '*' {
// Binary mode
parts[1] = parts[1][1:]
}
if parts[1] == filepath.Base(c.ISOUrls[0]) {
c.ISOChecksum = parts[0]
break
}
case "file":
file, err := os.Open(u.Path)
if err != nil {
errs = append(errs, err)
return warnings, errs
}
err = c.parseCheckSumFile(bufio.NewReader(file))
if err != nil {
errs = append(errs, err)
return warnings, errs
}
case "":
break
default:
errs = append(errs,
fmt.Errorf("Error parsing checksum url: %s, scheme not supported: %s", c.ISOChecksumURL, u.Scheme))
return warnings, errs
}
case "":
break
default:
errs = append(errs,
fmt.Errorf("Error parsing checksum url, scheme not supported: %s", u.Scheme))
return warnings, errs
}
}
}
@ -131,3 +123,38 @@ func (c *ISOConfig) Prepare(ctx *interpolate.Context) ([]string, []error) {
return warnings, errs
}
func (c *ISOConfig) parseCheckSumFile(rd *bufio.Reader) error {
for {
line, err := rd.ReadString('\n')
if err != nil {
if err == io.EOF {
return fmt.Errorf("No checksum for \"%s\" found at: %s", filepath.Base(c.ISOUrls[0]), c.ISOChecksumURL)
} else {
return fmt.Errorf("Error getting checksum from url: %s , %s", c.ISOChecksumURL, err.Error())
}
}
parts := strings.Fields(line)
if len(parts) < 2 {
continue
}
if strings.ToLower(parts[0]) == c.ISOChecksumType {
// BSD-style checksum
if parts[1] == fmt.Sprintf("(%s)", filepath.Base(c.ISOUrls[0])) {
c.ISOChecksum = parts[3]
break
}
} else {
// Standard checksum
if parts[1][0] == '*' {
// Binary mode
parts[1] = parts[1][1:]
}
if parts[1] == filepath.Base(c.ISOUrls[0]) {
c.ISOChecksum = parts[0]
break
}
}
}
return nil
}

View File

@ -1,6 +1,8 @@
package common
import (
"fmt"
"io/ioutil"
"reflect"
"testing"
)
@ -8,11 +10,22 @@ import (
func testISOConfig() ISOConfig {
return ISOConfig{
ISOChecksum: "foo",
ISOChecksumURL: "",
ISOChecksumType: "md5",
RawSingleISOUrl: "http://www.packer.io",
RawSingleISOUrl: "http://www.packer.io/the-OS.iso",
}
}
var cs_bsd_style = `
MD5 (other.iso) = bAr
MD5 (the-OS.iso) = baZ
`
var cs_gnu_style = `
bAr0 *the-OS.iso
baZ0 other.iso
`
func TestISOConfigPrepare_ISOChecksum(t *testing.T) {
i := testISOConfig()
@ -42,6 +55,53 @@ func TestISOConfigPrepare_ISOChecksum(t *testing.T) {
}
}
func TestISOConfigPrepare_ISOChecksumURL(t *testing.T) {
i := testISOConfig()
i.ISOChecksumURL = "file:///not_read"
// Test ISOChecksum overrides url
warns, err := i.Prepare(nil)
if len(warns) > 0 && len(err) > 0 {
t.Fatalf("bad: %#v, %#v", warns, err)
}
// Test good - ISOChecksumURL BSD style
i = testISOConfig()
i.ISOChecksum = ""
cs_file, _ := ioutil.TempFile("", "packer-test-")
ioutil.WriteFile(cs_file.Name(), []byte(cs_bsd_style), 0666)
i.ISOChecksumURL = fmt.Sprintf("file://%s", cs_file.Name())
warns, err = i.Prepare(nil)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
if i.ISOChecksum != "baz" {
t.Fatalf("should've found \"baz\" got: %s", i.ISOChecksum)
}
// Test good - ISOChecksumURL GNU style
i = testISOConfig()
i.ISOChecksum = ""
cs_file, _ = ioutil.TempFile("", "packer-test-")
ioutil.WriteFile(cs_file.Name(), []byte(cs_gnu_style), 0666)
i.ISOChecksumURL = fmt.Sprintf("file://%s", cs_file.Name())
warns, err = i.Prepare(nil)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
}
if err != nil {
t.Fatalf("should not have error: %s", err)
}
if i.ISOChecksum != "bar0" {
t.Fatalf("should've found \"bar0\" got: %s", i.ISOChecksum)
}
}
func TestISOConfigPrepare_ISOChecksumType(t *testing.T) {
i := testISOConfig()
@ -113,7 +173,7 @@ func TestISOConfigPrepare_ISOUrl(t *testing.T) {
// Test iso_url set
i = testISOConfig()
i.RawSingleISOUrl = "http://www.packer.io"
i.RawSingleISOUrl = "http://www.packer.io/the-OS.iso"
warns, err = i.Prepare(nil)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
@ -122,15 +182,15 @@ func TestISOConfigPrepare_ISOUrl(t *testing.T) {
t.Errorf("should not have error: %s", err)
}
expected := []string{"http://www.packer.io"}
expected := []string{"http://www.packer.io/the-OS.iso"}
if !reflect.DeepEqual(i.ISOUrls, expected) {
t.Fatalf("bad: %#v", i.ISOUrls)
}
// Test both set
i = testISOConfig()
i.RawSingleISOUrl = "http://www.packer.io"
i.ISOUrls = []string{"http://www.packer.io"}
i.RawSingleISOUrl = "http://www.packer.io/the-OS.iso"
i.ISOUrls = []string{"http://www.packer.io/the-OS.iso"}
warns, err = i.Prepare(nil)
if len(warns) > 0 {
t.Fatalf("bad: %#v", warns)
@ -143,8 +203,8 @@ func TestISOConfigPrepare_ISOUrl(t *testing.T) {
i = testISOConfig()
i.RawSingleISOUrl = ""
i.ISOUrls = []string{
"http://www.packer.io",
"http://www.hashicorp.com",
"http://www.packer.io/the-OS.iso",
"http://www.hashicorp.com/the-OS.iso",
}
warns, err = i.Prepare(nil)
@ -156,8 +216,8 @@ func TestISOConfigPrepare_ISOUrl(t *testing.T) {
}
expected = []string{
"http://www.packer.io",
"http://www.hashicorp.com",
"http://www.packer.io/the-OS.iso",
"http://www.hashicorp.com/the-OS.iso",
}
if !reflect.DeepEqual(i.ISOUrls, expected) {
t.Fatalf("bad: %#v", i.ISOUrls)

View File

@ -59,8 +59,9 @@ builder.
- `iso_checksum` (string) - The checksum for the OS ISO file. Because ISO
files are so large, this is required and Packer will verify it prior to
booting a virtual machine with the ISO attached. The type of the checksum is
specified with `iso_checksum_type`, documented below. Also can be url that
contains checksum file with `iso_checksum_type` type.
specified with `iso_checksum_type`, documented below. At least one of
`iso_checksum` and `iso_checksum_url` must be defined. This has precedence
over `iso_checksum_url` type.
- `iso_checksum_type` (string) - The type of the checksum specified in
`iso_checksum`. Valid values are "none", "md5", "sha1", "sha256", or
@ -68,6 +69,11 @@ builder.
recommended since ISO files are generally large and corruption does happen
from time to time.
- `iso_checksum_url` (string) - A URL to a GNU or BSD style checksum file
containing a checksum for the OS ISO file. At least one of `iso_checksum`
and `iso_checksum_url` must be defined. This will be ignored if
`iso_checksum` is non empty.
- `iso_url` (string) - A URL to the ISO containing the installation image.
This URL can be either an HTTP URL or a file URL (or path to a file). If
this is an HTTP URL, Packer will download it and cache it between runs.

View File

@ -83,12 +83,20 @@ builder.
- `iso_checksum` (string) - The checksum for the OS ISO file. Because ISO
files are so large, this is required and Packer will verify it prior to
booting a virtual machine with the ISO attached. The type of the checksum is
specified with `iso_checksum_type`, documented below. Also can be url that
contains checksum file with `iso_checksum_type` type.
specified with `iso_checksum_type`, documented below. At least one of
`iso_checksum` and `iso_checksum_url` must be defined. This has precedence
over `iso_checksum_url` type.
- `iso_checksum_type` (string) - The type of the checksum specified in
`iso_checksum`. Valid values are "md5", "sha1", "sha256", or
"sha512" currently.
`iso_checksum`. Valid values are "none", "md5", "sha1", "sha256", or
"sha512" currently. While "none" will skip checksumming, this is not
recommended since ISO files are generally large and corruption does happen
from time to time.
- `iso_checksum_url` (string) - A URL to a GNU or BSD style checksum file
containing a checksum for the OS ISO file. At least one of `iso_checksum`
and `iso_checksum_url` must be defined. This will be ignored if
`iso_checksum` is non empty.
- `iso_url` (string) - A URL to the ISO containing the installation image.
This URL can be either an HTTP URL or a file URL (or path to a file). If

View File

@ -57,8 +57,9 @@ builder.
- `iso_checksum` (string) - The checksum for the OS ISO file. Because ISO
files are so large, this is required and Packer will verify it prior to
booting a virtual machine with the ISO attached. The type of the checksum is
specified with `iso_checksum_type`, documented below. Also can be url that
contains checksum file with `iso_checksum_type` type.
specified with `iso_checksum_type`, documented below. At least one of
`iso_checksum` and `iso_checksum_url` must be defined. This has precedence
over `iso_checksum_url` type.
- `iso_checksum_type` (string) - The type of the checksum specified in
`iso_checksum`. Valid values are "none", "md5", "sha1", "sha256", or
@ -66,6 +67,11 @@ builder.
recommended since ISO files are generally large and corruption does happen
from time to time.
- `iso_checksum_url` (string) - A URL to a GNU or BSD style checksum file
containing a checksum for the OS ISO file. At least one of `iso_checksum`
and `iso_checksum_url` must be defined. This will be ignored if
`iso_checksum` is non empty.
- `iso_url` (string) - A URL to the ISO containing the installation image.
This URL can be either an HTTP URL or a file URL (or path to a file). If
this is an HTTP URL, Packer will download it and cache it between runs.

View File

@ -60,8 +60,9 @@ builder.
- `iso_checksum` (string) - The checksum for the OS ISO file. Because ISO
files are so large, this is required and Packer will verify it prior to
booting a virtual machine with the ISO attached. The type of the checksum is
specified with `iso_checksum_type`, documented below. Also can be url that
contains checksum file with `iso_checksum_type` type.
specified with `iso_checksum_type`, documented below. At least one of
`iso_checksum` and `iso_checksum_url` must be defined. This has precedence
over `iso_checksum_url` type.
- `iso_checksum_type` (string) - The type of the checksum specified in
`iso_checksum`. Valid values are "none", "md5", "sha1", "sha256", or
@ -69,6 +70,11 @@ builder.
recommended since ISO files are generally large and corruption does happen
from time to time.
- `iso_checksum_url` (string) - A URL to a GNU or BSD style checksum file
containing a checksum for the OS ISO file. At least one of `iso_checksum`
and `iso_checksum_url` must be defined. This will be ignored if
`iso_checksum` is non empty.
- `iso_url` (string) - A URL to the ISO containing the installation image.
This URL can be either an HTTP URL or a file URL (or path to a file). If
this is an HTTP URL, Packer will download it and cache it between runs.