From bd150201a91f3e1121bc728996157eb5e4518b51 Mon Sep 17 00:00:00 2001 From: Chris Eason Date: Sun, 16 Dec 2018 17:03:35 -0500 Subject: [PATCH 1/2] Add ability to resolve service FQDNs from host during 'minikube tunnel' (MacOS only for now) --- pkg/minikube/tunnel/cluster_inspector.go | 12 ++++-- pkg/minikube/tunnel/cluster_inspector_test.go | 7 +++- pkg/minikube/tunnel/route_darwin.go | 37 +++++++++++++++++++ pkg/minikube/tunnel/route_test.go | 7 +++- pkg/minikube/tunnel/types.go | 6 ++- 5 files changed, 60 insertions(+), 9 deletions(-) diff --git a/pkg/minikube/tunnel/cluster_inspector.go b/pkg/minikube/tunnel/cluster_inspector.go index 57c8dcee7566..4906ef573294 100644 --- a/pkg/minikube/tunnel/cluster_inspector.go +++ b/pkg/minikube/tunnel/cluster_inspector.go @@ -26,6 +26,7 @@ import ( "github.com/pkg/errors" "k8s.io/minikube/pkg/minikube/cluster" "k8s.io/minikube/pkg/minikube/config" + "k8s.io/minikube/pkg/util" ) type clusterInspector struct { @@ -93,9 +94,14 @@ func getRoute(host *host.Host, clusterConfig config.Config) (*Route, error) { if ip == nil { return nil, fmt.Errorf("invalid IP for host %s", hostDriverIP) } - + dnsIp, err := util.GetDNSIP(ipNet.String()) + if err != nil { + return nil, err + } return &Route{ - Gateway: ip, - DestCIDR: ipNet, + Gateway: ip, + DestCIDR: ipNet, + ClusterDomain: clusterConfig.KubernetesConfig.DNSDomain, + ClusterDNSIP: dnsIp, }, nil } diff --git a/pkg/minikube/tunnel/cluster_inspector_test.go b/pkg/minikube/tunnel/cluster_inspector_test.go index 12d429a330be..06c7e4818a04 100644 --- a/pkg/minikube/tunnel/cluster_inspector_test.go +++ b/pkg/minikube/tunnel/cluster_inspector_test.go @@ -17,6 +17,7 @@ limitations under the License. package tunnel import ( + "k8s.io/minikube/pkg/util" "testing" "net" @@ -78,10 +79,12 @@ func TestMinikubeCheckReturnsHostInformation(t *testing.T) { ip := net.ParseIP("1.2.3.4") _, ipNet, _ := net.ParseCIDR("96.0.0.0/12") + dnsIp, _ := util.GetDNSIP(ipNet.String()) expectedRoute := &Route{ - Gateway: ip, - DestCIDR: ipNet, + Gateway: ip, + DestCIDR: ipNet, + ClusterDNSIP: dnsIp, } if s != Running { diff --git a/pkg/minikube/tunnel/route_darwin.go b/pkg/minikube/tunnel/route_darwin.go index fdf7fcbffee6..9873b7b0a949 100644 --- a/pkg/minikube/tunnel/route_darwin.go +++ b/pkg/minikube/tunnel/route_darwin.go @@ -18,7 +18,9 @@ package tunnel import ( "fmt" + "io/ioutil" "net" + "os" "os/exec" "regexp" "strings" @@ -34,6 +36,9 @@ func (router *osRouter) EnsureRouteIsAdded(route *Route) error { if exists { return nil } + if err := writeResolverFile(route); err != nil { + return fmt.Errorf("could not write /etc/resolver/{cluster_domain} file: %s", err) + } serviceCIDR := route.DestCIDR.String() gatewayIP := route.Gateway.String() @@ -162,5 +167,37 @@ func (router *osRouter) Cleanup(route *Route) error { if !re.MatchString(message) { return fmt.Errorf("error deleting route: %s, %d", message, len(strings.Split(message, "\n"))) } + // idempotent removal of cluster domain dns + resolverFile := fmt.Sprintf("/etc/resolver/%s", route.ClusterDomain) + command = exec.Command("sudo", "rm", "-f", resolverFile) + if err := command.Run(); err != nil { + return fmt.Errorf("could not remove %s: %s", resolverFile, err) + } + return nil +} + +func writeResolverFile(route *Route) error { + resolverFile := "/etc/resolver/" + route.ClusterDomain + content := fmt.Sprintf("nameserver %s\nsearch_order 1\n", route.ClusterDNSIP) + // write resolver content into tmpFile, then copy it to /etc/resolver/clusterDomain + tmpFile, err := ioutil.TempFile("", "minikube-tunnel-resolver-") + if err != nil { + return err + } + defer os.Remove(tmpFile.Name()) + if _, err = tmpFile.WriteString(content); err != nil { + return err + } + if err = tmpFile.Close(); err != nil { + return err + } + command := exec.Command("sudo", "mkdir", "-p", "/etc/resolver") + if err := command.Run(); err != nil { + return err + } + command = exec.Command("sudo", "cp", "-f", tmpFile.Name(), resolverFile) + if err := command.Run(); err != nil { + return err + } return nil } diff --git a/pkg/minikube/tunnel/route_test.go b/pkg/minikube/tunnel/route_test.go index 2d8ee660f46b..7841512b9b3a 100644 --- a/pkg/minikube/tunnel/route_test.go +++ b/pkg/minikube/tunnel/route_test.go @@ -17,6 +17,7 @@ limitations under the License. package tunnel import ( + "k8s.io/minikube/pkg/util" "net" "reflect" "testing" @@ -130,10 +131,12 @@ got func unsafeParseRoute(gatewayIP string, destCIDR string) *Route { ip := net.ParseIP(gatewayIP) _, ipNet, _ := net.ParseCIDR(destCIDR) + dnsIp, _ := util.GetDNSIP(ipNet.String()) expectedRoute := &Route{ - Gateway: ip, - DestCIDR: ipNet, + Gateway: ip, + DestCIDR: ipNet, + ClusterDNSIP: dnsIp, } return expectedRoute } diff --git a/pkg/minikube/tunnel/types.go b/pkg/minikube/tunnel/types.go index a8540782e8f3..d1134af3bea7 100644 --- a/pkg/minikube/tunnel/types.go +++ b/pkg/minikube/tunnel/types.go @@ -58,8 +58,10 @@ func (t *Status) String() string { } type Route struct { - Gateway net.IP - DestCIDR *net.IPNet + Gateway net.IP + DestCIDR *net.IPNet + ClusterDomain string + ClusterDNSIP net.IP } func (r *Route) String() string { From 335da39434f51474652866b57f1375d0157b62b4 Mon Sep 17 00:00:00 2001 From: Chris Eason Date: Wed, 2 Jan 2019 11:53:58 -0500 Subject: [PATCH 2/2] Test for DNS resolution on Mac --- pkg/minikube/tunnel/route_darwin_test.go | 35 +++++++++++++++++++----- 1 file changed, 28 insertions(+), 7 deletions(-) diff --git a/pkg/minikube/tunnel/route_darwin_test.go b/pkg/minikube/tunnel/route_darwin_test.go index 3f75d3d157b2..5d6c421b444c 100644 --- a/pkg/minikube/tunnel/route_darwin_test.go +++ b/pkg/minikube/tunnel/route_darwin_test.go @@ -35,9 +35,14 @@ func TestDarwinRouteFailsOnConflictIntegrationTest(t *testing.T) { IP: net.IPv4(10, 96, 0, 0), Mask: net.IPv4Mask(255, 240, 0, 0), }, + ClusterDomain: "cluster.local", + ClusterDNSIP: net.IPv4(10, 96, 0, 10), } + conflictingCfg := *cfg + conflictingCfg.Gateway = net.IPv4(127, 0, 0, 2) - addRoute(t, "10.96.0.0/12", "127.0.0.2") + addRoute(t, &conflictingCfg) + defer cleanRoute(t, &conflictingCfg) err := (&osRouter{}).EnsureRouteIsAdded(cfg) if err == nil { t.Errorf("add should have error, but it is nil") @@ -51,9 +56,11 @@ func TestDarwinRouteIdempotentIntegrationTest(t *testing.T) { IP: net.IPv4(10, 96, 0, 0), Mask: net.IPv4Mask(255, 240, 0, 0), }, + ClusterDomain: "cluster.local", + ClusterDNSIP: net.IPv4(10, 96, 0, 10), } - cleanRoute(t, "10.96.0.0/12") + cleanRoute(t, cfg) err := (&osRouter{}).EnsureRouteIsAdded(cfg) if err != nil { t.Errorf("add error: %s", err) @@ -64,7 +71,7 @@ func TestDarwinRouteIdempotentIntegrationTest(t *testing.T) { t.Errorf("add error: %s", err) } - cleanRoute(t, "10.96.0.0/12") + cleanRoute(t, cfg) } func TestDarwinRouteCleanupIdempontentIntegrationTest(t *testing.T) { @@ -75,10 +82,12 @@ func TestDarwinRouteCleanupIdempontentIntegrationTest(t *testing.T) { IP: net.IPv4(10, 96, 0, 0), Mask: net.IPv4Mask(255, 240, 0, 0), }, + ClusterDomain: "cluster.local", + ClusterDNSIP: net.IPv4(10, 96, 0, 10), } - cleanRoute(t, "10.96.0.0/12") - addRoute(t, "10.96.0.0/12", "192.168.1.1") + cleanRoute(t, cfg) + addRoute(t, cfg) err := (&osRouter{}).Cleanup(cfg) if err != nil { t.Errorf("cleanup failed with %s", err) @@ -89,20 +98,32 @@ func TestDarwinRouteCleanupIdempontentIntegrationTest(t *testing.T) { } } -func addRoute(t *testing.T, cidr string, gw string) { +func addRoute(t *testing.T, r *Route) { + cidr := r.DestCIDR.String() + gw := r.Gateway.String() command := exec.Command("sudo", "route", "-n", "add", cidr, gw) _, err := command.CombinedOutput() if err != nil { t.Logf("add route error (should be ok): %s", err) } + err = writeResolverFile(r) + if err != nil { + t.Logf("add route DNS resolver error (should be ok): %s", err) + } } -func cleanRoute(t *testing.T, cidr string) { +func cleanRoute(t *testing.T, r *Route) { + cidr := r.DestCIDR.String() command := exec.Command("sudo", "route", "-n", "delete", cidr) _, err := command.CombinedOutput() if err != nil { t.Logf("cleanup error (should be ok): %s", err) } + command = exec.Command("sudo", "rm", "-f", fmt.Sprintf("/etc/resolver/%s", r.ClusterDomain)) + _, err = command.CombinedOutput() + if err != nil { + t.Logf("cleanup DNS resolver error (should be ok): %s", err) + } } func TestCIDRPadding(t *testing.T) {