forked from hashicorp/packer
/
config.go
158 lines (138 loc) · 5.2 KB
/
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
package ovf
import (
"fmt"
"net/url"
"os"
"strings"
vboxcommon "github.com/hashicorp/packer/builder/virtualbox/common"
"github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template/interpolate"
)
// Config is the configuration structure for the builder.
type Config struct {
common.PackerConfig `mapstructure:",squash"`
common.HTTPConfig `mapstructure:",squash"`
common.FloppyConfig `mapstructure:",squash"`
vboxcommon.ExportConfig `mapstructure:",squash"`
vboxcommon.ExportOpts `mapstructure:",squash"`
vboxcommon.OutputConfig `mapstructure:",squash"`
vboxcommon.RunConfig `mapstructure:",squash"`
vboxcommon.SSHConfig `mapstructure:",squash"`
vboxcommon.ShutdownConfig `mapstructure:",squash"`
vboxcommon.VBoxManageConfig `mapstructure:",squash"`
vboxcommon.VBoxManagePostConfig `mapstructure:",squash"`
vboxcommon.VBoxVersionConfig `mapstructure:",squash"`
BootCommand []string `mapstructure:"boot_command"`
Checksum string `mapstructure:"checksum"`
ChecksumType string `mapstructure:"checksum_type"`
GuestAdditionsMode string `mapstructure:"guest_additions_mode"`
GuestAdditionsPath string `mapstructure:"guest_additions_path"`
GuestAdditionsSHA256 string `mapstructure:"guest_additions_sha256"`
GuestAdditionsURL string `mapstructure:"guest_additions_url"`
ImportFlags []string `mapstructure:"import_flags"`
ImportOpts string `mapstructure:"import_opts"`
SourcePath string `mapstructure:"source_path"`
TargetPath string `mapstructure:"target_path"`
VMName string `mapstructure:"vm_name"`
KeepRegistered bool `mapstructure:"keep_registered"`
SkipExport bool `mapstructure:"skip_export"`
ctx interpolate.Context
}
func NewConfig(raws ...interface{}) (*Config, []string, error) {
c := new(Config)
err := config.Decode(c, &config.DecodeOpts{
Interpolate: true,
InterpolateContext: &c.ctx,
InterpolateFilter: &interpolate.RenderFilter{
Exclude: []string{
"boot_command",
"guest_additions_path",
"guest_additions_url",
"vboxmanage",
"vboxmanage_post",
},
},
}, raws...)
if err != nil {
return nil, nil, err
}
// Defaults
if c.GuestAdditionsMode == "" {
c.GuestAdditionsMode = "upload"
}
if c.GuestAdditionsPath == "" {
c.GuestAdditionsPath = "VBoxGuestAdditions.iso"
}
if c.VMName == "" {
c.VMName = fmt.Sprintf(
"packer-%s-%d", c.PackerBuildName, interpolate.InitTime.Unix())
}
// Prepare the errors
var errs *packer.MultiError
errs = packer.MultiErrorAppend(errs, c.ExportConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.ExportOpts.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.FloppyConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.HTTPConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.OutputConfig.Prepare(&c.ctx, &c.PackerConfig)...)
errs = packer.MultiErrorAppend(errs, c.RunConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.ShutdownConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.SSHConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.VBoxManageConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.VBoxManagePostConfig.Prepare(&c.ctx)...)
errs = packer.MultiErrorAppend(errs, c.VBoxVersionConfig.Prepare(&c.ctx)...)
c.ChecksumType = strings.ToLower(c.ChecksumType)
c.Checksum = strings.ToLower(c.Checksum)
if c.SourcePath == "" {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("source_path is required"))
} else {
c.SourcePath, err = common.DownloadableURL(c.SourcePath)
if err != nil {
errs = packer.MultiErrorAppend(errs, fmt.Errorf("source_path is invalid: %s", err))
}
// file must exist now.
fileURL, _ := url.Parse(c.SourcePath)
if fileURL.Scheme == "file" {
if _, err := os.Stat(fileURL.Path); err != nil {
errs = packer.MultiErrorAppend(errs,
fmt.Errorf("source file needs to exist at time of config validation: %s", err))
}
}
}
validMode := false
validModes := []string{
vboxcommon.GuestAdditionsModeDisable,
vboxcommon.GuestAdditionsModeAttach,
vboxcommon.GuestAdditionsModeUpload,
}
for _, mode := range validModes {
if c.GuestAdditionsMode == mode {
validMode = true
break
}
}
if !validMode {
errs = packer.MultiErrorAppend(errs,
fmt.Errorf("guest_additions_mode is invalid. Must be one of: %v", validModes))
}
if c.GuestAdditionsSHA256 != "" {
c.GuestAdditionsSHA256 = strings.ToLower(c.GuestAdditionsSHA256)
}
// Warnings
var warnings []string
if c.ShutdownCommand == "" {
warnings = append(warnings,
"A shutdown_command was not specified. Without a shutdown command, Packer\n"+
"will forcibly halt the virtual machine, which may result in data loss.")
}
// Check for any errors.
if errs != nil && len(errs.Errors) > 0 {
return nil, warnings, errs
}
// TODO: Write a packer fix and just remove import_opts
if c.ImportOpts != "" {
c.ImportFlags = append(c.ImportFlags, "--options", c.ImportOpts)
}
return c, warnings, nil
}