diff --git a/command/fix/fixer.go b/command/fix/fixer.go index f82cc9393..fd4d947da 100644 --- a/command/fix/fixer.go +++ b/command/fix/fixer.go @@ -22,6 +22,7 @@ func init() { Fixers = map[string]Fixer{ "iso-md5": new(FixerISOMD5), "createtime": new(FixerCreateTime), + "pp-vagrant-override": new(FixerVagrantPPOverride), "virtualbox-gaattach": new(FixerVirtualBoxGAAttach), } @@ -29,5 +30,6 @@ func init() { "iso-md5", "createtime", "virtualbox-gaattach", + "pp-vagrant-override", } } diff --git a/command/fix/fixer_pp_vagrant_override.go b/command/fix/fixer_pp_vagrant_override.go new file mode 100644 index 000000000..36aadfa46 --- /dev/null +++ b/command/fix/fixer_pp_vagrant_override.go @@ -0,0 +1,75 @@ +package fix + +import ( + "github.com/mitchellh/mapstructure" +) + +// FixerVagrantPPOvveride is a Fixer that replaces the provider-specific +// overrides for the Vagrant post-processor with the new style introduced +// as part of Packer 0.5.0. +type FixerVagrantPPOverride struct{} + +func (FixerVagrantPPOverride) Fix(input map[string]interface{}) (map[string]interface{}, error) { + // Our template type we'll use for this fixer only + type template struct { + PostProcessors []interface{} `mapstructure:"post-processors"` + } + + // Decode the input into our structure, if we can + var tpl template + if err := mapstructure.Decode(input, &tpl); err != nil { + return nil, err + } + + // Go through each post-processor and get out all the complex configs + pps := make([]map[string]interface{}, 0, len(tpl.PostProcessors)) + for _, rawPP := range tpl.PostProcessors { + switch pp := rawPP.(type) { + case string: + case map[string]interface{}: + pps = append(pps, pp) + case []interface{}: + for _, innerRawPP := range pp { + if innerPP, ok := innerRawPP.(map[string]interface{}); ok { + pps = append(pps, innerPP) + } + } + } + } + + // Go through each post-processor and make the fix if necessary + possible := []string{"aws", "digitalocean", "virtualbox", "vmware"} + for _, pp := range pps { + typeRaw, ok := pp["type"] + if !ok { + continue + } + + if typeName, ok := typeRaw.(string); !ok { + continue + } else if typeName != "vagrant" { + continue + } + + overrides := make(map[string]interface{}) + for _, name := range possible { + if _, ok := pp[name]; !ok { + continue + } + + overrides[name] = pp[name] + delete(pp, name) + } + + if len(overrides) > 0 { + pp["override"] = overrides + } + } + + input["post-processors"] = tpl.PostProcessors + return input, nil +} + +func (FixerVagrantPPOverride) Synopsis() string { + return `Fixes provider-specific overrides for Vagrant post-processor` +} diff --git a/command/fix/fixer_pp_vagrant_override_test.go b/command/fix/fixer_pp_vagrant_override_test.go new file mode 100644 index 000000000..ae344911e --- /dev/null +++ b/command/fix/fixer_pp_vagrant_override_test.go @@ -0,0 +1,79 @@ +package fix + +import ( + "reflect" + "testing" +) + +func TestFixerVagrantPPOverride_Impl(t *testing.T) { + var _ Fixer = new(FixerVagrantPPOverride) +} + +func TestFixerVagrantPPOverride_Fix(t *testing.T) { + var f FixerVagrantPPOverride + + input := map[string]interface{}{ + "post-processors": []interface{}{ + "foo", + + map[string]interface{}{ + "type": "vagrant", + "aws": map[string]interface{}{ + "foo": "bar", + }, + }, + + map[string]interface{}{ + "type": "vsphere", + }, + + []interface{}{ + map[string]interface{}{ + "type": "vagrant", + "vmware": map[string]interface{}{ + "foo": "bar", + }, + }, + }, + }, + } + + expected := map[string]interface{}{ + "post-processors": []interface{}{ + "foo", + + map[string]interface{}{ + "type": "vagrant", + "override": map[string]interface{}{ + "aws": map[string]interface{}{ + "foo": "bar", + }, + }, + }, + + map[string]interface{}{ + "type": "vsphere", + }, + + []interface{}{ + map[string]interface{}{ + "type": "vagrant", + "override": map[string]interface{}{ + "vmware": map[string]interface{}{ + "foo": "bar", + }, + }, + }, + }, + }, + } + + output, err := f.Fix(input) + if err != nil { + t.Fatalf("err: %s", err) + } + + if !reflect.DeepEqual(output, expected) { + t.Fatalf("unexpected: %#v\nexpected: %#v\n", output, expected) + } +}