diff --git a/test/e2e/network/network_policy.go b/test/e2e/network/network_policy.go index 423067322b1..08bc24e0f69 100644 --- a/test/e2e/network/network_policy.go +++ b/test/e2e/network/network_policy.go @@ -22,12 +22,12 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/kubernetes/pkg/apis/networking" "k8s.io/kubernetes/test/e2e/framework" + imageutils "k8s.io/kubernetes/test/utils/image" "fmt" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - imageutils "k8s.io/kubernetes/test/utils/image" ) /* @@ -36,290 +36,247 @@ are correctly enforced by a networking plugin. It accomplishes this by launching a simple netcat server, and two clients with different attributes. Each test case creates a network policy which should only allow connections from one of the clients. The test then asserts that the clients -failed or succesfully connected as expected. +failed or successfully connected as expected. */ var _ = SIGDescribe("NetworkPolicy", func() { + var service *v1.Service + var podServer *v1.Pod f := framework.NewDefaultFramework("network-policy") - It("should support a 'default-deny' policy [Feature:NetworkPolicy]", func() { - ns := f.Namespace + Context("NetworkPolicy between server and client", func() { + BeforeEach(func() { + By("Creating a simple server that serves on port 80 and 81.") + podServer, service = createServerPodAndService(f, f.Namespace, "server", []int{80, 81}) - By("Create a simple server.") - podServer, service := createServerPodAndService(f, ns, "server", []int{80}) - defer cleanupServerPodAndService(f, podServer, service) - framework.Logf("Waiting for Server to come up.") - err := framework.WaitForPodRunningInNamespace(f.ClientSet, podServer) - Expect(err).NotTo(HaveOccurred()) + By("Waiting for pod ready", func() { + err := f.WaitForPodReady(podServer.Name) + Expect(err).NotTo(HaveOccurred()) + }) - // Create a pod with name 'client-can-connect', which should be able to communicate with server. - By("Creating client which will be able to contact the server since no policies are present.") - testCanConnect(f, ns, "client-can-connect", service, 80) - - By("Creating a network policy denying all traffic.") - policy := &networking.NetworkPolicy{ - ObjectMeta: metav1.ObjectMeta{ - Name: "deny-all", - }, - Spec: networking.NetworkPolicySpec{ - PodSelector: metav1.LabelSelector{}, - Ingress: []networking.NetworkPolicyIngressRule{}, - }, - } - - policy, err = f.InternalClientset.Networking().NetworkPolicies(ns.Name).Create(policy) - Expect(err).NotTo(HaveOccurred()) - defer cleanupNetworkPolicy(f, policy) - - // Create a pod with name 'client-cannot-connect', which will attempt to comunicate with the server, - // but should not be able to now that isolation is on. - testCannotConnect(f, ns, "client-cannot-connect", service, 80) - }) - - It("should enforce policy based on PodSelector [Feature:NetworkPolicy]", func() { - ns := f.Namespace - - By("Creating a simple server.") - serverPod, service := createServerPodAndService(f, ns, "server", []int{80}) - defer cleanupServerPodAndService(f, serverPod, service) - framework.Logf("Waiting for Server to come up.") - err := framework.WaitForPodRunningInNamespace(f.ClientSet, serverPod) - Expect(err).NotTo(HaveOccurred()) - - By("Creating a network policy for the server which allows traffic from the pod 'client-a'.") - - policy := &networking.NetworkPolicy{ - ObjectMeta: metav1.ObjectMeta{ - Name: "allow-client-a-via-pod-selector", - }, - Spec: networking.NetworkPolicySpec{ - // Apply this policy to the Server - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{ - "pod-name": serverPod.Name, - }, - }, - // Allow traffic only from client-a - Ingress: []networking.NetworkPolicyIngressRule{{ - From: []networking.NetworkPolicyPeer{{ - PodSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "pod-name": "client-a", - }, - }, - }}, - }}, - }, - } - - policy, err = f.InternalClientset.Networking().NetworkPolicies(ns.Name).Create(policy) - Expect(err).NotTo(HaveOccurred()) - defer cleanupNetworkPolicy(f, policy) - - By("Creating client-a which should be able to contact the server.") - testCanConnect(f, ns, "client-a", service, 80) - testCannotConnect(f, ns, "client-b", service, 80) - }) - - It("should enforce policy based on Ports [Feature:NetworkPolicy]", func() { - ns := f.Namespace - - // Create Server with Service - By("Creating a simple server.") - serverPod, service := createServerPodAndService(f, ns, "server", []int{80, 81}) - defer cleanupServerPodAndService(f, serverPod, service) - framework.Logf("Waiting for Server to come up.") - err := framework.WaitForPodRunningInNamespace(f.ClientSet, serverPod) - Expect(err).NotTo(HaveOccurred()) - - By("Testing pods can connect to both ports when no policy is present.") - testCanConnect(f, ns, "basecase-reachable-80", service, 80) - testCanConnect(f, ns, "basecase-reachable-81", service, 81) - - By("Creating a network policy for the Service which allows traffic only to one port.") - policy := &networking.NetworkPolicy{ - ObjectMeta: metav1.ObjectMeta{ - Name: "allow-ingress-on-port-81", - }, - Spec: networking.NetworkPolicySpec{ - // Apply to server - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{ - "pod-name": serverPod.Name, - }, - }, - // Allow traffic only to one port. - Ingress: []networking.NetworkPolicyIngressRule{{ - Ports: []networking.NetworkPolicyPort{{ - Port: &intstr.IntOrString{IntVal: 81}, - }}, - }}, - }, - } - policy, err = f.InternalClientset.Networking().NetworkPolicies(ns.Name).Create(policy) - Expect(err).NotTo(HaveOccurred()) - defer cleanupNetworkPolicy(f, policy) - - By("Testing pods can connect only to the port allowed by the policy.") - testCannotConnect(f, ns, "client-a", service, 80) - testCanConnect(f, ns, "client-b", service, 81) - }) - - It("should enforce multiple, stacked policies with overlapping podSelectors [Feature:NetworkPolicy]", func() { - ns := f.Namespace - - // Create Server with Service - By("Creating a simple server.") - serverPod, service := createServerPodAndService(f, ns, "server", []int{80, 81}) - defer cleanupServerPodAndService(f, serverPod, service) - framework.Logf("Waiting for Server to come up.") - err := framework.WaitForPodRunningInNamespace(f.ClientSet, serverPod) - Expect(err).NotTo(HaveOccurred()) - - By("Testing pods can connect to both ports when no policy is present.") - testCanConnect(f, ns, "test-a", service, 80) - testCanConnect(f, ns, "test-b", service, 81) - - By("Creating a network policy for the Service which allows traffic only to one port.") - policy := &networking.NetworkPolicy{ - ObjectMeta: metav1.ObjectMeta{ - Name: "allow-ingress-on-port-80", - }, - Spec: networking.NetworkPolicySpec{ - // Apply to server - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{ - "pod-name": serverPod.Name, - }, - }, - // Allow traffic only to one port. - Ingress: []networking.NetworkPolicyIngressRule{{ - Ports: []networking.NetworkPolicyPort{{ - Port: &intstr.IntOrString{IntVal: 80}, - }}, - }}, - }, - } - policy, err = f.InternalClientset.Networking().NetworkPolicies(ns.Name).Create(policy) - Expect(err).NotTo(HaveOccurred()) - defer cleanupNetworkPolicy(f, policy) - - By("Creating a network policy for the Service which allows traffic only to another port.") - policy2 := &networking.NetworkPolicy{ - ObjectMeta: metav1.ObjectMeta{ - Name: "allow-ingress-on-port-81", - }, - Spec: networking.NetworkPolicySpec{ - // Apply to server - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{ - "pod-name": serverPod.Name, - }, - }, - // Allow traffic only to one port. - Ingress: []networking.NetworkPolicyIngressRule{{ - Ports: []networking.NetworkPolicyPort{{ - Port: &intstr.IntOrString{IntVal: 81}, - }}, - }}, - }, - } - policy2, err = f.InternalClientset.Networking().NetworkPolicies(ns.Name).Create(policy2) - Expect(err).NotTo(HaveOccurred()) - defer cleanupNetworkPolicy(f, policy2) - - By("Testing pods can connect to both ports when both policies are present.") - testCanConnect(f, ns, "client-a", service, 80) - testCanConnect(f, ns, "client-b", service, 81) - }) - - It("should support allow-all policy [Feature:NetworkPolicy]", func() { - ns := f.Namespace - - // Create Server with Service - By("Creating a simple server.") - serverPod, service := createServerPodAndService(f, ns, "server", []int{80, 81}) - defer cleanupServerPodAndService(f, serverPod, service) - framework.Logf("Waiting for Server to come up.") - err := framework.WaitForPodRunningInNamespace(f.ClientSet, serverPod) - Expect(err).NotTo(HaveOccurred()) - - By("Testing pods can connect to both ports when no policy is present.") - testCanConnect(f, ns, "test-a", service, 80) - testCanConnect(f, ns, "test-b", service, 81) - - By("Creating a network policy which allows all traffic.") - policy := &networking.NetworkPolicy{ - ObjectMeta: metav1.ObjectMeta{ - Name: "allow-all", - }, - Spec: networking.NetworkPolicySpec{ - // Allow all traffic - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{}, - }, - Ingress: []networking.NetworkPolicyIngressRule{{}}, - }, - } - policy, err = f.InternalClientset.Networking().NetworkPolicies(ns.Name).Create(policy) - Expect(err).NotTo(HaveOccurred()) - defer cleanupNetworkPolicy(f, policy) - - By("Testing pods can connect to both ports when an 'allow-all' policy is present.") - testCanConnect(f, ns, "client-a", service, 80) - testCanConnect(f, ns, "client-b", service, 81) - }) - - It("should enforce policy based on NamespaceSelector [Feature:NetworkPolicy]", func() { - nsA := f.Namespace - nsBName := f.BaseName + "-b" - // The CreateNamespace helper uses the input name as a Name Generator, so the namespace itself - // will have a different name than what we are setting as the value of ns-name. - // This is fine as long as we don't try to match the label as nsB.Name in our policy. - nsB, err := f.CreateNamespace(nsBName, map[string]string{ - "ns-name": nsBName, + // Create pods, which should be able to communicate with the server on port 80 and 81. + By("Testing pods can connect to both ports when no policy is present.") + testCanConnect(f, f.Namespace, "client-can-connect-80", service, 80) + testCanConnect(f, f.Namespace, "client-can-connect-81", service, 81) }) - Expect(err).NotTo(HaveOccurred()) - // Create Server with Service in NS-B - By("Creating a webserver tied to a service.") - serverPod, service := createServerPodAndService(f, nsA, "server", []int{80}) - defer cleanupServerPodAndService(f, serverPod, service) - framework.Logf("Waiting for server to come up.") - err = framework.WaitForPodRunningInNamespace(f.ClientSet, serverPod) - Expect(err).NotTo(HaveOccurred()) + AfterEach(func() { + cleanupServerPodAndService(f, podServer, service) + }) - // Create Policy for that service that allows traffic only via namespace B - By("Creating a network policy for the server which allows traffic from namespace-b.") - policy := &networking.NetworkPolicy{ - ObjectMeta: metav1.ObjectMeta{ - Name: "allow-ns-b-via-namespace-selector", - }, - Spec: networking.NetworkPolicySpec{ - // Apply to server - PodSelector: metav1.LabelSelector{ - MatchLabels: map[string]string{ - "pod-name": serverPod.Name, - }, + It("should support a 'default-deny' policy [Feature:NetworkPolicy]", func() { + policy := &networking.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "deny-all", }, - // Allow traffic only from NS-B - Ingress: []networking.NetworkPolicyIngressRule{{ - From: []networking.NetworkPolicyPeer{{ - NamespaceSelector: &metav1.LabelSelector{ - MatchLabels: map[string]string{ - "ns-name": nsBName, - }, - }, - }}, - }}, - }, - } - policy, err = f.InternalClientset.Networking().NetworkPolicies(nsA.Name).Create(policy) - Expect(err).NotTo(HaveOccurred()) - defer cleanupNetworkPolicy(f, policy) + Spec: networking.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{}, + Ingress: []networking.NetworkPolicyIngressRule{}, + }, + } - testCannotConnect(f, nsA, "client-a", service, 80) - testCanConnect(f, nsB, "client-b", service, 80) + policy, err := f.InternalClientset.Networking().NetworkPolicies(f.Namespace.Name).Create(policy) + Expect(err).NotTo(HaveOccurred()) + defer cleanupNetworkPolicy(f, policy) + + // Create a pod with name 'client-cannot-connect', which will attempt to communicate with the server, + // but should not be able to now that isolation is on. + testCannotConnect(f, f.Namespace, "client-cannot-connect", service, 80) + }) + + It("should enforce policy based on PodSelector [Feature:NetworkPolicy]", func() { + By("Creating a network policy for the server which allows traffic from the pod 'client-a'.") + policy := &networking.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-client-a-via-pod-selector", + }, + Spec: networking.NetworkPolicySpec{ + // Apply this policy to the Server + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "pod-name": podServer.Name, + }, + }, + // Allow traffic only from client-a + Ingress: []networking.NetworkPolicyIngressRule{{ + From: []networking.NetworkPolicyPeer{{ + PodSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "pod-name": "client-a", + }, + }, + }}, + }}, + }, + } + + policy, err := f.InternalClientset.Networking().NetworkPolicies(f.Namespace.Name).Create(policy) + Expect(err).NotTo(HaveOccurred()) + defer cleanupNetworkPolicy(f, policy) + + By("Creating client-a which should be able to contact the server.", func() { + testCanConnect(f, f.Namespace, "client-a", service, 80) + }) + By("Creating client-b which should not be able to contact the server.", func() { + testCannotConnect(f, f.Namespace, "client-b", service, 80) + }) + }) + + It("should enforce policy based on NamespaceSelector [Feature:NetworkPolicy]", func() { + nsA := f.Namespace + nsBName := f.BaseName + "-b" + // The CreateNamespace helper uses the input name as a Name Generator, so the namespace itself + // will have a different name than what we are setting as the value of ns-name. + // This is fine as long as we don't try to match the label as nsB.Name in our policy. + nsB, err := f.CreateNamespace(nsBName, map[string]string{ + "ns-name": nsBName, + }) + Expect(err).NotTo(HaveOccurred()) + + // Create Server with Service in NS-B + framework.Logf("Waiting for server to come up.") + err = framework.WaitForPodRunningInNamespace(f.ClientSet, podServer) + Expect(err).NotTo(HaveOccurred()) + + // Create Policy for that service that allows traffic only via namespace B + By("Creating a network policy for the server which allows traffic from namespace-b.") + policy := &networking.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-ns-b-via-namespace-selector", + }, + Spec: networking.NetworkPolicySpec{ + // Apply to server + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "pod-name": podServer.Name, + }, + }, + // Allow traffic only from NS-B + Ingress: []networking.NetworkPolicyIngressRule{{ + From: []networking.NetworkPolicyPeer{{ + NamespaceSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "ns-name": nsBName, + }, + }, + }}, + }}, + }, + } + policy, err = f.InternalClientset.Networking().NetworkPolicies(nsA.Name).Create(policy) + Expect(err).NotTo(HaveOccurred()) + defer cleanupNetworkPolicy(f, policy) + + testCannotConnect(f, nsA, "client-a", service, 80) + testCanConnect(f, nsB, "client-b", service, 80) + }) + + It("should enforce policy based on Ports [Feature:NetworkPolicy]", func() { + By("Creating a network policy for the Service which allows traffic only to one port.") + policy := &networking.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-ingress-on-port-81", + }, + Spec: networking.NetworkPolicySpec{ + // Apply to server + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "pod-name": podServer.Name, + }, + }, + // Allow traffic only to one port. + Ingress: []networking.NetworkPolicyIngressRule{{ + Ports: []networking.NetworkPolicyPort{{ + Port: &intstr.IntOrString{IntVal: 81}, + }}, + }}, + }, + } + policy, err := f.InternalClientset.Networking().NetworkPolicies(f.Namespace.Name).Create(policy) + Expect(err).NotTo(HaveOccurred()) + defer cleanupNetworkPolicy(f, policy) + + By("Testing pods can connect only to the port allowed by the policy.") + testCannotConnect(f, f.Namespace, "client-a", service, 80) + testCanConnect(f, f.Namespace, "client-b", service, 81) + }) + + It("should enforce multiple, stacked policies with overlapping podSelectors [Feature:NetworkPolicy]", func() { + By("Creating a network policy for the Service which allows traffic only to one port.") + policy := &networking.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-ingress-on-port-80", + }, + Spec: networking.NetworkPolicySpec{ + // Apply to server + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "pod-name": podServer.Name, + }, + }, + // Allow traffic only to one port. + Ingress: []networking.NetworkPolicyIngressRule{{ + Ports: []networking.NetworkPolicyPort{{ + Port: &intstr.IntOrString{IntVal: 80}, + }}, + }}, + }, + } + policy, err := f.InternalClientset.Networking().NetworkPolicies(f.Namespace.Name).Create(policy) + Expect(err).NotTo(HaveOccurred()) + defer cleanupNetworkPolicy(f, policy) + + By("Creating a network policy for the Service which allows traffic only to another port.") + policy2 := &networking.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-ingress-on-port-81", + }, + Spec: networking.NetworkPolicySpec{ + // Apply to server + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + "pod-name": podServer.Name, + }, + }, + // Allow traffic only to one port. + Ingress: []networking.NetworkPolicyIngressRule{{ + Ports: []networking.NetworkPolicyPort{{ + Port: &intstr.IntOrString{IntVal: 81}, + }}, + }}, + }, + } + policy2, err = f.InternalClientset.Networking().NetworkPolicies(f.Namespace.Name).Create(policy2) + Expect(err).NotTo(HaveOccurred()) + defer cleanupNetworkPolicy(f, policy2) + + By("Testing pods can connect to both ports when both policies are present.") + testCanConnect(f, f.Namespace, "client-a", service, 80) + testCanConnect(f, f.Namespace, "client-b", service, 81) + }) + + It("should support allow-all policy [Feature:NetworkPolicy]", func() { + By("Creating a network policy which allows all traffic.") + policy := &networking.NetworkPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "allow-all", + }, + Spec: networking.NetworkPolicySpec{ + // Allow all traffic + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{}, + }, + Ingress: []networking.NetworkPolicyIngressRule{{}}, + }, + } + policy, err := f.InternalClientset.Networking().NetworkPolicies(f.Namespace.Name).Create(policy) + Expect(err).NotTo(HaveOccurred()) + defer cleanupNetworkPolicy(f, policy) + + By("Testing pods can connect to both ports when an 'allow-all' policy is present.") + testCanConnect(f, f.Namespace, "client-a", service, 80) + testCanConnect(f, f.Namespace, "client-b", service, 81) + }) }) }) @@ -339,7 +296,35 @@ func testCanConnect(f *framework.Framework, ns *v1.Namespace, podName string, se framework.Logf("Waiting for %s to complete.", podClient.Name) err = framework.WaitForPodSuccessInNamespace(f.ClientSet, podClient.Name, ns.Name) - Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("checking %s could communicate with server.", podClient.Name)) + if err != nil { + // Collect pod logs when we see a failure. + logs, logErr := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, podName, fmt.Sprintf("%s-container", podName)) + if logErr != nil { + framework.Failf("Error getting container logs: %s", logErr) + } + + // Collect current NetworkPolicies applied in the test namespace. + policies, err := f.InternalClientset.Networking().NetworkPolicies(f.Namespace.Name).List(metav1.ListOptions{}) + if err != nil { + framework.Logf("error getting current NetworkPolicies for %s namespace: %s", f.Namespace.Name, err) + } + + // Collect the list of pods running in the test namespace. + podsInNS, err := framework.GetPodsInNamespace(f.ClientSet, f.Namespace.Name, map[string]string{}) + if err != nil { + framework.Logf("error getting pods for %s namespace: %s", f.Namespace.Name, err) + } + + pods := []string{} + for _, p := range podsInNS { + pods = append(pods, fmt.Sprintf("Pod: %s, Status: %s\n", p.Name, p.Status.String())) + } + + framework.Failf("Pod %s should be able to connect to service %s, but was not able to connect.\nPod logs:\n%s\n\n Current NetworkPolicies:\n\t%v\n\n Pods:\n\t%v\n\n", podName, service.Name, logs, policies.Items, pods) + + // Dump debug information for the test namespace. + framework.DumpDebugInfo(f.ClientSet, f.Namespace.Name) + } } func testCannotConnect(f *framework.Framework, ns *v1.Namespace, podName string, service *v1.Service, targetPort int) { @@ -354,7 +339,38 @@ func testCannotConnect(f *framework.Framework, ns *v1.Namespace, podName string, framework.Logf("Waiting for %s to complete.", podClient.Name) err := framework.WaitForPodSuccessInNamespace(f.ClientSet, podClient.Name, ns.Name) - Expect(err).To(HaveOccurred(), fmt.Sprintf("checking %s could not communicate with server.", podName)) + + // We expect an error here since it's a cannot connect test. + // Dump debug information if the error was nil. + if err == nil { + // Collect pod logs when we see a failure. + logs, logErr := framework.GetPodLogs(f.ClientSet, f.Namespace.Name, podName, fmt.Sprintf("%s-container", podName)) + if logErr != nil { + framework.Failf("Error getting container logs: %s", logErr) + } + + // Collect current NetworkPolicies applied in the test namespace. + policies, err := f.InternalClientset.Networking().NetworkPolicies(f.Namespace.Name).List(metav1.ListOptions{}) + if err != nil { + framework.Logf("error getting current NetworkPolicies for %s namespace: %s", f.Namespace.Name, err) + } + + // Collect the list of pods running in the test namespace. + podsInNS, err := framework.GetPodsInNamespace(f.ClientSet, f.Namespace.Name, map[string]string{}) + if err != nil { + framework.Logf("error getting pods for %s namespace: %s", f.Namespace.Name, err) + } + + pods := []string{} + for _, p := range podsInNS { + pods = append(pods, fmt.Sprintf("Pod: %s, Status: %s\n", p.Name, p.Status.String())) + } + + framework.Failf("Pod %s should not be able to connect to service %s, but was able to connect.\nPod logs:\n%s\n\n Current NetworkPolicies:\n\t%v\n\n Pods:\n\t %v\n\n", podName, service.Name, logs, policies.Items, pods) + + // Dump debug information for the test namespace. + framework.DumpDebugInfo(f.ClientSet, f.Namespace.Name) + } } // Create a server pod with a listening container for each port in ports[]. @@ -369,13 +385,25 @@ func createServerPodAndService(f *framework.Framework, namespace *v1.Namespace, // Build the containers for the server pod. containers = append(containers, v1.Container{ Name: fmt.Sprintf("%s-container-%d", podName, port), - Image: imageutils.GetE2EImage(imageutils.Redis), - Args: []string{ - "/bin/sh", - "-c", - fmt.Sprintf("/bin/nc -kl %d", port), + Image: imageutils.GetE2EImage(imageutils.Porter), + Env: []v1.EnvVar{ + { + Name: fmt.Sprintf("SERVE_PORT_%d", port), + Value: "foo", + }, }, Ports: []v1.ContainerPort{{ContainerPort: int32(port)}}, + ReadinessProbe: &v1.Probe{ + Handler: v1.Handler{ + HTTPGet: &v1.HTTPGetAction{ + Path: "/", + Port: intstr.IntOrString{ + IntVal: int32(port), + }, + Scheme: v1.URISchemeHTTP, + }, + }, + }, }) // Build the Service Ports for the service. @@ -433,7 +461,7 @@ func cleanupServerPodAndService(f *framework.Framework, pod *v1.Pod, service *v1 } // Create a client pod which will attempt a netcat to the provided service, on the specified port. -// This client will attempt a oneshot connection, then die, without restarting the pod. +// This client will attempt a one-shot connection, then die, without restarting the pod. // Test can then be asserted based on whether the pod quit with an error or not. func createNetworkClientPod(f *framework.Framework, namespace *v1.Namespace, podName string, targetService *v1.Service, targetPort int) *v1.Pod { pod, err := f.ClientSet.Core().Pods(namespace.Name).Create(&v1.Pod{ @@ -448,11 +476,12 @@ func createNetworkClientPod(f *framework.Framework, namespace *v1.Namespace, pod Containers: []v1.Container{ { Name: fmt.Sprintf("%s-container", podName), - Image: imageutils.GetE2EImage(imageutils.Redis), + Image: imageutils.GetBusyBoxImage(), Args: []string{ "/bin/sh", "-c", - fmt.Sprintf("/usr/bin/printf dummy-data | /bin/nc -w 8 %s.%s %d", targetService.Name, targetService.Namespace, targetPort), + fmt.Sprintf("for i in $(seq 1 5); do wget -T 8 %s.%s:%d -O - && exit 0 || sleep 1; done; exit 1", + targetService.Name, targetService.Namespace, targetPort), }, }, }, @@ -460,6 +489,7 @@ func createNetworkClientPod(f *framework.Framework, namespace *v1.Namespace, pod }) Expect(err).NotTo(HaveOccurred()) + return pod }