From 7dac96f4744a19fd2a760987994a48c0e6025b78 Mon Sep 17 00:00:00 2001 From: Alejandro Mery Date: Tue, 24 Oct 2023 15:14:12 +0000 Subject: [PATCH 1/3] dns/show: refactor Record formatting Signed-off-by: Alejandro Mery --- pkg/dns/show.go | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/pkg/dns/show.go b/pkg/dns/show.go index 24cba56..c29a3f0 100644 --- a/pkg/dns/show.go +++ b/pkg/dns/show.go @@ -1,29 +1,53 @@ package dns import ( + "bytes" "context" "fmt" + "io" + "os" "time" "darvaza.org/core" + "github.com/libdns/libdns" ) // Show shows current DNS entries func (mgr *Manager) Show(ctx context.Context, names ...string) error { + var buf bytes.Buffer + recs, err := mgr.GetRecords(ctx, names...) if err != nil { return core.Wrap(err, "GetRecords") } for _, rr := range recs { - _, _ = fmt.Printf("%s\t%v\tIN\t%s\t%s\t; %s\n", - rr.Name, - int(rr.TTL/time.Second), - rr.Type, - rr.Value, - rr.ID) + _ = fmtRecord(&buf, rr) + _, _ = buf.WriteRune('\n') + } + _, _ = fmt.Fprintf(&buf, "; %v records\n", len(recs)) + + _, err = buf.WriteTo(os.Stdout) + return err +} + +func fmtRecord(w io.Writer, rr libdns.Record) error { + ttl := int(rr.TTL / time.Second) + if ttl < 1 { + ttl = 1 + } + + _, err := fmt.Fprintf(w, "%s\t%v\tIN\t%s\t%s", + rr.Name, + ttl, + rr.Type, + rr.Value) + + if err == nil { + if rr.ID != "" { + _, err = fmt.Fprintf(w, "\t; %s", rr.ID) + } } - _, _ = fmt.Printf("; %v records\n", len(recs)) - return nil + return err } From 356322bc94cde05139ecfff30ddc83dadab528f9 Mon Sep 17 00:00:00 2001 From: Alejandro Mery Date: Thu, 26 Oct 2023 18:34:42 +0000 Subject: [PATCH 2/3] dns/show: introduce writeRecords() helper to print a whole []libdns.Record Signed-off-by: Alejandro Mery --- pkg/dns/show.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/pkg/dns/show.go b/pkg/dns/show.go index c29a3f0..d133a2c 100644 --- a/pkg/dns/show.go +++ b/pkg/dns/show.go @@ -14,20 +14,24 @@ import ( // Show shows current DNS entries func (mgr *Manager) Show(ctx context.Context, names ...string) error { - var buf bytes.Buffer - recs, err := mgr.GetRecords(ctx, names...) if err != nil { return core.Wrap(err, "GetRecords") } + return writeRecords(recs, os.Stdout) +} + +func writeRecords(recs []libdns.Record, w io.Writer) error { + var buf bytes.Buffer + for _, rr := range recs { _ = fmtRecord(&buf, rr) _, _ = buf.WriteRune('\n') } _, _ = fmt.Fprintf(&buf, "; %v records\n", len(recs)) - _, err = buf.WriteTo(os.Stdout) + _, err := buf.WriteTo(w) return err } From 9da49f2d86c55bcc5315ee0616c31b363c1a9f91 Mon Sep 17 00:00:00 2001 From: Alejandro Mery Date: Tue, 24 Oct 2023 17:12:53 +0000 Subject: [PATCH 3/3] dns/show: sort records v2: change Name to lower case and Type to upper case before comparing Signed-off-by: Alejandro Mery --- pkg/dns/record.go | 48 +++++++++++++++++++++++++++++++++++++++++++++++ pkg/dns/show.go | 1 + 2 files changed, 49 insertions(+) diff --git a/pkg/dns/record.go b/pkg/dns/record.go index 2b98905..1b9fc51 100644 --- a/pkg/dns/record.go +++ b/pkg/dns/record.go @@ -6,6 +6,7 @@ import ( "io" "net/netip" "sort" + "strings" "time" "darvaza.org/core" @@ -38,6 +39,53 @@ 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 { + aName := strings.ToLower(a.Name) + bName := strings.ToLower(b.Name) + + switch { + case aName < bName: + return true + case aName > bName: + return false + } + + aType := strings.ToUpper(a.Type) + bType := strings.ToUpper(b.Type) + + switch { + case aType < bType: + return true + case aType > bType: + return false + case aType == "A", aType == "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 d133a2c..e6a7fbb 100644 --- a/pkg/dns/show.go +++ b/pkg/dns/show.go @@ -19,6 +19,7 @@ func (mgr *Manager) Show(ctx context.Context, names ...string) error { return core.Wrap(err, "GetRecords") } + SortRecords(recs) return writeRecords(recs, os.Stdout) }