diff --git a/pkg/dns/record.go b/pkg/dns/record.go index 2b98905..7629a59 100644 --- a/pkg/dns/record.go +++ b/pkg/dns/record.go @@ -38,6 +38,47 @@ func SortAddrRecords(s []AddrRecord) []AddrRecord { return s } +// SortRecords sorts a slice of [libdns.Record], by Name, Type and Value +func SortRecords(s []libdns.Record) []libdns.Record { + sort.Slice(s, func(i, j int) bool { + return lessRecord(s[i], s[j]) + }) + return s +} + +func lessRecord(a, b libdns.Record) bool { + switch { + case a.Name < b.Name: + return true + case a.Name > b.Name: + return false + } + + switch { + case a.Type < b.Type: + return true + case a.Type > b.Type: + return false + case a.Type == "A", a.Type == "AAAA": + // IP Addresses + var aa, ba netip.Addr + + switch { + case aa.UnmarshalText([]byte(a.Value)) != nil: + // bad address on a + return true + case ba.UnmarshalText([]byte(b.Value)) != nil: + // bad address on b + return false + default: + return aa.Less(ba) + } + default: + // text + return a.Value < b.Value + } +} + // SortRegions sorts regions. first by length those 3-character // or shorter, and then by length. It's mostly aimed at // supporting ISO-3166 order diff --git a/pkg/dns/show.go b/pkg/dns/show.go index c29a3f0..e106f06 100644 --- a/pkg/dns/show.go +++ b/pkg/dns/show.go @@ -21,6 +21,8 @@ func (mgr *Manager) Show(ctx context.Context, names ...string) error { return core.Wrap(err, "GetRecords") } + SortRecords(recs) + for _, rr := range recs { _ = fmtRecord(&buf, rr) _, _ = buf.WriteRune('\n')