Skip to content

Commit

Permalink
kubelet: Read DNS Config options from file for Windows
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
claudiubelu committed Mar 21, 2023
1 parent c9ff286 commit c68bc27
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 93 deletions.
27 changes: 27 additions & 0 deletions pkg/kubelet/network/dns/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,33 @@ func parseResolvConf(reader io.Reader) (nameservers []string, searches []string,
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) {
dnsPolicy := pod.Spec.DNSPolicy
switch dnsPolicy {
Expand Down
34 changes: 2 additions & 32 deletions pkg/kubelet/network/dns/dns_other.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,35 +19,5 @@ limitations under the License.

package dns

import (
"fmt"
"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
}
// Read the DNS configuration from a resolv.conf file.
var getHostDNSConfig = getDNSConfig
31 changes: 0 additions & 31 deletions pkg/kubelet/network/dns/dns_other_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,39 +19,8 @@ limitations under the License.

package dns

import (
"fmt"
"os"
"testing"
)

var (
defaultResolvConf = "/etc/resolv.conf"
// configurer.getHostDNSConfig is faked on Windows, while it is not faked on Linux.
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 changes: 15 additions & 4 deletions pkg/kubelet/network/dns/dns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package dns
import (
"fmt"
"net"
"os"
"strconv"
"strings"
"testing"
Expand Down Expand Up @@ -536,6 +537,7 @@ func testGetPodDNS(t *testing.T) {
}

configurer = NewConfigurer(recorder, nodeRef, nil, testClusterDNS, testClusterDNSDomain, defaultResolvConf)
configurer.getHostDNSConfig = fakeGetHostDNSConfigCustom
for i, pod := range pods {
var err error
dnsConfig, err := configurer.GetPodDNS(pod)
Expand Down Expand Up @@ -600,11 +602,20 @@ func TestGetPodDNSCustom(t *testing.T) {
},
}

resolvConf, cleanup := getResolvConf(t)
defer cleanup()
resolvConfContent := []byte(fmt.Sprintf("nameserver %s\nsearch %s\n", testHostNameserver, testHostDomain))
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.getHostDNSConfig = fakeGetHostDNSConfigCustom
configurer := NewConfigurer(recorder, nodeRef, nil, []net.IP{netutils.ParseIPSloppy(testClusterNameserver)}, testClusterDNSDomain, tmpfile.Name())

testCases := []struct {
desc string
Expand Down
63 changes: 44 additions & 19 deletions pkg/kubelet/network/dns/dns_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package dns

import (
"fmt"
"os"
"strings"
"syscall"
"unsafe"
Expand Down Expand Up @@ -63,31 +64,55 @@ var (
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) {
if resolverConfig != "" && resolverConfig != hostResolvConf {
err := fmt.Errorf(`Unexpected resolver config value: "%s". Expected "" or "%s".`, resolverConfig, hostResolvConf)
if resolverConfig == "" {
// 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)
}

var (
hostDNS, hostSearch []string
err error
)
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.")
return nil, err
}

// If we get here, the resolverConfig == hostResolvConf and that is not actually a file, so
// it means to use the host settings.
// Get host DNS settings
if resolverConfig == hostResolvConf {
hostDNS, err = getDNSServerList()
if err != nil {
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.")
return nil, err
}
hostSearch, err = getDNSSuffixList()
if err != nil {
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.")
return nil, err
}
hostDNS, err := getDNSServerList()
if err != nil {
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.")
return nil, err
}
hostSearch, err := getDNSSuffixList()
if err != nil {
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.")
return nil, err
}
return &runtimeapi.DNSConfig{
Servers: hostDNS,
Expand Down
7 changes: 0 additions & 7 deletions pkg/kubelet/network/dns/dns_windows_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ limitations under the License.
package dns

import (
"testing"

runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
)

Expand All @@ -35,8 +33,3 @@ func fakeGetHostDNSConfigCustom(resolverConfig string) (*runtimeapi.DNSConfig, e
Searches: []string{testHostDomain},
}, 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() {}
}

0 comments on commit c68bc27

Please sign in to comment.