Browse code

Merge pull request #44239 from thaJeztah/resolvconf_refactor_step2

libnetwork: simplify handling of reading resolv.conf

Tianon Gravi authored on 2022/12/23 06:18:47
Showing 4 changed files
... ...
@@ -531,8 +531,8 @@ func (n *network) getBridgeNamePrefix(s *subnet) string {
531 531
 func checkOverlap(nw *net.IPNet) error {
532 532
 	var nameservers []string
533 533
 
534
-	if rc, err := resolvconf.Get(); err == nil {
535
-		nameservers = resolvconf.GetNameserversAsCIDR(rc.Content)
534
+	if rc, err := os.ReadFile(resolvconf.Path()); err == nil {
535
+		nameservers = resolvconf.GetNameserversAsCIDR(rc)
536 536
 	}
537 537
 
538 538
 	if err := netutils.CheckNameserverOverlaps(nameservers, nw); err != nil {
... ...
@@ -6,8 +6,8 @@
6 6
 package netutils
7 7
 
8 8
 import (
9
-	"fmt"
10 9
 	"net"
10
+	"os"
11 11
 	"strings"
12 12
 
13 13
 	"github.com/docker/docker/libnetwork/ipamutils"
... ...
@@ -18,9 +18,7 @@ import (
18 18
 	"github.com/vishvananda/netlink"
19 19
 )
20 20
 
21
-var (
22
-	networkGetRoutesFct func(netlink.Link, int) ([]netlink.Route, error)
23
-)
21
+var networkGetRoutesFct func(netlink.Link, int) ([]netlink.Route, error)
24 22
 
25 23
 // CheckRouteOverlaps checks whether the passed network overlaps with any existing routes
26 24
 func CheckRouteOverlaps(toCheck *net.IPNet) error {
... ...
@@ -111,8 +109,8 @@ func FindAvailableNetwork(list []*net.IPNet) (*net.IPNet, error) {
111 111
 	// can't read /etc/resolv.conf. So instead we skip the append if resolvConf
112 112
 	// is nil. It either doesn't exist, or we can't read it for some reason.
113 113
 	var nameservers []string
114
-	if rc, err := resolvconf.Get(); err == nil {
115
-		nameservers = resolvconf.GetNameserversAsCIDR(rc.Content)
114
+	if rc, err := os.ReadFile(resolvconf.Path()); err == nil {
115
+		nameservers = resolvconf.GetNameserversAsCIDR(rc)
116 116
 	}
117 117
 	for _, nw := range list {
118 118
 		if err := CheckNameserverOverlaps(nameservers, nw); err == nil {
... ...
@@ -121,5 +119,5 @@ func FindAvailableNetwork(list []*net.IPNet) (*net.IPNet, error) {
121 121
 			}
122 122
 		}
123 123
 	}
124
-	return nil, fmt.Errorf("no available network")
124
+	return nil, errors.New("no available network")
125 125
 }
... ...
@@ -18,7 +18,7 @@ func ElectInterfaceAddresses(name string) ([]*net.IPNet, []*net.IPNet, error) {
18 18
 
19 19
 // FindAvailableNetwork returns a network from the passed list which does not
20 20
 // overlap with existing interfaces in the system
21
-
21
+//
22 22
 // TODO : Use appropriate windows APIs to identify non-overlapping subnets
23 23
 func FindAvailableNetwork(list []*net.IPNet) (*net.IPNet, error) {
24 24
 	return nil, nil
... ...
@@ -193,8 +193,6 @@ func isIPv4Loopback(ipAddress string) bool {
193 193
 }
194 194
 
195 195
 func (sb *sandbox) setupDNS() error {
196
-	var newRC *resolvconf.File
197
-
198 196
 	if sb.config.resolvConfPath == "" {
199 197
 		sb.config.resolvConfPath = defaultPrefix + "/" + sb.id + "/resolv.conf"
200 198
 	}
... ...
@@ -228,32 +226,30 @@ func (sb *sandbox) setupDNS() error {
228 228
 		// fallback if not specified
229 229
 		originResolvConfPath = resolvconf.Path()
230 230
 	}
231
-	currRC, err := resolvconf.GetSpecific(originResolvConfPath)
231
+	currRC, err := os.ReadFile(originResolvConfPath)
232 232
 	if err != nil {
233 233
 		if !os.IsNotExist(err) {
234 234
 			return err
235 235
 		}
236
-		// it's ok to continue if /etc/resolv.conf doesn't exist, default resolvers (Google's Public DNS)
237
-		// will be used
238
-		currRC = &resolvconf.File{}
239
-		logrus.Infof("/etc/resolv.conf does not exist")
236
+		// No /etc/resolv.conf found: we'll use the default resolvers (Google's Public DNS).
237
+		logrus.WithField("path", originResolvConfPath).Infof("no resolv.conf found, falling back to defaults")
240 238
 	}
241 239
 
240
+	var newRC *resolvconf.File
242 241
 	if len(sb.config.dnsList) > 0 || len(sb.config.dnsSearchList) > 0 || len(sb.config.dnsOptionsList) > 0 {
243 242
 		var (
244
-			err            error
245
-			dnsList        = resolvconf.GetNameservers(currRC.Content, resolvconf.IP)
246
-			dnsSearchList  = resolvconf.GetSearchDomains(currRC.Content)
247
-			dnsOptionsList = resolvconf.GetOptions(currRC.Content)
243
+			dnsList        = sb.config.dnsList
244
+			dnsSearchList  = sb.config.dnsSearchList
245
+			dnsOptionsList = sb.config.dnsOptionsList
248 246
 		)
249
-		if len(sb.config.dnsList) > 0 {
250
-			dnsList = sb.config.dnsList
247
+		if len(sb.config.dnsList) == 0 {
248
+			dnsList = resolvconf.GetNameservers(currRC, resolvconf.IP)
251 249
 		}
252
-		if len(sb.config.dnsSearchList) > 0 {
253
-			dnsSearchList = sb.config.dnsSearchList
250
+		if len(sb.config.dnsSearchList) == 0 {
251
+			dnsSearchList = resolvconf.GetSearchDomains(currRC)
254 252
 		}
255
-		if len(sb.config.dnsOptionsList) > 0 {
256
-			dnsOptionsList = sb.config.dnsOptionsList
253
+		if len(sb.config.dnsOptionsList) == 0 {
254
+			dnsOptionsList = resolvconf.GetOptions(currRC)
257 255
 		}
258 256
 		newRC, err = resolvconf.Build(sb.config.resolvConfPath, dnsList, dnsSearchList, dnsOptionsList)
259 257
 		if err != nil {
... ...
@@ -268,14 +264,16 @@ func (sb *sandbox) setupDNS() error {
268 268
 		// use the host resolver for queries. This is supported by the
269 269
 		// docker embedded DNS server. Hence save the external resolvers
270 270
 		// before filtering it out.
271
-		sb.setExternalResolvers(currRC.Content, resolvconf.IPv4, true)
271
+		sb.setExternalResolvers(currRC, resolvconf.IPv4, true)
272 272
 
273 273
 		// Replace any localhost/127.* (at this point we have no info about ipv6, pass it as true)
274
-		if newRC, err = resolvconf.FilterResolvDNS(currRC.Content, true); err != nil {
274
+		newRC, err = resolvconf.FilterResolvDNS(currRC, true)
275
+		if err != nil {
275 276
 			return err
276 277
 		}
277 278
 		// No contention on container resolv.conf file at sandbox creation
278
-		if err := os.WriteFile(sb.config.resolvConfPath, newRC.Content, filePerm); err != nil {
279
+		err = os.WriteFile(sb.config.resolvConfPath, newRC.Content, filePerm)
280
+		if err != nil {
279 281
 			return types.InternalErrorf("failed to write unhaltered resolv.conf file content when setting up dns for sandbox %s: %v", sb.ID(), err)
280 282
 		}
281 283
 	}
... ...
@@ -361,27 +359,16 @@ func (sb *sandbox) updateDNS(ipv6Enabled bool) error {
361 361
 // - Add only the embedded server's IP to container's resolv.conf
362 362
 // - If the embedded server needs any resolv.conf options add it to the current list
363 363
 func (sb *sandbox) rebuildDNS() error {
364
-	currRC, err := resolvconf.GetSpecific(sb.config.resolvConfPath)
364
+	currRC, err := os.ReadFile(sb.config.resolvConfPath)
365 365
 	if err != nil {
366 366
 		return err
367 367
 	}
368 368
 
369
-	if len(sb.extDNS) == 0 {
370
-		sb.setExternalResolvers(currRC.Content, resolvconf.IPv4, false)
371
-	}
372
-	var (
373
-		dnsList        = []string{sb.resolver.NameServer()}
374
-		dnsOptionsList = resolvconf.GetOptions(currRC.Content)
375
-		dnsSearchList  = resolvconf.GetSearchDomains(currRC.Content)
376
-	)
377
-
378
-	// external v6 DNS servers has to be listed in resolv.conf
379
-	dnsList = append(dnsList, resolvconf.GetNameservers(currRC.Content, resolvconf.IPv6)...)
380
-
381 369
 	// If the user config and embedded DNS server both have ndots option set,
382 370
 	// remember the user's config so that unqualified names not in the docker
383 371
 	// domain can be dropped.
384 372
 	resOptions := sb.resolver.ResolverOptions()
373
+	dnsOptionsList := resolvconf.GetOptions(currRC)
385 374
 
386 375
 dnsOpt:
387 376
 	for _, resOpt := range resOptions {
... ...
@@ -411,6 +398,15 @@ dnsOpt:
411 411
 		// Ref: https://linux.die.net/man/5/resolv.conf
412 412
 		dnsOptionsList = append(dnsOptionsList, resOptions...)
413 413
 	}
414
+	if len(sb.extDNS) == 0 {
415
+		sb.setExternalResolvers(currRC, resolvconf.IPv4, false)
416
+	}
417
+
418
+	var (
419
+		// external v6 DNS servers have to be listed in resolv.conf
420
+		dnsList       = append([]string{sb.resolver.NameServer()}, resolvconf.GetNameservers(currRC, resolvconf.IPv6)...)
421
+		dnsSearchList = resolvconf.GetSearchDomains(currRC)
422
+	)
414 423
 
415 424
 	_, err = resolvconf.Build(sb.config.resolvConfPath, dnsList, dnsSearchList, dnsOptionsList)
416 425
 	return err