Unused keys are invalid in templates [GH-104]
This commit is contained in:
parent
245deaf599
commit
3b4ef72e47
|
@ -13,6 +13,8 @@ FEATURES:
|
||||||
|
|
||||||
IMPROVEMENTS:
|
IMPROVEMENTS:
|
||||||
|
|
||||||
|
* everything: invalid keys in configuration are now considered validation
|
||||||
|
errors. [GH-104]
|
||||||
* amazon-ebs: Verify the source AMI is EBS-backed before launching. [GH-169]
|
* amazon-ebs: Verify the source AMI is EBS-backed before launching. [GH-169]
|
||||||
* vmware: error if shutdown command has non-zero exit status.
|
* vmware: error if shutdown command has non-zero exit status.
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,8 @@ import (
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -50,15 +52,38 @@ type Builder struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Builder) Prepare(raws ...interface{}) error {
|
func (b *Builder) Prepare(raws ...interface{}) error {
|
||||||
var err error
|
var md mapstructure.Metadata
|
||||||
|
decoderConfig := &mapstructure.DecoderConfig{
|
||||||
|
Metadata: &md,
|
||||||
|
Result: &b.config,
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder, err := mapstructure.NewDecoder(decoderConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
for _, raw := range raws {
|
for _, raw := range raws {
|
||||||
err := mapstructure.Decode(raw, &b.config)
|
err := decoder.Decode(raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Accumulate any errors
|
||||||
|
errs := make([]error, 0)
|
||||||
|
|
||||||
|
// Unused keys are errors
|
||||||
|
if len(md.Unused) > 0 {
|
||||||
|
sort.Strings(md.Unused)
|
||||||
|
for _, unused := range md.Unused {
|
||||||
|
if unused != "type" && !strings.HasPrefix(unused, "packer_") {
|
||||||
|
errs = append(
|
||||||
|
errs, fmt.Errorf("Unknown configuration key: %s", unused))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if b.config.AccessKey == "" {
|
if b.config.AccessKey == "" {
|
||||||
b.config.AccessKey = os.Getenv("AWS_ACCESS_KEY_ID")
|
b.config.AccessKey = os.Getenv("AWS_ACCESS_KEY_ID")
|
||||||
}
|
}
|
||||||
|
@ -84,8 +109,6 @@ func (b *Builder) Prepare(raws ...interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accumulate any errors
|
// Accumulate any errors
|
||||||
errs := make([]error, 0)
|
|
||||||
|
|
||||||
if b.config.AccessKey == "" {
|
if b.config.AccessKey == "" {
|
||||||
errs = append(errs, errors.New("An access_key must be specified"))
|
errs = append(errs, errors.New("An access_key must be specified"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,6 +148,18 @@ func TestBuilderPrepare_InstanceType(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBuilderPrepare_InvalidKey(t *testing.T) {
|
||||||
|
var b Builder
|
||||||
|
config := testConfig()
|
||||||
|
|
||||||
|
// Add a random key
|
||||||
|
config["i_should_not_be_valid"] = true
|
||||||
|
err := b.Prepare(config)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("should have error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestBuilderPrepare_Region(t *testing.T) {
|
func TestBuilderPrepare_Region(t *testing.T) {
|
||||||
var b Builder
|
var b Builder
|
||||||
config := testConfig()
|
config := testConfig()
|
||||||
|
|
|
@ -13,7 +13,9 @@ import (
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -56,15 +58,39 @@ type Builder struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Builder) Prepare(raws ...interface{}) error {
|
func (b *Builder) Prepare(raws ...interface{}) error {
|
||||||
|
var md mapstructure.Metadata
|
||||||
|
decoderConfig := &mapstructure.DecoderConfig{
|
||||||
|
Metadata: &md,
|
||||||
|
Result: &b.config,
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder, err := mapstructure.NewDecoder(decoderConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
for _, raw := range raws {
|
for _, raw := range raws {
|
||||||
err := mapstructure.Decode(raw, &b.config)
|
err := decoder.Decode(raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Accumulate any errors
|
||||||
|
errs := make([]error, 0)
|
||||||
|
|
||||||
|
// Unused keys are errors
|
||||||
|
if len(md.Unused) > 0 {
|
||||||
|
sort.Strings(md.Unused)
|
||||||
|
for _, unused := range md.Unused {
|
||||||
|
if unused != "type" && !strings.HasPrefix(unused, "packer_") {
|
||||||
|
errs = append(
|
||||||
|
errs, fmt.Errorf("Unknown configuration key: %s", unused))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Optional configuration with defaults
|
// Optional configuration with defaults
|
||||||
//
|
|
||||||
if b.config.APIKey == "" {
|
if b.config.APIKey == "" {
|
||||||
// Default to environment variable for api_key, if it exists
|
// Default to environment variable for api_key, if it exists
|
||||||
b.config.APIKey = os.Getenv("DIGITALOCEAN_API_KEY")
|
b.config.APIKey = os.Getenv("DIGITALOCEAN_API_KEY")
|
||||||
|
@ -123,11 +149,7 @@ func (b *Builder) Prepare(raws ...interface{}) error {
|
||||||
b.config.RawStateTimeout = "6m"
|
b.config.RawStateTimeout = "6m"
|
||||||
}
|
}
|
||||||
|
|
||||||
// A list of errors on the configuration
|
|
||||||
errs := make([]error, 0)
|
|
||||||
|
|
||||||
// Required configurations that will display errors if not set
|
// Required configurations that will display errors if not set
|
||||||
//
|
|
||||||
if b.config.ClientID == "" {
|
if b.config.ClientID == "" {
|
||||||
errs = append(errs, errors.New("a client_id must be specified"))
|
errs = append(errs, errors.New("a client_id must be specified"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,6 +106,18 @@ func TestBuilderPrepare_ClientID(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBuilderPrepare_InvalidKey(t *testing.T) {
|
||||||
|
var b Builder
|
||||||
|
config := testConfig()
|
||||||
|
|
||||||
|
// Add a random key
|
||||||
|
config["i_should_not_be_valid"] = true
|
||||||
|
err := b.Prepare(config)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("should have error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestBuilderPrepare_RegionID(t *testing.T) {
|
func TestBuilderPrepare_RegionID(t *testing.T) {
|
||||||
var b Builder
|
var b Builder
|
||||||
config := testConfig()
|
config := testConfig()
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -62,15 +63,38 @@ type config struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Builder) Prepare(raws ...interface{}) error {
|
func (b *Builder) Prepare(raws ...interface{}) error {
|
||||||
var err error
|
var md mapstructure.Metadata
|
||||||
|
decoderConfig := &mapstructure.DecoderConfig{
|
||||||
|
Metadata: &md,
|
||||||
|
Result: &b.config,
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder, err := mapstructure.NewDecoder(decoderConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
for _, raw := range raws {
|
for _, raw := range raws {
|
||||||
err := mapstructure.Decode(raw, &b.config)
|
err := decoder.Decode(raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Accumulate any errors
|
||||||
|
errs := make([]error, 0)
|
||||||
|
|
||||||
|
// Unused keys are errors
|
||||||
|
if len(md.Unused) > 0 {
|
||||||
|
sort.Strings(md.Unused)
|
||||||
|
for _, unused := range md.Unused {
|
||||||
|
if unused != "type" && !strings.HasPrefix(unused, "packer_") {
|
||||||
|
errs = append(
|
||||||
|
errs, fmt.Errorf("Unknown configuration key: %s", unused))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if b.config.DiskSize == 0 {
|
if b.config.DiskSize == 0 {
|
||||||
b.config.DiskSize = 40000
|
b.config.DiskSize = 40000
|
||||||
}
|
}
|
||||||
|
@ -127,8 +151,6 @@ func (b *Builder) Prepare(raws ...interface{}) error {
|
||||||
b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName)
|
b.config.VMName = fmt.Sprintf("packer-%s", b.config.PackerBuildName)
|
||||||
}
|
}
|
||||||
|
|
||||||
errs := make([]error, 0)
|
|
||||||
|
|
||||||
if b.config.HTTPPortMin > b.config.HTTPPortMax {
|
if b.config.HTTPPortMin > b.config.HTTPPortMax {
|
||||||
errs = append(errs, errors.New("http_port_min must be less than http_port_max"))
|
errs = append(errs, errors.New("http_port_min must be less than http_port_max"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -271,6 +271,18 @@ func TestBuilderPrepare_HTTPPort(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBuilderPrepare_InvalidKey(t *testing.T) {
|
||||||
|
var b Builder
|
||||||
|
config := testConfig()
|
||||||
|
|
||||||
|
// Add a random key
|
||||||
|
config["i_should_not_be_valid"] = true
|
||||||
|
err := b.Prepare(config)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("should have error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestBuilderPrepare_ISOMD5(t *testing.T) {
|
func TestBuilderPrepare_ISOMD5(t *testing.T) {
|
||||||
var b Builder
|
var b Builder
|
||||||
config := testConfig()
|
config := testConfig()
|
||||||
|
|
|
@ -12,6 +12,7 @@ import (
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
"time"
|
"time"
|
||||||
|
@ -63,13 +64,38 @@ type config struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Builder) Prepare(raws ...interface{}) error {
|
func (b *Builder) Prepare(raws ...interface{}) error {
|
||||||
|
var md mapstructure.Metadata
|
||||||
|
decoderConfig := &mapstructure.DecoderConfig{
|
||||||
|
Metadata: &md,
|
||||||
|
Result: &b.config,
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder, err := mapstructure.NewDecoder(decoderConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
for _, raw := range raws {
|
for _, raw := range raws {
|
||||||
err := mapstructure.Decode(raw, &b.config)
|
err := decoder.Decode(raw)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Accumulate any errors
|
||||||
|
errs := make([]error, 0)
|
||||||
|
|
||||||
|
// Unused keys are errors
|
||||||
|
if len(md.Unused) > 0 {
|
||||||
|
sort.Strings(md.Unused)
|
||||||
|
for _, unused := range md.Unused {
|
||||||
|
if unused != "type" && !strings.HasPrefix(unused, "packer_") {
|
||||||
|
errs = append(
|
||||||
|
errs, fmt.Errorf("Unknown configuration key: %s", unused))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if b.config.DiskName == "" {
|
if b.config.DiskName == "" {
|
||||||
b.config.DiskName = "disk"
|
b.config.DiskName = "disk"
|
||||||
}
|
}
|
||||||
|
@ -122,10 +148,6 @@ func (b *Builder) Prepare(raws ...interface{}) error {
|
||||||
b.config.ToolsUploadPath = "{{ .Flavor }}.iso"
|
b.config.ToolsUploadPath = "{{ .Flavor }}.iso"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Accumulate any errors
|
|
||||||
var err error
|
|
||||||
errs := make([]error, 0)
|
|
||||||
|
|
||||||
if b.config.HTTPPortMin > b.config.HTTPPortMax {
|
if b.config.HTTPPortMin > b.config.HTTPPortMax {
|
||||||
errs = append(errs, errors.New("http_port_min must be less than http_port_max"))
|
errs = append(errs, errors.New("http_port_min must be less than http_port_max"))
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,6 +163,18 @@ func TestBuilderPrepare_HTTPPort(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBuilderPrepare_InvalidKey(t *testing.T) {
|
||||||
|
var b Builder
|
||||||
|
config := testConfig()
|
||||||
|
|
||||||
|
// Add a random key
|
||||||
|
config["i_should_not_be_valid"] = true
|
||||||
|
err := b.Prepare(config)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("should have error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestBuilderPrepare_ISOMD5(t *testing.T) {
|
func TestBuilderPrepare_ISOMD5(t *testing.T) {
|
||||||
var b Builder
|
var b Builder
|
||||||
config := testConfig()
|
config := testConfig()
|
||||||
|
|
|
@ -6,6 +6,8 @@ import (
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
"github.com/mitchellh/packer/packer"
|
"github.com/mitchellh/packer/packer"
|
||||||
"os"
|
"os"
|
||||||
|
"sort"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type config struct {
|
type config struct {
|
||||||
|
@ -21,13 +23,37 @@ type Provisioner struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provisioner) Prepare(raws ...interface{}) error {
|
func (p *Provisioner) Prepare(raws ...interface{}) error {
|
||||||
|
var md mapstructure.Metadata
|
||||||
|
decoderConfig := &mapstructure.DecoderConfig{
|
||||||
|
Metadata: &md,
|
||||||
|
Result: &p.config,
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder, err := mapstructure.NewDecoder(decoderConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
for _, raw := range raws {
|
for _, raw := range raws {
|
||||||
if err := mapstructure.Decode(raw, &p.config); err != nil {
|
err := decoder.Decode(raw)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
errs := []error{}
|
// Accumulate any errors
|
||||||
|
errs := make([]error, 0)
|
||||||
|
|
||||||
|
// Unused keys are errors
|
||||||
|
if len(md.Unused) > 0 {
|
||||||
|
sort.Strings(md.Unused)
|
||||||
|
for _, unused := range md.Unused {
|
||||||
|
if unused != "type" && !strings.HasPrefix(unused, "packer_") {
|
||||||
|
errs = append(
|
||||||
|
errs, fmt.Errorf("Unknown configuration key: %s", unused))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if _, err := os.Stat(p.config.Source); err != nil {
|
if _, err := os.Stat(p.config.Source); err != nil {
|
||||||
errs = append(errs,
|
errs = append(errs,
|
||||||
|
|
|
@ -23,6 +23,18 @@ func TestProvisioner_Impl(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestProvisionerPrepare_InvalidKey(t *testing.T) {
|
||||||
|
var p Provisioner
|
||||||
|
config := testConfig()
|
||||||
|
|
||||||
|
// Add a random key
|
||||||
|
config["i_should_not_be_valid"] = true
|
||||||
|
err := p.Prepare(config)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("should have error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestProvisionerPrepare_InvalidSource(t *testing.T) {
|
func TestProvisionerPrepare_InvalidSource(t *testing.T) {
|
||||||
var p Provisioner
|
var p Provisioner
|
||||||
config := testConfig()
|
config := testConfig()
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"text/template"
|
"text/template"
|
||||||
)
|
)
|
||||||
|
@ -58,12 +59,38 @@ type ExecuteCommandTemplate struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Provisioner) Prepare(raws ...interface{}) error {
|
func (p *Provisioner) Prepare(raws ...interface{}) error {
|
||||||
|
var md mapstructure.Metadata
|
||||||
|
decoderConfig := &mapstructure.DecoderConfig{
|
||||||
|
Metadata: &md,
|
||||||
|
Result: &p.config,
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder, err := mapstructure.NewDecoder(decoderConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
for _, raw := range raws {
|
for _, raw := range raws {
|
||||||
if err := mapstructure.Decode(raw, &p.config); err != nil {
|
err := decoder.Decode(raw)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Accumulate any errors
|
||||||
|
errs := make([]error, 0)
|
||||||
|
|
||||||
|
// Unused keys are errors
|
||||||
|
if len(md.Unused) > 0 {
|
||||||
|
sort.Strings(md.Unused)
|
||||||
|
for _, unused := range md.Unused {
|
||||||
|
if unused != "type" && !strings.HasPrefix(unused, "packer_") {
|
||||||
|
errs = append(
|
||||||
|
errs, fmt.Errorf("Unknown configuration key: %s", unused))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if p.config.ExecuteCommand == "" {
|
if p.config.ExecuteCommand == "" {
|
||||||
p.config.ExecuteCommand = "chmod +x {{.Path}}; {{.Vars}} {{.Path}}"
|
p.config.ExecuteCommand = "chmod +x {{.Path}}; {{.Vars}} {{.Path}}"
|
||||||
}
|
}
|
||||||
|
@ -88,8 +115,6 @@ func (p *Provisioner) Prepare(raws ...interface{}) error {
|
||||||
p.config.Vars = make([]string, 0)
|
p.config.Vars = make([]string, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
errs := make([]error, 0)
|
|
||||||
|
|
||||||
if p.config.Script != "" && len(p.config.Scripts) > 0 {
|
if p.config.Script != "" && len(p.config.Scripts) > 0 {
|
||||||
errs = append(errs, errors.New("Only one of script or scripts can be specified."))
|
errs = append(errs, errors.New("Only one of script or scripts can be specified."))
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,18 @@ func TestProvisionerPrepare_InlineShebang(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestProvisionerPrepare_InvalidKey(t *testing.T) {
|
||||||
|
var p Provisioner
|
||||||
|
config := testConfig()
|
||||||
|
|
||||||
|
// Add a random key
|
||||||
|
config["i_should_not_be_valid"] = true
|
||||||
|
err := p.Prepare(config)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatal("should have error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestProvisionerPrepare_Script(t *testing.T) {
|
func TestProvisionerPrepare_Script(t *testing.T) {
|
||||||
config := testConfig()
|
config := testConfig()
|
||||||
delete(config, "inline")
|
delete(config, "inline")
|
||||||
|
|
Loading…
Reference in New Issue