diff --git a/fix/fixer.go b/fix/fixer.go index bf2ccf25b..8ed4ac746 100644 --- a/fix/fixer.go +++ b/fix/fixer.go @@ -41,6 +41,7 @@ func init() { "hyperv-vmxc-typo": new(FixerHypervVmxcTypo), "hyperv-cpu-and-ram": new(FizerHypervCPUandRAM), "vmware-compaction": new(FixerVMwareCompaction), + "clean-image-name": new(FixerCleanImageName), } FixerOrder = []string{ @@ -63,5 +64,6 @@ func init() { "powershell-escapes", "vmware-compaction", "hyperv-cpu-and-ram", + "clean-image-name", } } diff --git a/fix/fixer_clean_image_name.go b/fix/fixer_clean_image_name.go new file mode 100644 index 000000000..cbb85f894 --- /dev/null +++ b/fix/fixer_clean_image_name.go @@ -0,0 +1,62 @@ +package fix + +import ( + "fmt" + "regexp" + + "github.com/mitchellh/mapstructure" +) + +// FixerCleanImageName is a Fixer that replaces the "clean_(image|ami)_name" template +// calls with "clean_resource_name" +type FixerCleanImageName struct{} + +func (FixerCleanImageName) Fix(input map[string]interface{}) (map[string]interface{}, error) { + // Our template type we'll use for this fixer only + type template struct { + Builders []map[string]interface{} + } + + // Decode the input into our structure, if we can + var tpl template + if err := mapstructure.Decode(input, &tpl); err != nil { + return nil, err + } + + re := regexp.MustCompile(`clean_(image|ami)_name`) + + // Go through each builder and replace CreateTime if we can + for _, builder := range tpl.Builders { + for key, value := range builder { + switch v := value.(type) { + case string: + changed := re.ReplaceAllString(v, "clean_resource_name") + builder[key] = changed + case map[string]string: + for k := range v { + v[k] = re.ReplaceAllString(v[k], "clean_resource_name") + } + builder[key] = v + case map[string]interface{}: + for k := range v { + if s, ok := v[k].(string); ok { + v[k] = re.ReplaceAllString(s, "clean_resource_name") + } + } + builder[key] = v + default: + if key == "image_labels" { + + panic(fmt.Sprintf("value: %#v", value)) + } + } + } + } + + input["builders"] = tpl.Builders + return input, nil +} + +func (FixerCleanImageName) Synopsis() string { + return `Replaces /clean_(image|ami)_name/ in builder configs with "clean_resource_name"` +} diff --git a/fix/fixer_clean_image_name_test.go b/fix/fixer_clean_image_name_test.go new file mode 100644 index 000000000..21799ba5f --- /dev/null +++ b/fix/fixer_clean_image_name_test.go @@ -0,0 +1,52 @@ +package fix + +import ( + "testing" + + "github.com/google/go-cmp/cmp" +) + +func TestFixerCleanImageName_Impl(t *testing.T) { + var raw interface{} + raw = new(FixerCleanImageName) + if _, ok := raw.(Fixer); !ok { + t.Fatalf("must be a Fixer") + } +} + +func TestFixerCleanImageName_Fix(t *testing.T) { + var f FixerCleanImageName + + input := map[string]interface{}{ + "builders": []interface{}{ + map[string]interface{}{ + "type": "foo", + "ami_name": "heyo clean_image_name", + "image_labels": map[string]interface{}{ + "name": "test-packer-{{packer_version | clean_image_name}}", + }, + }, + }, + } + + expected := map[string]interface{}{ + "builders": []map[string]interface{}{ + { + "type": "foo", + "ami_name": "heyo clean_resource_name", + "image_labels": map[string]interface{}{ + "name": "test-packer-{{packer_version | clean_resource_name}}", + }, + }, + }, + } + + output, err := f.Fix(input) + if err != nil { + t.Fatalf("err: %s", err) + } + + if diff := cmp.Diff(expected, output); diff != "" { + t.Fatalf("unexpected output: %s", diff) + } +}