EXISTING: laba A 1.2.3.4 [0] laba MX 10 laba [1] labc CNAME laba [2] labe A 10.10.10.15 [3] labe A 10.10.10.16 [4] labe A 10.10.10.17 [5] labe A 10.10.10.18 [6] labg NS 10.10.10.15 [7] labg NS 10.10.10.16 [8] labg NS 10.10.10.17 [9] labg NS 10.10.10.18 [10] labh CNAME labd [11] DESIRED: laba A 1.2.3.4 [0'] laba A 1.2.3.5 [1'] laba MX 20 labb [2'] labe A 10.10.10.95 [3'] labe A 10.10.10.96 [4'] labe A 10.10.10.97 [5'] labe A 10.10.10.98 [6'] labf TXT "foo" [7'] labg NS 10.10.10.10 [8'] labg NS 10.10.10.15 [9'] labg NS 10.10.10.16 [10'] labg NS 10.10.10.97 [11'] labh A 1.2.3.4 [12'] ByRRSet: [] laba:A CHANGE NewSet: { [0], [1'] } (ByRecords needs: Old [0] ) [] laba:MX CHANGE NewSet: { [2'] } (ByLabel needs: Old: [2]) [] labc:CNAME DELETE Old: { [2 ] } [] labe:A CHANGE NewSet: { [3'], [4'], [5'], [6'] } [] labf:TXT CHANGE NewSet: { [7'] } [] labg:NS CHANGE NewSet: { [7] [8] [8'] [11'] } [] labh:CNAME DELETE Old { [11] } [] labh:A CREATE NewSet: { [12'] } ByRecord: CREATE [1'] CHANGE [1] [2'] DELETE [2] CHANGE [3] [3'] CHANGE [4] [4'] CHANGE [5] [5'] CHANGE [6] [6'] CREATE [7'] CREATE [8'] CHANGE [10] [11'] DELETE [11] CREATE [12'] ByLabel: (take ByRRSet gather all CHANGES) laba CHANGE NewSet: { [0'], [1'], [2'] } labc DELETE Old: { [2] } labe CHANGE New: { [3'], [4'], [5'], [6'] } labf CREATE New: { [7'] } labg CHANGE NewSet: { [7] [8] [8'] [11'] } labh DELETE Old { [11] } labh CREATE NewSet: { [12'] } By Record: rewrite as triples: FQDN+TYPE, TARGET, RC byRecord: group-by key=FQDN+TYPE, use targets to make add/change/delete for each record. byRSet: group-by key=FQDN+TYPE, use targets to make add/change/delete for each record. for each key: if both have this key: IF targets are the same, skip. Else generate CHANGE for KEY: New = Recs from desired. Msgs = The msgs from targetdiff(e.Recs, d.Recs) byLabel: group-by key=FQDN, use type+targets to make add/change/delete for each record. rewrite as triples: FQDN {, TYPE, TARGET, RC type CompareConfig struct { existing, desired models.Records ldata: []LabelConfig } type ByLabelConfig struct { label string tdata: []ByRTypeConfig } type ByRTypeConfig struct { rtype string existing: []TargetConfig desired: []TargetConfig existingRecs: []*models.RecordConfig desiredRecs: []*models.RecordConfig } type TargetConfig struct { compareable string rec *model.RecordConfig } func highest[S ~[]T, T any](s S) int { return len(s) - 1 } populate CompareConfig. for rec := range desired { label = FILL rtype = FILL comp = FILL cc.labelMap[label] = &rc cc.keyMap[key] = &rc if not seen label: append cc.ldata ByLabelConfig{} labelIdx = last(cc.ldata) if not seen key: append cc.ldata[labelIdx].tdata ByRTypeConfig{} rtIdx = last(cc.ldata[labelIdx].tdata) cc.ldata[labelIdx].label = label cc.ldata[labelIdx].tdata[rtIdx].rtype = rtype cc.ldata[labelIdx].tdata[rtIdx].existing[append].comparable = comp cc.ldata[labelIdx].tdata[rtIdx].existing[append].rec = &rc } ByRSet: func traverse(cc CompareConfig) { for label := range cc.data { for rtype := range label.data { Msgs := genmsgs(rtype.existing, rtype.desired) if no Msgs, continue if len(rtype.existing) = 0 { yield create(label, rtype, rtype.desiredRecs, Msgs) } else if len(rtype.desired) = 0 { yield delete(label, rtype, rtype.existingRecs, Msgs) } else { // equal yield change(label, rtype, rtype.desiredRecs, Msgs) } } } byLabel: func traverse(cc CompareConfig) { for label := range cc.data { initialize msgs, desiredRecords anyExisting = false for rtype := range label.data { accumulate Msgs := genmsgs(rtype.existing, rtype.desired) if Msgs (i.e. there were changes) { accumulate AllDesired := rtype.desiredRecs if len(rtype.existing) != 0 { anyExisting = true } } } if there are Msgs: if len(AllDesired) = 0 { yield delete(label) } else if countAllExisting == 0 { yield create(label, AllDesired) } else { yield change(label, AllDesired) } } } ByRecord: func traverse(cc CompareConfig) { for label := range cc.data { for rtype := range label.data { create, change, delete := difftargets(rtype.existing, rtype.desired) yield creates, changes, deletes } } } Byzone: func traverse(cc CompareConfig) { for label := range cc.data { for rtype := range label.data { Msgs := genmsgs(rtype.existing, rtype.desired) accumulate Msgs } } if len(accumMsgs) == 0 { return nil, FirstMsg } else { return desired, Msgs } }