Commit 3b4ef72e authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

Unused keys are invalid in templates [GH-104]

parent 245deaf5
......@@ -13,6 +13,8 @@ FEATURES:
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]
* vmware: error if shutdown command has non-zero exit status.
......
......@@ -16,6 +16,8 @@ import (
"github.com/mitchellh/packer/packer"
"log"
"os"
"sort"
"strings"
"text/template"
"time"
)
......@@ -50,15 +52,38 @@ type Builder struct {
}
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 {
err := mapstructure.Decode(raw, &b.config)
err := decoder.Decode(raw)
if err != nil {
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 == "" {
b.config.AccessKey = os.Getenv("AWS_ACCESS_KEY_ID")
}
......@@ -84,8 +109,6 @@ func (b *Builder) Prepare(raws ...interface{}) error {
}
// Accumulate any errors
errs := make([]error, 0)
if b.config.AccessKey == "" {
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) {
var b Builder
config := testConfig()
......
......@@ -13,7 +13,9 @@ import (
"github.com/mitchellh/packer/packer"
"log"
"os"
"sort"
"strconv"
"strings"
"text/template"
"time"
)
......@@ -56,15 +58,39 @@ type Builder struct {
}
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 {
err := mapstructure.Decode(raw, &b.config)
err := decoder.Decode(raw)
if err != nil {
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
//
if b.config.APIKey == "" {
// Default to environment variable for api_key, if it exists
b.config.APIKey = os.Getenv("DIGITALOCEAN_API_KEY")
......@@ -123,11 +149,7 @@ func (b *Builder) Prepare(raws ...interface{}) error {
b.config.RawStateTimeout = "6m"
}
// A list of errors on the configuration
errs := make([]error, 0)
// Required configurations that will display errors if not set
//
if b.config.ClientID == "" {
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) {
var b Builder
config := testConfig()
......
......@@ -12,6 +12,7 @@ import (
"os"
"os/exec"
"path/filepath"
"sort"
"strings"
"time"
)
......@@ -62,15 +63,38 @@ type config struct {
}
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 {
err := mapstructure.Decode(raw, &b.config)
err := decoder.Decode(raw)
if err != nil {
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 {
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)
}
errs := make([]error, 0)
if b.config.HTTPPortMin > b.config.HTTPPortMax {
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) {
var b Builder
config := testConfig()
......
......@@ -12,6 +12,7 @@ import (
"net/url"
"os"
"path/filepath"
"sort"
"strings"
"text/template"
"time"
......@@ -63,13 +64,38 @@ type config struct {
}
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 {
err := mapstructure.Decode(raw, &b.config)
err := decoder.Decode(raw)
if err != nil {
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 == "" {
b.config.DiskName = "disk"
}
......@@ -122,10 +148,6 @@ func (b *Builder) Prepare(raws ...interface{}) error {
b.config.ToolsUploadPath = "{{ .Flavor }}.iso"
}
// Accumulate any errors
var err error
errs := make([]error, 0)
if b.config.HTTPPortMin > b.config.HTTPPortMax {
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) {
var b Builder
config := testConfig()
......
......@@ -6,6 +6,8 @@ import (
"github.com/mitchellh/mapstructure"
"github.com/mitchellh/packer/packer"
"os"
"sort"
"strings"
)
type config struct {
......@@ -21,13 +23,37 @@ type Provisioner struct {
}
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 {
if err := mapstructure.Decode(raw, &p.config); err != nil {
err := decoder.Decode(raw)
if err != nil {
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 {
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) {
var p Provisioner
config := testConfig()
......
......@@ -14,6 +14,7 @@ import (
"io/ioutil"
"log"
"os"
"sort"
"strings"
"text/template"
)
......@@ -58,12 +59,38 @@ type ExecuteCommandTemplate struct {
}
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 {
if err := mapstructure.Decode(raw, &p.config); err != nil {
err := decoder.Decode(raw)
if err != nil {
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 == "" {
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)
}
errs := make([]error, 0)
if p.config.Script != "" && len(p.config.Scripts) > 0 {
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) {
config := testConfig()
delete(config, "inline")
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment