From ded13a8b10b4cbe53a75c9eb968e099fc79a524b Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Sat, 23 May 2015 14:48:07 -0700 Subject: [PATCH] packer: Core, and template validate --- packer/core.go | 77 +++++++++++++++++++ packer/core_test.go | 60 +++++++++++++++ packer/packer_test.go | 11 +++ .../test-fixtures/validate-dup-builder.json | 10 +++ .../test-fixtures/validate-req-variable.json | 9 +++ 5 files changed, 167 insertions(+) create mode 100644 packer/core.go create mode 100644 packer/core_test.go create mode 100644 packer/packer_test.go create mode 100644 packer/test-fixtures/validate-dup-builder.json create mode 100644 packer/test-fixtures/validate-req-variable.json diff --git a/packer/core.go b/packer/core.go new file mode 100644 index 000000000..de6fe4169 --- /dev/null +++ b/packer/core.go @@ -0,0 +1,77 @@ +package packer + +import ( + "fmt" + "os" + + "github.com/hashicorp/go-multierror" + "github.com/mitchellh/packer/template" +) + +// Core is the main executor of Packer. If Packer is being used as a +// library, this is the struct you'll want to instantiate to get anything done. +type Core struct { + cache Cache + components ComponentFinder + ui Ui + template *template.Template + variables map[string]string +} + +// CoreConfig is the structure for initializing a new Core. Once a CoreConfig +// is used to initialize a Core, it shouldn't be re-used or modified again. +type CoreConfig struct { + Cache Cache + Components ComponentFinder + Ui Ui + Template *template.Template + Variables map[string]string +} + +// NewCore creates a new Core. +func NewCore(c *CoreConfig) (*Core, error) { + if c.Ui == nil { + c.Ui = &BasicUi{ + Reader: os.Stdin, + Writer: os.Stdout, + ErrorWriter: os.Stdout, + } + } + + return &Core{ + cache: c.Cache, + components: c.Components, + ui: c.Ui, + template: c.Template, + variables: c.Variables, + }, nil +} + +// Validate does a full validation of the template. +// +// This will automatically call template.Validate() in addition to doing +// richer semantic checks around variables and so on. +func (c *Core) Validate() error { + // First validate the template in general, we can't do anything else + // unless the template itself is valid. + if err := c.template.Validate(); err != nil { + return err + } + + // Validate variables are set + var err error + for n, v := range c.template.Variables { + if v.Required { + if _, ok := c.variables[n]; !ok { + err = multierror.Append(err, fmt.Errorf( + "required variable not set: %s", n)) + } + } + } + + // TODO: validate all builders exist + // TODO: ^^ provisioner + // TODO: ^^ post-processor + + return err +} diff --git a/packer/core_test.go b/packer/core_test.go new file mode 100644 index 000000000..dc7880302 --- /dev/null +++ b/packer/core_test.go @@ -0,0 +1,60 @@ +package packer + +import ( + "os" + "testing" + + "github.com/mitchellh/packer/template" +) + +func TestCoreValidate(t *testing.T) { + cases := []struct { + File string + Vars map[string]string + Err bool + }{ + { + "validate-dup-builder.json", + nil, + true, + }, + + // Required variable not set + { + "validate-req-variable.json", + nil, + true, + }, + + { + "validate-req-variable.json", + map[string]string{"foo": "bar"}, + false, + }, + } + + for _, tc := range cases { + f, err := os.Open(fixtureDir(tc.File)) + if err != nil { + t.Fatalf("err: %s", err) + } + + tpl, err := template.Parse(f) + f.Close() + if err != nil { + t.Fatalf("err: %s\n\n%s", tc.File, err) + } + + core, err := NewCore(&CoreConfig{ + Template: tpl, + Variables: tc.Vars, + }) + if err != nil { + t.Fatalf("err: %s\n\n%s", tc.File, err) + } + + if err := core.Validate(); (err != nil) != tc.Err { + t.Fatalf("err: %s\n\n%s", tc.File, err) + } + } +} diff --git a/packer/packer_test.go b/packer/packer_test.go new file mode 100644 index 000000000..ec536e2c3 --- /dev/null +++ b/packer/packer_test.go @@ -0,0 +1,11 @@ +package packer + +import ( + "path/filepath" +) + +const FixtureDir = "./test-fixtures" + +func fixtureDir(n string) string { + return filepath.Join(FixtureDir, n) +} diff --git a/packer/test-fixtures/validate-dup-builder.json b/packer/test-fixtures/validate-dup-builder.json new file mode 100644 index 000000000..21d206d35 --- /dev/null +++ b/packer/test-fixtures/validate-dup-builder.json @@ -0,0 +1,10 @@ +{ + "builders": [ + {"type": "foo"} + ], + + "provisioners": [{ + "type": "foo", + "only": ["bar"] + }] +} diff --git a/packer/test-fixtures/validate-req-variable.json b/packer/test-fixtures/validate-req-variable.json new file mode 100644 index 000000000..796d0b669 --- /dev/null +++ b/packer/test-fixtures/validate-req-variable.json @@ -0,0 +1,9 @@ +{ + "variables": { + "foo": null + }, + + "builders": [{ + "type": "foo" + }] +}