From 64632fa6407c310467ec0581c813c2e1a011aed4 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Tue, 17 Jun 2025 19:33:45 +0700 Subject: [PATCH] cmd/cli: use resolvconffile lib for parsing --- cmd/cli/resolvconf.go | 24 +++--------------- cmd/cli/resolvconf_test.go | 46 ++++++++++++++++++++++++++++++++++ internal/resolvconffile/dns.go | 13 ++++++---- 3 files changed, 57 insertions(+), 26 deletions(-) create mode 100644 cmd/cli/resolvconf_test.go diff --git a/cmd/cli/resolvconf.go b/cmd/cli/resolvconf.go index 587841d..496bd9b 100644 --- a/cmd/cli/resolvconf.go +++ b/cmd/cli/resolvconf.go @@ -3,36 +3,18 @@ package cli import ( "net" "net/netip" - "os" "path/filepath" - "strings" "time" "github.com/fsnotify/fsnotify" + + "github.com/Control-D-Inc/ctrld/internal/resolvconffile" ) // parseResolvConfNameservers reads the resolv.conf file and returns the nameservers found. // Returns nil if no nameservers are found. func (p *prog) parseResolvConfNameservers(path string) ([]string, error) { - content, err := os.ReadFile(path) - if err != nil { - return nil, err - } - - // Parse the file for "nameserver" lines - var currentNS []string - lines := strings.Split(string(content), "\n") - for _, line := range lines { - trimmed := strings.TrimSpace(line) - if strings.HasPrefix(trimmed, "nameserver") { - parts := strings.Fields(trimmed) - if len(parts) >= 2 { - currentNS = append(currentNS, parts[1]) - } - } - } - - return currentNS, nil + return resolvconffile.NameserversFromFile(path) } // watchResolvConf watches any changes to /etc/resolv.conf file, diff --git a/cmd/cli/resolvconf_test.go b/cmd/cli/resolvconf_test.go new file mode 100644 index 0000000..9ee7e3b --- /dev/null +++ b/cmd/cli/resolvconf_test.go @@ -0,0 +1,46 @@ +//go:build unix + +package cli + +import ( + "os" + "slices" + "strings" + "testing" + + "github.com/Control-D-Inc/ctrld/internal/dns/resolvconffile" +) + +func oldParseResolvConfNameservers(path string) ([]string, error) { + content, err := os.ReadFile(path) + if err != nil { + return nil, err + } + + // Parse the file for "nameserver" lines + var currentNS []string + lines := strings.Split(string(content), "\n") + for _, line := range lines { + trimmed := strings.TrimSpace(line) + if strings.HasPrefix(trimmed, "nameserver") { + parts := strings.Fields(trimmed) + if len(parts) >= 2 { + currentNS = append(currentNS, parts[1]) + } + } + } + + return currentNS, nil +} + +func Test_prog_parseResolvConfNameservers(t *testing.T) { + oldNss, _ := oldParseResolvConfNameservers(resolvconffile.Path) + p := &prog{} + nss, _ := p.parseResolvConfNameservers(resolvconffile.Path) + slices.Sort(oldNss) + slices.Sort(nss) + if !slices.Equal(oldNss, nss) { + t.Errorf("result mismatched, old: %v, new: %v", oldNss, nss) + } + t.Logf("result: %v", nss) +} diff --git a/internal/resolvconffile/dns.go b/internal/resolvconffile/dns.go index 0d532eb..386e9a8 100644 --- a/internal/resolvconffile/dns.go +++ b/internal/resolvconffile/dns.go @@ -1,5 +1,3 @@ -//go:build !js && !windows - package resolvconffile import ( @@ -24,15 +22,20 @@ func NameServersWithPort() []string { } func NameServers() []string { - c, err := resolvconffile.ParseFile(resolvconfPath) + nss, _ := NameserversFromFile(resolvconfPath) + return nss +} + +func NameserversFromFile(path string) ([]string, error) { + c, err := resolvconffile.ParseFile(path) if err != nil { - return nil + return nil, err } ns := make([]string, 0, len(c.Nameservers)) for _, nameserver := range c.Nameservers { ns = append(ns, nameserver.String()) } - return ns + return ns, nil } // SearchDomains returns the current search domains config in /etc/resolv.conf file.