k8s.io/kubernetes@v1.29.3/test/e2e/windows/dns.go (about)

     1  /*
     2  Copyright 2019 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package windows
    18  
    19  import (
    20  	"context"
    21  	"strings"
    22  
    23  	v1 "k8s.io/api/core/v1"
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  	"k8s.io/kubernetes/test/e2e/feature"
    26  	"k8s.io/kubernetes/test/e2e/framework"
    27  	e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
    28  	e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
    29  	admissionapi "k8s.io/pod-security-admission/api"
    30  
    31  	"github.com/onsi/ginkgo/v2"
    32  	"github.com/onsi/gomega"
    33  )
    34  
    35  var _ = sigDescribe(feature.Windows, "DNS", skipUnlessWindows(func() {
    36  
    37  	ginkgo.BeforeEach(func() {
    38  		e2eskipper.SkipUnlessNodeOSDistroIs("windows")
    39  	})
    40  
    41  	f := framework.NewDefaultFramework("dns")
    42  	f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged
    43  	ginkgo.It("should support configurable pod DNS servers", func(ctx context.Context) {
    44  
    45  		ginkgo.By("Getting the IP address of the internal Kubernetes service")
    46  
    47  		svc, err := f.ClientSet.CoreV1().Services("kube-system").Get(ctx, "kube-dns", metav1.GetOptions{})
    48  		framework.ExpectNoError(err)
    49  
    50  		ginkgo.By("Preparing a test DNS service with injected DNS names...")
    51  		// the default service IP will vary from cluster to cluster, but will always be present and is a good DNS test target
    52  		testInjectedIP := svc.Spec.ClusterIP
    53  		testSearchPath := "default.svc.cluster.local"
    54  
    55  		ginkgo.By("Creating a windows pod with dnsPolicy=None and customized dnsConfig...")
    56  		testPod := e2epod.NewAgnhostPod(f.Namespace.Name, "e2e-dns-utils", nil, nil, nil)
    57  		testPod.Spec.DNSPolicy = v1.DNSNone
    58  		testPod.Spec.DNSConfig = &v1.PodDNSConfig{
    59  			Nameservers: []string{testInjectedIP, "1.1.1.1"},
    60  			Searches:    []string{testSearchPath},
    61  		}
    62  		testPod.Spec.NodeSelector = map[string]string{
    63  			"kubernetes.io/os": "windows",
    64  		}
    65  		testPod, err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(ctx, testPod, metav1.CreateOptions{})
    66  		framework.ExpectNoError(err)
    67  
    68  		ginkgo.By("confirming that the pod has a windows label")
    69  		gomega.Expect(testPod.Spec.NodeSelector).To(gomega.HaveKeyWithValue("kubernetes.io/os", "windows"), "pod.spec.nodeSelector")
    70  
    71  		framework.Logf("Created pod %v", testPod)
    72  		defer func() {
    73  			framework.Logf("Deleting pod %s...", testPod.Name)
    74  			if err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Delete(ctx, testPod.Name, *metav1.NewDeleteOptions(0)); err != nil {
    75  				framework.Failf("Failed to delete pod %s: %v", testPod.Name, err)
    76  			}
    77  		}()
    78  		framework.ExpectNoError(e2epod.WaitForPodNameRunningInNamespace(ctx, f.ClientSet, testPod.Name, f.Namespace.Name), "failed to wait for pod %s to be running", testPod.Name)
    79  
    80  		// This isn't the best 'test' but it is a great diagnostic, see later test for the 'real' test.
    81  		ginkgo.By("Calling ipconfig to get debugging info for this pod's DNS and confirm that a dns server 1.1.1.1 can be injected, along with ")
    82  		cmd := []string{"ipconfig", "/all"}
    83  		stdout, _, err := e2epod.ExecWithOptions(f, e2epod.ExecOptions{
    84  			Command:       cmd,
    85  			Namespace:     f.Namespace.Name,
    86  			PodName:       testPod.Name,
    87  			ContainerName: "agnhost-container",
    88  			CaptureStdout: true,
    89  			CaptureStderr: true,
    90  		})
    91  		framework.ExpectNoError(err)
    92  		framework.Logf("ipconfig /all:\n%s", stdout)
    93  
    94  		if !strings.Contains(stdout, "1.1.1.1") {
    95  			framework.Failf("One of the custom DNS options 1.1.1.1, not found in ipconfig /all")
    96  		}
    97  
    98  		// We've now verified that the DNS stuff is injected...  now lets make sure that curl'ing 'wrong' endpoints fails, i.e.
    99  		// a negative control, to run before we run our final test...
   100  
   101  		ginkgo.By("Verifying that curl queries FAIL for wrong URLs")
   102  
   103  		// the below tests use curl because nslookup doesn't seem to use ndots properly
   104  		// ideally we'd use the powershell native ResolveDns but, that is not a part of agnhost images (as of k8s 1.20)
   105  		// TODO @jayunit100 add ResolveHost to agn images
   106  
   107  		cmd = []string{"curl.exe", "-k", "https://kubernetezzzzzzzz:443"}
   108  		stdout, _, err = e2epod.ExecWithOptions(f, e2epod.ExecOptions{
   109  			Command:       cmd,
   110  			Namespace:     f.Namespace.Name,
   111  			PodName:       testPod.Name,
   112  			ContainerName: "agnhost-container",
   113  			CaptureStdout: true,
   114  			CaptureStderr: true,
   115  		})
   116  		if err == nil {
   117  			framework.Logf("Warning: Somehow the curl command succeeded... The output was \n %v", stdout)
   118  			framework.Failf("Expected a bogus URL query to fail - something is wrong with this test harness, cannot proceed.")
   119  		}
   120  
   121  		ginkgo.By("Verifying that injected dns records for 'kubernetes' resolve to the valid ip address")
   122  		cmd = []string{"curl.exe", "-k", "https://kubernetes:443"}
   123  		stdout, _, err = e2epod.ExecWithOptions(f, e2epod.ExecOptions{
   124  			Command:       cmd,
   125  			Namespace:     f.Namespace.Name,
   126  			PodName:       testPod.Name,
   127  			ContainerName: "agnhost-container",
   128  			CaptureStdout: true,
   129  			CaptureStderr: true,
   130  		})
   131  		framework.Logf("Result of curling the kubernetes service... (Failure ok, only testing for the sake of DNS resolution) %v ... error = %v", stdout, err)
   132  
   133  		// curl returns an error if the host isn't resolved, otherwise, it will return a passing result.
   134  		if err != nil {
   135  			framework.ExpectNoError(err)
   136  		}
   137  
   138  		// TODO: Add more test cases for other DNSPolicies.
   139  	})
   140  }))