mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	kubelet: Read DNS Config options from file for Windows
A previous commit added the capability to read the DNS configuration options from a Windows host, while removing the capability to read from a resolv.conf-like file. This commit addresses this issue: if the given ``--resolv-conf`` option is not set to ``Host``, it will consider it as a file, preserving the previous behavior.
This commit is contained in:
		@@ -281,6 +281,33 @@ func parseResolvConf(reader io.Reader) (nameservers []string, searches []string,
 | 
				
			|||||||
	return nameservers, searches, options, utilerrors.NewAggregate(allErrors)
 | 
						return nameservers, searches, options, utilerrors.NewAggregate(allErrors)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Reads a resolv.conf-like file and returns the DNS config options from it.
 | 
				
			||||||
 | 
					// Returns an empty DNSConfig if the given resolverConfigFile is an empty string.
 | 
				
			||||||
 | 
					func getDNSConfig(resolverConfigFile string) (*runtimeapi.DNSConfig, error) {
 | 
				
			||||||
 | 
						var hostDNS, hostSearch, hostOptions []string
 | 
				
			||||||
 | 
						// Get host DNS settings
 | 
				
			||||||
 | 
						if resolverConfigFile != "" {
 | 
				
			||||||
 | 
							f, err := os.Open(resolverConfigFile)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								klog.ErrorS(err, "Could not open resolv conf file.")
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							defer f.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							hostDNS, hostSearch, hostOptions, err = parseResolvConf(f)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								err := fmt.Errorf("Encountered error while parsing resolv conf file. Error: %w", err)
 | 
				
			||||||
 | 
								klog.ErrorS(err, "Could not parse resolv conf file.")
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return &runtimeapi.DNSConfig{
 | 
				
			||||||
 | 
							Servers:  hostDNS,
 | 
				
			||||||
 | 
							Searches: hostSearch,
 | 
				
			||||||
 | 
							Options:  hostOptions,
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getPodDNSType(pod *v1.Pod) (podDNSType, error) {
 | 
					func getPodDNSType(pod *v1.Pod) (podDNSType, error) {
 | 
				
			||||||
	dnsPolicy := pod.Spec.DNSPolicy
 | 
						dnsPolicy := pod.Spec.DNSPolicy
 | 
				
			||||||
	switch dnsPolicy {
 | 
						switch dnsPolicy {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,35 +19,5 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package dns
 | 
					package dns
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					// Read the DNS configuration from a resolv.conf file.
 | 
				
			||||||
	"fmt"
 | 
					var getHostDNSConfig = getDNSConfig
 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
 | 
					 | 
				
			||||||
	"k8s.io/klog/v2"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func getHostDNSConfig(resolverConfig string) (*runtimeapi.DNSConfig, error) {
 | 
					 | 
				
			||||||
	var hostDNS, hostSearch, hostOptions []string
 | 
					 | 
				
			||||||
	// Get host DNS settings
 | 
					 | 
				
			||||||
	if resolverConfig != "" {
 | 
					 | 
				
			||||||
		f, err := os.Open(resolverConfig)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			klog.ErrorS(err, "Could not open resolv conf file.")
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		defer f.Close()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		hostDNS, hostSearch, hostOptions, err = parseResolvConf(f)
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			err := fmt.Errorf("Encountered error while parsing resolv conf file. Error: %w", err)
 | 
					 | 
				
			||||||
			klog.ErrorS(err, "Could not parse resolv conf file.")
 | 
					 | 
				
			||||||
			return nil, err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return &runtimeapi.DNSConfig{
 | 
					 | 
				
			||||||
		Servers:  hostDNS,
 | 
					 | 
				
			||||||
		Searches: hostSearch,
 | 
					 | 
				
			||||||
		Options:  hostOptions,
 | 
					 | 
				
			||||||
	}, nil
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,39 +19,8 @@ limitations under the License.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
package dns
 | 
					package dns
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"os"
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
	defaultResolvConf = "/etc/resolv.conf"
 | 
						defaultResolvConf = "/etc/resolv.conf"
 | 
				
			||||||
	// configurer.getHostDNSConfig is faked on Windows, while it is not faked on Linux.
 | 
						// configurer.getHostDNSConfig is faked on Windows, while it is not faked on Linux.
 | 
				
			||||||
	fakeGetHostDNSConfigCustom = getHostDNSConfig
 | 
						fakeGetHostDNSConfigCustom = getHostDNSConfig
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					 | 
				
			||||||
// getResolvConf returns a temporary resolv.conf file containing the testHostNameserver nameserver and
 | 
					 | 
				
			||||||
// testHostDomain search field, and a cleanup function for the temporary file.
 | 
					 | 
				
			||||||
func getResolvConf(t *testing.T) (string, func()) {
 | 
					 | 
				
			||||||
	resolvConfContent := []byte(fmt.Sprintf("nameserver %s\nsearch %s\n", testHostNameserver, testHostDomain))
 | 
					 | 
				
			||||||
	tmpfile, err := os.CreateTemp("", "tmpResolvConf")
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		t.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cleanup := func() {
 | 
					 | 
				
			||||||
		os.Remove(tmpfile.Name())
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if _, err := tmpfile.Write(resolvConfContent); err != nil {
 | 
					 | 
				
			||||||
		cleanup()
 | 
					 | 
				
			||||||
		t.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err := tmpfile.Close(); err != nil {
 | 
					 | 
				
			||||||
		cleanup()
 | 
					 | 
				
			||||||
		t.Fatal(err)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return tmpfile.Name(), cleanup
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,6 +19,7 @@ package dns
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"net"
 | 
						"net"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
@@ -536,6 +537,7 @@ func testGetPodDNS(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	configurer = NewConfigurer(recorder, nodeRef, nil, testClusterDNS, testClusterDNSDomain, defaultResolvConf)
 | 
						configurer = NewConfigurer(recorder, nodeRef, nil, testClusterDNS, testClusterDNSDomain, defaultResolvConf)
 | 
				
			||||||
 | 
						configurer.getHostDNSConfig = fakeGetHostDNSConfigCustom
 | 
				
			||||||
	for i, pod := range pods {
 | 
						for i, pod := range pods {
 | 
				
			||||||
		var err error
 | 
							var err error
 | 
				
			||||||
		dnsConfig, err := configurer.GetPodDNS(pod)
 | 
							dnsConfig, err := configurer.GetPodDNS(pod)
 | 
				
			||||||
@@ -600,11 +602,20 @@ func TestGetPodDNSCustom(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	resolvConf, cleanup := getResolvConf(t)
 | 
						resolvConfContent := []byte(fmt.Sprintf("nameserver %s\nsearch %s\n", testHostNameserver, testHostDomain))
 | 
				
			||||||
	defer cleanup()
 | 
						tmpfile, err := os.CreateTemp("", "tmpResolvConf")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer os.Remove(tmpfile.Name())
 | 
				
			||||||
 | 
						if _, err := tmpfile.Write(resolvConfContent); err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := tmpfile.Close(); err != nil {
 | 
				
			||||||
 | 
							t.Fatal(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	configurer := NewConfigurer(recorder, nodeRef, nil, []net.IP{netutils.ParseIPSloppy(testClusterNameserver)}, testClusterDNSDomain, resolvConf)
 | 
						configurer := NewConfigurer(recorder, nodeRef, nil, []net.IP{netutils.ParseIPSloppy(testClusterNameserver)}, testClusterDNSDomain, tmpfile.Name())
 | 
				
			||||||
	configurer.getHostDNSConfig = fakeGetHostDNSConfigCustom
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	testCases := []struct {
 | 
						testCases := []struct {
 | 
				
			||||||
		desc              string
 | 
							desc              string
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -21,6 +21,7 @@ package dns
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"syscall"
 | 
						"syscall"
 | 
				
			||||||
	"unsafe"
 | 
						"unsafe"
 | 
				
			||||||
@@ -63,32 +64,56 @@ var (
 | 
				
			|||||||
	procGetNetworkParams = iphlpapidll.MustFindProc("GetNetworkParams")
 | 
						procGetNetworkParams = iphlpapidll.MustFindProc("GetNetworkParams")
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func fileExists(filename string) (bool, error) {
 | 
				
			||||||
 | 
						stat, err := os.Stat(filename)
 | 
				
			||||||
 | 
						if os.IsNotExist(err) {
 | 
				
			||||||
 | 
							return false, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return false, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return stat.Mode().IsRegular(), nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getHostDNSConfig(resolverConfig string) (*runtimeapi.DNSConfig, error) {
 | 
					func getHostDNSConfig(resolverConfig string) (*runtimeapi.DNSConfig, error) {
 | 
				
			||||||
	if resolverConfig != "" && resolverConfig != hostResolvConf {
 | 
						if resolverConfig == "" {
 | 
				
			||||||
		err := fmt.Errorf(`Unexpected resolver config value: "%s". Expected "" or "%s".`, resolverConfig, hostResolvConf)
 | 
							// This handles "" by returning defaults.
 | 
				
			||||||
 | 
							return getDNSConfig(resolverConfig)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						isFile, err := fileExists(resolverConfig)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							err = fmt.Errorf(`Unexpected error while getting os.Stat for "%s" resolver config. Error: %w`, resolverConfig, err)
 | 
				
			||||||
 | 
							klog.ErrorS(err, "Cannot get host DNS Configuration.")
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if isFile {
 | 
				
			||||||
 | 
							// Get the DNS config from a resolv.conf-like file.
 | 
				
			||||||
 | 
							return getDNSConfig(resolverConfig)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if resolverConfig != hostResolvConf {
 | 
				
			||||||
 | 
							err := fmt.Errorf(`Unexpected resolver config value: "%s". Expected "", "%s", or a path to an existing resolv.conf file.`, resolverConfig, hostResolvConf)
 | 
				
			||||||
		klog.ErrorS(err, "Cannot get host DNS Configuration.")
 | 
							klog.ErrorS(err, "Cannot get host DNS Configuration.")
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var (
 | 
						// If we get here, the resolverConfig == hostResolvConf and that is not actually a file, so
 | 
				
			||||||
		hostDNS, hostSearch []string
 | 
						// it means to use the host settings.
 | 
				
			||||||
		err                 error
 | 
					 | 
				
			||||||
	)
 | 
					 | 
				
			||||||
	// Get host DNS settings
 | 
						// Get host DNS settings
 | 
				
			||||||
	if resolverConfig == hostResolvConf {
 | 
						hostDNS, err := getDNSServerList()
 | 
				
			||||||
		hostDNS, err = getDNSServerList()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		err = fmt.Errorf("Could not get the host's DNS Server List. Error: %w", err)
 | 
							err = fmt.Errorf("Could not get the host's DNS Server List. Error: %w", err)
 | 
				
			||||||
		klog.ErrorS(err, "Encountered error while getting host's DNS Server List.")
 | 
							klog.ErrorS(err, "Encountered error while getting host's DNS Server List.")
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
		hostSearch, err = getDNSSuffixList()
 | 
						hostSearch, err := getDNSSuffixList()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		err = fmt.Errorf("Could not get the host's DNS Suffix List. Error: %w", err)
 | 
							err = fmt.Errorf("Could not get the host's DNS Suffix List. Error: %w", err)
 | 
				
			||||||
		klog.ErrorS(err, "Encountered error while getting host's DNS Suffix List.")
 | 
							klog.ErrorS(err, "Encountered error while getting host's DNS Suffix List.")
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return &runtimeapi.DNSConfig{
 | 
						return &runtimeapi.DNSConfig{
 | 
				
			||||||
		Servers:  hostDNS,
 | 
							Servers:  hostDNS,
 | 
				
			||||||
		Searches: hostSearch,
 | 
							Searches: hostSearch,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,8 +20,6 @@ limitations under the License.
 | 
				
			|||||||
package dns
 | 
					package dns
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
 | 
						runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -35,8 +33,3 @@ func fakeGetHostDNSConfigCustom(resolverConfig string) (*runtimeapi.DNSConfig, e
 | 
				
			|||||||
		Searches: []string{testHostDomain},
 | 
							Searches: []string{testHostDomain},
 | 
				
			||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
// getResolvConf returns the hostResolvConf string, which will be used to get the Host's DNS configuration.
 | 
					 | 
				
			||||||
func getResolvConf(t *testing.T) (string, func()) {
 | 
					 | 
				
			||||||
	return hostResolvConf, func() {}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user