/
iso_config.go
192 lines (180 loc) · 6.36 KB
/
iso_config.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
//go:generate struct-markdown
package common
import (
"encoding/hex"
"errors"
"fmt"
"log"
"net/url"
"os"
"strings"
getter "github.com/hashicorp/go-getter"
"github.com/hashicorp/packer/template/interpolate"
)
// By default, Packer will symlink, download or copy image files to the Packer
// cache into a "`hash($iso_url+$iso_checksum).$iso_target_extension`" file.
// Packer uses [hashicorp/go-getter](https://github.com/hashicorp/go-getter) in
// file mode in order to perform a download.
//
// go-getter supports the following protocols:
//
// * Local files
// * Git
// * Mercurial
// * HTTP
// * Amazon S3
//
//
// \~> On windows - when referencing a local iso - if packer is running
// without symlinking rights, the iso will be copied to the cache folder. Read
// [Symlinks in Windows 10
// !](https://blogs.windows.com/buildingapps/2016/12/02/symlinks-windows-10/)
// for more info.
//
// Examples:
// go-getter can guess the checksum type based on `iso_checksum` len.
//
// ``` json
// {
// "iso_checksum": "946a6077af6f5f95a51f82fdc44051c7aa19f9cfc5f737954845a6050543d7c2",
// "iso_url": "ubuntu.org/.../ubuntu-14.04.1-server-amd64.iso"
// }
// ```
//
// ``` json
// {
// "iso_checksum_type": "file",
// "iso_checksum": "ubuntu.org/..../ubuntu-14.04.1-server-amd64.iso.sum",
// "iso_url": "ubuntu.org/.../ubuntu-14.04.1-server-amd64.iso"
// }
// ```
//
// ``` json
// {
// "iso_checksum_url": "./shasums.txt",
// "iso_url": "ubuntu.org/.../ubuntu-14.04.1-server-amd64.iso"
// }
// ```
//
// ``` json
// {
// "iso_checksum_type": "sha256",
// "iso_checksum_url": "./shasums.txt",
// "iso_url": "ubuntu.org/.../ubuntu-14.04.1-server-amd64.iso"
// }
// ```
//
type ISOConfig struct {
// The checksum for the ISO file or virtual hard drive file. The algorithm
// to use when computing the checksum can be optionally specified with
// `iso_checksum_type`. When `iso_checksum_type` is not set packer will
// guess the checksumming type based on `iso_checksum` length.
// `iso_checksum` can be also be a file or an URL, in which case
// `iso_checksum_type` must be set to `file`; the go-getter will download
// it and use the first hash found.
ISOChecksum string `mapstructure:"iso_checksum" required:"true"`
// An URL to a checksum file containing a checksum for the ISO file. At
// least one of `iso_checksum` and `iso_checksum_url` must be defined.
// `iso_checksum_url` will be ignored if `iso_checksum` is non empty.
ISOChecksumURL string `mapstructure:"iso_checksum_url"`
// The algorithm to be used when computing the checksum of the file
// specified in `iso_checksum`. Currently, valid values are "", "none",
// "md5", "sha1", "sha256", "sha512" or "file". Since the validity of ISO
// and virtual disk files are typically crucial to a successful build,
// Packer performs a check of any supplied media by default. While setting
// "none" will cause Packer to skip this check, corruption of large files
// such as ISOs and virtual hard drives can occur from time to time. As
// such, skipping this check is not recommended. `iso_checksum_type` must
// be set to `file` when `iso_checksum` is an url.
ISOChecksumType string `mapstructure:"iso_checksum_type"`
// A URL to the ISO containing the installation image or virtual hard drive
// (VHD or VHDX) file to clone.
RawSingleISOUrl string `mapstructure:"iso_url" required:"true"`
// Multiple URLs for the ISO to download. Packer will try these in order.
// If anything goes wrong attempting to download or while downloading a
// single URL, it will move on to the next. All URLs must point to the same
// file (same checksum). By default this is empty and `iso_url` is used.
// Only one of `iso_url` or `iso_urls` can be specified.
ISOUrls []string `mapstructure:"iso_urls"`
// The path where the iso should be saved after download. By default will
// go in the packer cache, with a hash of the original filename and
// checksum as its name.
TargetPath string `mapstructure:"iso_target_path"`
// The extension of the iso file after download. This defaults to `iso`.
TargetExtension string `mapstructure:"iso_target_extension"`
}
func (c *ISOConfig) Prepare(ctx *interpolate.Context) (warnings []string, errs []error) {
if len(c.ISOUrls) != 0 && c.RawSingleISOUrl != "" {
errs = append(
errs, errors.New("Only one of iso_url or iso_urls must be specified"))
return
}
if c.RawSingleISOUrl != "" {
// make sure only array is set
c.ISOUrls = append([]string{c.RawSingleISOUrl}, c.ISOUrls...)
c.RawSingleISOUrl = ""
}
if len(c.ISOUrls) == 0 {
errs = append(
errs, errors.New("One of iso_url or iso_urls must be specified"))
return
}
c.ISOChecksumType = strings.ToLower(c.ISOChecksumType)
if c.TargetExtension == "" {
c.TargetExtension = "iso"
}
c.TargetExtension = strings.ToLower(c.TargetExtension)
// Warnings
if c.ISOChecksumType == "none" {
warnings = append(warnings,
"A checksum type of 'none' was specified. Since ISO files are so big,\n"+
"a checksum is highly recommended.")
return warnings, errs
}
if c.ISOChecksumURL != "" {
if c.ISOChecksum != "" {
warnings = append(warnings, "You have provided both an "+
"iso_checksum and an iso_checksum_url. Discarding the "+
"iso_checksum_url and using the checksum.")
} else {
if strings.HasSuffix(strings.ToLower(c.ISOChecksumURL), ".iso") {
errs = append(errs, fmt.Errorf("Error parsing checksum:"+
" .iso is not a valid checksum extension"))
}
// go-getter auto-parses checksum files
c.ISOChecksumType = "file"
c.ISOChecksum = c.ISOChecksumURL
}
}
if c.ISOChecksum == "" {
errs = append(errs, fmt.Errorf("A checksum must be specified"))
}
if c.ISOChecksumType == "file" {
u, err := url.Parse(c.ISOUrls[0])
if err != nil {
errs = append(errs, fmt.Errorf("error parsing URL <%s>: %s",
c.ISOUrls[0], err))
}
wd, err := os.Getwd()
if err != nil {
log.Printf("get working directory: %v", err)
// here we ignore the error in case the
// working directory is not needed.
}
gc := getter.Client{
Dst: "no-op",
Src: u.String(),
Pwd: wd,
Dir: false,
Getters: getter.Getters,
}
cksum, err := gc.ChecksumFromFile(c.ISOChecksumURL, u)
if cksum == nil || err != nil {
errs = append(errs, fmt.Errorf("Couldn't extract checksum from checksum file"))
} else {
c.ISOChecksumType = cksum.Type
c.ISOChecksum = hex.EncodeToString(cksum.Value)
}
}
return warnings, errs
}