diff --git a/models/record.go b/models/record.go index d7d324a4f..5016836ef 100644 --- a/models/record.go +++ b/models/record.go @@ -246,7 +246,15 @@ type RecordKey struct { // Key converts a RecordConfig into a RecordKey. func (rc *RecordConfig) Key() RecordKey { - return RecordKey{rc.Name, rc.Type} + t := rc.Type + if rc.R53Alias != nil { + if v, ok := rc.R53Alias["type"]; ok { + // Route53 aliases append their alias type, so that records for the same + // label with different alias types are considered separate. + t = fmt.Sprintf("%s_%s", t, v) + } + } + return RecordKey{rc.Name, t} } // Records is a list of *RecordConfig. diff --git a/models/record_test.go b/models/record_test.go new file mode 100644 index 000000000..4888563e1 --- /dev/null +++ b/models/record_test.go @@ -0,0 +1,33 @@ +package models + +import "testing" + +func TestKey(t *testing.T) { + var tests = []struct { + rc RecordConfig + expected RecordKey + }{ + { + RecordConfig{Type: "A", Name: "@"}, + RecordKey{Type: "A", Name: "@"}, + }, + { + RecordConfig{Type: "R53_ALIAS", Name: "@"}, + RecordKey{Type: "R53_ALIAS", Name: "@"}, + }, + { + RecordConfig{Type: "R53_ALIAS", Name: "@", R53Alias: map[string]string{"foo": "bar"}}, + RecordKey{Type: "R53_ALIAS", Name: "@"}, + }, + { + RecordConfig{Type: "R53_ALIAS", Name: "@", R53Alias: map[string]string{"type": "AAAA"}}, + RecordKey{Type: "R53_ALIAS_AAAA", Name: "@"}, + }, + } + for i, test := range tests { + actual := test.rc.Key() + if test.expected != actual { + t.Errorf("%d: Expected %s, got %s", i, test.expected, actual) + } + } +} diff --git a/providers/diff/diff.go b/providers/diff/diff.go index 093a6f8bf..56e24c06b 100644 --- a/providers/diff/diff.go +++ b/providers/diff/diff.go @@ -68,16 +68,14 @@ func (d *differ) IncrementalDiff(existing []*models.RecordConfig) (unchanged, cr desired := d.dc.Records // sort existing and desired by name - type key struct { - name, rType string - } - existingByNameAndType := map[key][]*models.RecordConfig{} - desiredByNameAndType := map[key][]*models.RecordConfig{} + + existingByNameAndType := map[models.RecordKey][]*models.RecordConfig{} + desiredByNameAndType := map[models.RecordKey][]*models.RecordConfig{} for _, e := range existing { if d.matchIgnored(e.GetLabel()) { log.Printf("Ignoring record %s %s due to IGNORE", e.GetLabel(), e.Type) } else { - k := key{e.GetLabelFQDN(), e.Type} + k := e.Key() existingByNameAndType[k] = append(existingByNameAndType[k], e) } } @@ -85,7 +83,7 @@ func (d *differ) IncrementalDiff(existing []*models.RecordConfig) (unchanged, cr if d.matchIgnored(dr.GetLabel()) { panic(fmt.Sprintf("Trying to update/add IGNOREd record: %s %s", dr.GetLabel(), dr.Type)) } else { - k := key{dr.GetLabelFQDN(), dr.Type} + k := dr.Key() desiredByNameAndType[k] = append(desiredByNameAndType[k], dr) } } @@ -93,7 +91,7 @@ func (d *differ) IncrementalDiff(existing []*models.RecordConfig) (unchanged, cr if d.dc.KeepUnknown { for k := range existingByNameAndType { if _, ok := desiredByNameAndType[k]; !ok { - log.Printf("Ignoring record set %s %s due to NO_PURGE", k.rType, k.name) + log.Printf("Ignoring record set %s %s due to NO_PURGE", k.Type, k.Name) delete(existingByNameAndType, k) } } diff --git a/providers/route53/route53Provider.go b/providers/route53/route53Provider.go index 208535937..879b9de7a 100644 --- a/providers/route53/route53Provider.go +++ b/providers/route53/route53Provider.go @@ -102,21 +102,6 @@ func (r *route53Provider) getZones() error { return nil } -// map key for grouping records -type key struct { - Name, Type string -} - -func getKey(r *models.RecordConfig) key { - var recordType = r.Type - - if r.R53Alias != nil { - recordType = fmt.Sprintf("%s_%s", recordType, r.R53Alias["type"]) - } - - return key{r.GetLabelFQDN(), recordType} -} - type errNoExist struct { domain string } @@ -175,29 +160,18 @@ func (r *route53Provider) GetDomainCorrections(dc *models.DomainConfig) ([]*mode // diff differ := diff.New(dc, getAliasMap) - _, create, delete, modify := differ.IncrementalDiff(existingRecords) - - namesToUpdate := map[key][]string{} - for _, c := range create { - namesToUpdate[getKey(c.Desired)] = append(namesToUpdate[getKey(c.Desired)], c.String()) - } - for _, d := range delete { - namesToUpdate[getKey(d.Existing)] = append(namesToUpdate[getKey(d.Existing)], d.String()) - } - for _, m := range modify { - namesToUpdate[getKey(m.Desired)] = append(namesToUpdate[getKey(m.Desired)], m.String()) - } + namesToUpdate := differ.ChangedGroups(existingRecords) if len(namesToUpdate) == 0 { return nil, nil } - updates := map[key][]*models.RecordConfig{} + updates := map[models.RecordKey][]*models.RecordConfig{} // for each name we need to update, collect relevant records from dc for k := range namesToUpdate { updates[k] = nil for _, rc := range dc.Records { - if getKey(rc) == k { + if rc.Key() == k { updates[k] = append(updates[k], rc) } }