Merge pull request #3162 from rickard-von-essen/checksum
Allow to specify ISO checksum via URL
This commit is contained in:
commit
df6e4c0565
|
@ -1,8 +1,14 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/packer/template/interpolate"
|
||||
|
@ -11,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"`
|
||||
|
@ -23,27 +30,6 @@ func (c *ISOConfig) Prepare(ctx *interpolate.Context) ([]string, []error) {
|
|||
var err error
|
||||
var warnings []string
|
||||
|
||||
if c.ISOChecksumType == "" {
|
||||
errs = append(
|
||||
errs, errors.New("The iso_checksum_type must be specified."))
|
||||
} else {
|
||||
c.ISOChecksumType = strings.ToLower(c.ISOChecksumType)
|
||||
if c.ISOChecksumType != "none" {
|
||||
if c.ISOChecksum == "" {
|
||||
errs = append(
|
||||
errs, errors.New("Due to large file sizes, an iso_checksum is required"))
|
||||
} else {
|
||||
c.ISOChecksum = strings.ToLower(c.ISOChecksum)
|
||||
}
|
||||
|
||||
if h := HashForType(c.ISOChecksumType); h == nil {
|
||||
errs = append(
|
||||
errs,
|
||||
fmt.Errorf("Unsupported checksum type: %s", c.ISOChecksumType))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if c.RawSingleISOUrl == "" && len(c.ISOUrls) == 0 {
|
||||
errs = append(
|
||||
errs, errors.New("One of iso_url or iso_urls must be specified."))
|
||||
|
@ -54,6 +40,72 @@ func (c *ISOConfig) Prepare(ctx *interpolate.Context) ([]string, []error) {
|
|||
c.ISOUrls = []string{c.RawSingleISOUrl}
|
||||
}
|
||||
|
||||
if c.ISOChecksumType == "" {
|
||||
errs = append(
|
||||
errs, errors.New("The iso_checksum_type must be specified."))
|
||||
} else {
|
||||
c.ISOChecksumType = strings.ToLower(c.ISOChecksumType)
|
||||
if c.ISOChecksumType != "none" {
|
||||
if c.ISOChecksum == "" && c.ISOChecksumURL == "" {
|
||||
errs = append(
|
||||
errs, errors.New("Due to large file sizes, an iso_checksum is required"))
|
||||
return warnings, errs
|
||||
} else {
|
||||
if h := HashForType(c.ISOChecksumType); h == nil {
|
||||
errs = append(
|
||||
errs, fmt.Errorf("Unsupported checksum type: %s", c.ISOChecksumType))
|
||||
return warnings, errs
|
||||
}
|
||||
|
||||
// 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 parsing checksum: %s", err))
|
||||
return warnings, errs
|
||||
}
|
||||
switch u.Scheme {
|
||||
case "http", "https":
|
||||
res, err := http.Get(c.ISOChecksumURL)
|
||||
c.ISOChecksum = ""
|
||||
if err != nil {
|
||||
errs = append(errs,
|
||||
fmt.Errorf("Error getting checksum from url: %s", c.ISOChecksumURL))
|
||||
return warnings, errs
|
||||
}
|
||||
defer res.Body.Close()
|
||||
err = c.parseCheckSumFile(bufio.NewReader(res.Body))
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
return warnings, errs
|
||||
}
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.ISOChecksum = strings.ToLower(c.ISOChecksum)
|
||||
|
||||
for i, url := range c.ISOUrls {
|
||||
c.ISOUrls[i], err = DownloadableURL(url)
|
||||
if err != nil {
|
||||
|
@ -71,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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -59,7 +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.
|
||||
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
|
||||
|
@ -67,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.
|
||||
|
|
|
@ -83,11 +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.
|
||||
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
|
||||
|
|
|
@ -57,7 +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.
|
||||
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
|
||||
|
@ -65,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.
|
||||
|
|
|
@ -60,7 +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.
|
||||
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 +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.
|
||||
|
|
Loading…
Reference in New Issue