From 1da5ebd28151ef3faf74faf60a07943fbd767ef4 Mon Sep 17 00:00:00 2001 From: Roman Dodin Date: Tue, 24 Oct 2023 23:58:49 +0200 Subject: [PATCH] Dns fetch with slices instead of map for predictability of the order (#1672) * use slices to collect dns servers * added rn --- docs/rn/0.47.md | 2 +- utils/resolve.go | 26 +++++++++++++------------- utils/resolve_test.go | 16 +++------------- 3 files changed, 17 insertions(+), 27 deletions(-) diff --git a/docs/rn/0.47.md b/docs/rn/0.47.md index b253122cc..f98a7c322 100644 --- a/docs/rn/0.47.md +++ b/docs/rn/0.47.md @@ -39,4 +39,4 @@ Containerlab now [generates an SSH config](../manual/inventory.md#ssh-config) fi ### 0.47.1 -* Do not extract more than 3 DNS servers from the host's resolv.conf #1671 +* Do not extract more than 3 DNS servers from the host's resolv.conf #1671, #1672 diff --git a/utils/resolve.go b/utils/resolve.go index 68515b616..f25e632b2 100644 --- a/utils/resolve.go +++ b/utils/resolve.go @@ -7,13 +7,17 @@ import ( "strings" log "github.com/sirupsen/logrus" + "golang.org/x/exp/slices" ) // ExtractDNSServersFromResolvConf extracts IP addresses // of the DNS servers from the resolv.conf-formatted files passed in filenames list. // Returns a list of IP addresses of the DNS servers. func ExtractDNSServersFromResolvConf(filesys fs.FS, filenames []string) ([]string, error) { - DNSServersMap := map[string]struct{}{} + // list of DNS servers up to 10 elements + // since realistically there should be no more than 3 + // DNS servers, we leave some room for duplicates + DNSServers := make([]string, 0, 10) for _, filename := range filenames { readFile, err := filesys.Open(filename) @@ -39,27 +43,23 @@ func ExtractDNSServersFromResolvConf(filesys fs.FS, filenames []string) ([]strin continue } - DNSServersMap[ip.String()] = struct{}{} + DNSServers = append(DNSServers, ip.String()) } } readFile.Close() } - if len(DNSServersMap) == 0 { + if len(DNSServers) == 0 { return nil, nil } - DNSServers := make([]string, 0, len(DNSServersMap)) - var count int - for k := range DNSServersMap { - if count == 3 { - // keep only the first three DNS servers - // since C DNS resolver can't handle more - break - } - DNSServers = append(DNSServers, k) - count++ + // remove duplicates + slices.Sort(DNSServers) + DNSServers = slices.Compact(DNSServers) + + if len(DNSServers) > 3 { + DNSServers = DNSServers[:3] } return DNSServers, nil diff --git a/utils/resolve_test.go b/utils/resolve_test.go index d641fd40c..0625ab9fb 100644 --- a/utils/resolve_test.go +++ b/utils/resolve_test.go @@ -2,12 +2,10 @@ package utils import ( "io/fs" - "strings" "testing" "testing/fstest" "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" ) func TestExtractDNSServersFromResolvConf(t *testing.T) { @@ -132,6 +130,7 @@ search . "etc/someother/resolv.conf": &fstest.MapFile{ Data: []byte( ` +nameserver 2.2.2.2 nameserver 8.8.8.8 options edns0 trust-ad search . @@ -141,7 +140,7 @@ search . }, filenames: []string{"etc/resolv.conf", "etc/someother/resolv.conf"}, }, - want: []string{"1.1.1.1", "8.8.8.8"}, + want: []string{"1.1.1.1", "2.2.2.2", "8.8.8.8"}, wantErr: false, }, { @@ -163,16 +162,7 @@ search . return } - if diff := cmp.Diff(got, tt.want, cmpopts.SortSlices(func(s1, s2 string) bool { - switch strings.Compare(s1, s2) { - case -1: - return false - case 0: - return true - } - return true - }, - )); diff != "" { + if diff := cmp.Diff(got, tt.want); diff != "" { t.Errorf(diff) } })