diff --git a/common/command/build_flags.go b/common/command/build_flags.go deleted file mode 100644 index d08ca58b8..000000000 --- a/common/command/build_flags.go +++ /dev/null @@ -1,39 +0,0 @@ -package command - -import ( - "flag" - "fmt" - "strings" -) - -// BuildOptionFlags sets the proper command line flags needed for -// build options. -func BuildOptionFlags(fs *flag.FlagSet, f *BuildOptions) { - fs.Var((*SliceValue)(&f.Except), "except", "build all builds except these") - fs.Var((*SliceValue)(&f.Only), "only", "only build the given builds by name") - fs.Var((*userVarValue)(&f.UserVars), "var", "specify a user variable") - fs.Var((*AppendSliceValue)(&f.UserVarFiles), "var-file", "file with user variables") -} - -// userVarValue is a flag.Value that parses out user variables in -// the form of 'key=value' and sets it on this map. -type userVarValue map[string]string - -func (v *userVarValue) String() string { - return "" -} - -func (v *userVarValue) Set(raw string) error { - idx := strings.Index(raw, "=") - if idx == -1 { - return fmt.Errorf("No '=' value in arg: %s", raw) - } - - if *v == nil { - *v = make(map[string]string) - } - - key, value := raw[0:idx], raw[idx+1:] - (*v)[key] = value - return nil -} diff --git a/common/command/build_flags_test.go b/common/command/build_flags_test.go deleted file mode 100644 index 5d39eb946..000000000 --- a/common/command/build_flags_test.go +++ /dev/null @@ -1,104 +0,0 @@ -package command - -import ( - "flag" - "reflect" - "testing" -) - -func TestBuildOptionFlags(t *testing.T) { - opts := new(BuildOptions) - fs := flag.NewFlagSet("test", flag.ContinueOnError) - BuildOptionFlags(fs, opts) - - args := []string{ - "-except=foo,bar,baz", - "-only=a,b", - "-var=foo=bar", - "-var", "bar=baz", - "-var=foo=bang", - "-var-file=foo", - "-var-file=bar", - } - - err := fs.Parse(args) - if err != nil { - t.Fatalf("err: %s", err) - } - - expected := []string{"foo", "bar", "baz"} - if !reflect.DeepEqual(opts.Except, expected) { - t.Fatalf("bad: %#v", opts.Except) - } - - expected = []string{"a", "b"} - if !reflect.DeepEqual(opts.Only, expected) { - t.Fatalf("bad: %#v", opts.Only) - } - - if len(opts.UserVars) != 2 { - t.Fatalf("bad: %#v", opts.UserVars) - } - - if opts.UserVars["foo"] != "bang" { - t.Fatalf("bad: %#v", opts.UserVars) - } - - if opts.UserVars["bar"] != "baz" { - t.Fatalf("bad: %#v", opts.UserVars) - } - - expected = []string{"foo", "bar"} - if !reflect.DeepEqual(opts.UserVarFiles, expected) { - t.Fatalf("bad: %#v", opts.UserVarFiles) - } -} - -func TestUserVarValue_implements(t *testing.T) { - var raw interface{} - raw = new(userVarValue) - if _, ok := raw.(flag.Value); !ok { - t.Fatalf("userVarValue should be a Value") - } -} - -func TestUserVarValueSet(t *testing.T) { - sv := new(userVarValue) - err := sv.Set("key=value") - if err != nil { - t.Fatalf("err: %s", err) - } - - vars := map[string]string(*sv) - if vars["key"] != "value" { - t.Fatalf("Bad: %#v", vars) - } - - // Empty value - err = sv.Set("key=") - if err != nil { - t.Fatalf("err: %s", err) - } - - vars = map[string]string(*sv) - if vars["key"] != "" { - t.Fatalf("Bad: %#v", vars) - } - - // Equal in value - err = sv.Set("key=foo=bar") - if err != nil { - t.Fatalf("err: %s", err) - } - - vars = map[string]string(*sv) - if vars["key"] != "foo=bar" { - t.Fatalf("Bad: %#v", vars) - } - - // No equal - err = sv.Set("key") - if err == nil { - t.Fatal("should have error") - } -} diff --git a/common/command/flag_slice_value.go b/common/command/flag_slice_value.go deleted file mode 100644 index 8989dedad..000000000 --- a/common/command/flag_slice_value.go +++ /dev/null @@ -1,34 +0,0 @@ -package command - -import "strings" - -// AppendSliceValue implements the flag.Value interface and allows multiple -// calls to the same variable to append a list. -type AppendSliceValue []string - -func (s *AppendSliceValue) String() string { - return strings.Join(*s, ",") -} - -func (s *AppendSliceValue) Set(value string) error { - if *s == nil { - *s = make([]string, 0, 1) - } - - *s = append(*s, value) - return nil -} - -// SliceValue implements the flag.Value interface and allows a list of -// strings to be given on the command line and properly parsed into a slice -// of strings internally. -type SliceValue []string - -func (s *SliceValue) String() string { - return strings.Join(*s, ",") -} - -func (s *SliceValue) Set(value string) error { - *s = strings.Split(value, ",") - return nil -} diff --git a/common/command/flag_slice_value_test.go b/common/command/flag_slice_value_test.go deleted file mode 100644 index ca80c9d9f..000000000 --- a/common/command/flag_slice_value_test.go +++ /dev/null @@ -1,54 +0,0 @@ -package command - -import ( - "flag" - "reflect" - "testing" -) - -func TestAppendSliceValue_implements(t *testing.T) { - var raw interface{} - raw = new(AppendSliceValue) - if _, ok := raw.(flag.Value); !ok { - t.Fatalf("AppendSliceValue should be a Value") - } -} - -func TestAppendSliceValueSet(t *testing.T) { - sv := new(AppendSliceValue) - err := sv.Set("foo") - if err != nil { - t.Fatalf("err: %s", err) - } - - err = sv.Set("bar") - if err != nil { - t.Fatalf("err: %s", err) - } - - expected := []string{"foo", "bar"} - if !reflect.DeepEqual([]string(*sv), expected) { - t.Fatalf("Bad: %#v", sv) - } -} - -func TestSliceValue_implements(t *testing.T) { - var raw interface{} - raw = new(SliceValue) - if _, ok := raw.(flag.Value); !ok { - t.Fatalf("SliceValue should be a Value") - } -} - -func TestSliceValueSet(t *testing.T) { - sv := new(SliceValue) - err := sv.Set("foo,bar,baz") - if err != nil { - t.Fatalf("err: %s", err) - } - - expected := []string{"foo", "bar", "baz"} - if !reflect.DeepEqual([]string(*sv), expected) { - t.Fatalf("Bad: %#v", sv) - } -} diff --git a/common/command/template.go b/common/command/template.go deleted file mode 100644 index 27a42f901..000000000 --- a/common/command/template.go +++ /dev/null @@ -1,162 +0,0 @@ -package command - -import ( - "errors" - "fmt" - jsonutil "github.com/mitchellh/packer/common/json" - "github.com/mitchellh/packer/packer" - "io/ioutil" - "log" - "os" -) - -// BuildOptions is a set of options related to builds that can be set -// from the command line. -type BuildOptions struct { - UserVarFiles []string - UserVars map[string]string - Except []string - Only []string -} - -// Validate validates the options -func (f *BuildOptions) Validate() error { - if len(f.Except) > 0 && len(f.Only) > 0 { - return errors.New("Only one of '-except' or '-only' may be specified.") - } - - if len(f.UserVarFiles) > 0 { - for _, path := range f.UserVarFiles { - if _, err := os.Stat(path); err != nil { - return fmt.Errorf("Cannot access: %s", path) - } - } - } - - return nil -} - -// AllUserVars returns the user variables, compiled from both the -// file paths and the vars on the command line. -func (f *BuildOptions) AllUserVars() (map[string]string, error) { - all := make(map[string]string) - - // Copy in the variables from the files - for _, path := range f.UserVarFiles { - fileVars, err := readFileVars(path) - if err != nil { - return nil, err - } - - for k, v := range fileVars { - all[k] = v - } - } - - // Copy in the command-line vars - for k, v := range f.UserVars { - all[k] = v - } - - return all, nil -} - -// Builds returns the builds out of the given template that pass the -// configured options. -func (f *BuildOptions) Builds(t *packer.Template, cf *packer.ComponentFinder) ([]packer.Build, error) { - buildNames := t.BuildNames() - - // Process the name - tpl, _, err := t.NewConfigTemplate() - if err != nil { - return nil, err - } - - checks := make(map[string][]string) - checks["except"] = f.Except - checks["only"] = f.Only - for t, ns := range checks { - for _, n := range ns { - found := false - for _, actual := range buildNames { - var processed string - processed, err = tpl.Process(actual, nil) - if err != nil { - return nil, err - } - if actual == n || processed == n { - found = true - break - } - } - - if !found { - return nil, fmt.Errorf( - "Unknown build in '%s' flag: %s", t, n) - } - } - } - - builds := make([]packer.Build, 0, len(buildNames)) - for _, buildName := range buildNames { - var processedBuildName string - processedBuildName, err = tpl.Process(buildName, nil) - if err != nil { - return nil, err - } - if len(f.Except) > 0 { - found := false - for _, except := range f.Except { - if buildName == except || processedBuildName == except { - found = true - break - } - } - - if found { - log.Printf("Skipping build '%s' because specified by -except.", processedBuildName) - continue - } - } - - if len(f.Only) > 0 { - found := false - for _, only := range f.Only { - if buildName == only || processedBuildName == only { - found = true - break - } - } - - if !found { - log.Printf("Skipping build '%s' because not specified by -only.", processedBuildName) - continue - } - } - - log.Printf("Creating build: %s", processedBuildName) - build, err := t.Build(buildName, cf) - if err != nil { - return nil, fmt.Errorf("Failed to create build '%s': \n\n%s", buildName, err) - } - - builds = append(builds, build) - } - - return builds, nil -} - -func readFileVars(path string) (map[string]string, error) { - bytes, err := ioutil.ReadFile(path) - if err != nil { - return nil, err - } - - vars := make(map[string]string) - err = jsonutil.Unmarshal(bytes, &vars) - if err != nil { - return nil, err - } - - return vars, nil -} diff --git a/common/command/template_test.go b/common/command/template_test.go deleted file mode 100644 index 419ee7012..000000000 --- a/common/command/template_test.go +++ /dev/null @@ -1,228 +0,0 @@ -package command - -import ( - "github.com/mitchellh/packer/packer" - "testing" -) - -func testTemplate() (*packer.Template, *packer.ComponentFinder) { - tplData := `{ - "variables": { - "foo": null - }, - - "builders": [ - { - "type": "foo" - }, - { - "name": "{{user \"foo\"}}", - "type": "bar" - } - ] - } - ` - - tpl, err := packer.ParseTemplate([]byte(tplData), map[string]string{"foo": "bar"}) - if err != nil { - panic(err) - } - - cf := &packer.ComponentFinder{ - Builder: func(string) (packer.Builder, error) { return new(packer.MockBuilder), nil }, - } - - return tpl, cf -} - -func TestBuildOptionsBuilds(t *testing.T) { - opts := new(BuildOptions) - bs, err := opts.Builds(testTemplate()) - if err != nil { - t.Fatalf("err: %s", err) - } - - if len(bs) != 2 { - t.Fatalf("bad: %d", len(bs)) - } -} - -func TestBuildOptionsBuilds_except(t *testing.T) { - opts := new(BuildOptions) - opts.Except = []string{"foo"} - - bs, err := opts.Builds(testTemplate()) - if err != nil { - t.Fatalf("err: %s", err) - } - - if len(bs) != 1 { - t.Fatalf("bad: %d", len(bs)) - } - - if bs[0].Name() != "bar" { - t.Fatalf("bad: %s", bs[0].Name()) - } -} - -//Test to make sure the build name pattern matches -func TestBuildOptionsBuilds_exceptConfigTemplateRaw(t *testing.T) { - opts := new(BuildOptions) - opts.Except = []string{"{{user \"foo\"}}"} - - bs, err := opts.Builds(testTemplate()) - if err != nil { - t.Fatalf("err: %s", err) - } - - if len(bs) != 1 { - t.Fatalf("bad: %d", len(bs)) - } - - if bs[0].Name() != "foo" { - t.Fatalf("bad: %s", bs[0].Name()) - } -} - -//Test to make sure the processed build name matches -func TestBuildOptionsBuilds_exceptConfigTemplateProcessed(t *testing.T) { - opts := new(BuildOptions) - opts.Except = []string{"bar"} - - bs, err := opts.Builds(testTemplate()) - if err != nil { - t.Fatalf("err: %s", err) - } - - if len(bs) != 1 { - t.Fatalf("bad: %d", len(bs)) - } - - if bs[0].Name() != "foo" { - t.Fatalf("bad: %s", bs[0].Name()) - } -} - -func TestBuildOptionsBuilds_only(t *testing.T) { - opts := new(BuildOptions) - opts.Only = []string{"foo"} - - bs, err := opts.Builds(testTemplate()) - if err != nil { - t.Fatalf("err: %s", err) - } - - if len(bs) != 1 { - t.Fatalf("bad: %d", len(bs)) - } - - if bs[0].Name() != "foo" { - t.Fatalf("bad: %s", bs[0].Name()) - } -} - -//Test to make sure the build name pattern matches -func TestBuildOptionsBuilds_onlyConfigTemplateRaw(t *testing.T) { - opts := new(BuildOptions) - opts.Only = []string{"{{user \"foo\"}}"} - - bs, err := opts.Builds(testTemplate()) - if err != nil { - t.Fatalf("err: %s", err) - } - - if len(bs) != 1 { - t.Fatalf("bad: %d", len(bs)) - } - - if bs[0].Name() != "bar" { - t.Fatalf("bad: %s", bs[0].Name()) - } -} - -//Test to make sure the processed build name matches -func TestBuildOptionsBuilds_onlyConfigTemplateProcessed(t *testing.T) { - opts := new(BuildOptions) - opts.Only = []string{"bar"} - - bs, err := opts.Builds(testTemplate()) - if err != nil { - t.Fatalf("err: %s", err) - } - - if len(bs) != 1 { - t.Fatalf("bad: %d", len(bs)) - } - - if bs[0].Name() != "bar" { - t.Fatalf("bad: %s", bs[0].Name()) - } -} - -func TestBuildOptionsBuilds_exceptNonExistent(t *testing.T) { - opts := new(BuildOptions) - opts.Except = []string{"i-dont-exist"} - - _, err := opts.Builds(testTemplate()) - if err == nil { - t.Fatal("err should not be nil") - } -} - -func TestBuildOptionsBuilds_onlyNonExistent(t *testing.T) { - opts := new(BuildOptions) - opts.Only = []string{"i-dont-exist"} - - _, err := opts.Builds(testTemplate()) - if err == nil { - t.Fatal("err should not be nil") - } -} - -func TestBuildOptionsValidate(t *testing.T) { - bf := new(BuildOptions) - - err := bf.Validate() - if err != nil { - t.Fatalf("err: %s", err) - } - - // Both set - bf.Except = make([]string, 1) - bf.Only = make([]string, 1) - err = bf.Validate() - if err == nil { - t.Fatal("should error") - } - - // One set - bf.Except = make([]string, 1) - bf.Only = make([]string, 0) - err = bf.Validate() - if err != nil { - t.Fatalf("err: %s", err) - } - - bf.Except = make([]string, 0) - bf.Only = make([]string, 1) - err = bf.Validate() - if err != nil { - t.Fatalf("err: %s", err) - } -} - -func TestBuildOptionsValidate_userVarFiles(t *testing.T) { - bf := new(BuildOptions) - - err := bf.Validate() - if err != nil { - t.Fatalf("err: %s", err) - } - - // Non-existent file - bf.UserVarFiles = []string{"ireallyshouldntexistanywhere"} - err = bf.Validate() - if err == nil { - t.Fatal("should error") - } -}