From 32e6c84245e64f8172724661bfa313fde132d0c7 Mon Sep 17 00:00:00 2001 From: msherif1234 Date: Sat, 27 May 2023 09:24:13 -0400 Subject: [PATCH] SDN-3979: adding disruption e2e coverage This is continuation of github.com/openshift/ingress-node-firewall/pull/221 Signed-off-by: msherif1234 --- test/e2e/daemonset/daemonset.go | 32 ++- test/e2e/deployment/deployment.go | 64 +++++ test/e2e/functional/tests/e2e.go | 268 ++++++++++++++++-- .../ingress-node-firewall.go | 10 + test/e2e/namespaces/namespaces.go | 4 +- test/e2e/pods/pods.go | 35 ++- test/e2e/transport/transport.go | 4 +- 7 files changed, 377 insertions(+), 40 deletions(-) create mode 100644 test/e2e/deployment/deployment.go diff --git a/test/e2e/daemonset/daemonset.go b/test/e2e/daemonset/daemonset.go index 26caade3c..821a83bd9 100644 --- a/test/e2e/daemonset/daemonset.go +++ b/test/e2e/daemonset/daemonset.go @@ -15,11 +15,33 @@ import ( "k8s.io/apimachinery/pkg/util/wait" ) -func WaitForDaemonSetReady(client *testclient.ClientSet, ds *appsv1.DaemonSet, namespace, name string, retryInterval, timeout time.Duration) error { - err := wait.PollImmediate(retryInterval, timeout, func() (done bool, err error) { +func GetDaemonSet(client *testclient.ClientSet, namespace, name string, timeout time.Duration) (*appsv1.DaemonSet, error) { + var daemonSet appsv1.DaemonSet + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + err := client.Get(ctx, types.NamespacedName{Name: name, Namespace: namespace}, &daemonSet) + return &daemonSet, err +} + +func GetDaemonSetWithRetry(client *testclient.ClientSet, namespace, name string, retryInterval, timeout time.Duration) (*appsv1.DaemonSet, error) { + var daemonSet *appsv1.DaemonSet + err := wait.PollUntilContextTimeout(context.Background(), retryInterval, timeout, true, func(ctx context.Context) (done bool, err error) { + if daemonSet, err = GetDaemonSet(client, namespace, name, timeout); err != nil { + if errors.IsNotFound(err) { + return false, nil + } + return false, err + } + return true, err + }) + return daemonSet, err +} + +func WaitForDaemonSetReady(client *testclient.ClientSet, ds *appsv1.DaemonSet, retryInterval, timeout time.Duration) error { + err := wait.PollUntilContextTimeout(context.Background(), retryInterval, timeout, true, func(ctx context.Context) (done bool, err error) { ctx, cancel := context.WithTimeout(context.Background(), timeout) defer cancel() - err = client.Get(ctx, types.NamespacedName{Name: name, Namespace: namespace}, ds) + err = client.Get(ctx, types.NamespacedName{Name: ds.Name, Namespace: ds.Namespace}, ds) if err != nil { if errors.IsNotFound(err) { return false, nil @@ -33,7 +55,7 @@ func WaitForDaemonSetReady(client *testclient.ClientSet, ds *appsv1.DaemonSet, n } }) if err != nil { - return fmt.Errorf("failed to wait for daemonset %s in namespace %s to be ready: %v", ds.Name, namespace, err) + return fmt.Errorf("failed to wait for daemonset %s in namespace %s to be ready: %v", ds.Name, ds.Namespace, err) } return nil @@ -41,7 +63,7 @@ func WaitForDaemonSetReady(client *testclient.ClientSet, ds *appsv1.DaemonSet, n func GetDaemonSetOnNode(client *testclient.ClientSet, namespace, nodeName string) (*corev1.Pod, error) { var podList *corev1.PodList - err := wait.PollImmediate(1*time.Second, 10*time.Second, func() (done bool, err error) { + err := wait.PollUntilContextTimeout(context.Background(), 1*time.Second, 10*time.Second, true, func(ctx context.Context) (done bool, err error) { podList, err = client.Pods(namespace).List(context.TODO(), metav1.ListOptions{ LabelSelector: "app=ingress-node-firewall-daemon", FieldSelector: fmt.Sprintf("spec.nodeName=%s", nodeName), diff --git a/test/e2e/deployment/deployment.go b/test/e2e/deployment/deployment.go new file mode 100644 index 000000000..e2ea7d025 --- /dev/null +++ b/test/e2e/deployment/deployment.go @@ -0,0 +1,64 @@ +package deployment + +import ( + "context" + "fmt" + "time" + + testclient "github.com/openshift/ingress-node-firewall/test/e2e/client" + + appsv1 "k8s.io/api/apps/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" + "k8s.io/apimachinery/pkg/util/wait" +) + +func GetDeployment(client *testclient.ClientSet, namespace, name string, timeout time.Duration) (*appsv1.Deployment, error) { + var deployment appsv1.Deployment + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + err := client.Get(ctx, types.NamespacedName{Name: name, Namespace: namespace}, &deployment) + return &deployment, err +} + +func GetDeploymentWithRetry(client *testclient.ClientSet, namespace, name string, retryInterval, timeout time.Duration) (*appsv1.Deployment, error) { + var deployment *appsv1.Deployment + err := wait.PollUntilContextTimeout(context.Background(), retryInterval, timeout, true, func(ctx context.Context) (done bool, err error) { + if deployment, err = GetDeployment(client, namespace, name, timeout); err != nil { + if errors.IsNotFound(err) { + return false, nil + } + return false, err + } + return true, nil + }) + + return deployment, err +} + +func WaitForDeploymentSetReady(client *testclient.ClientSet, deployment *appsv1.Deployment, retryInterval, + timeout time.Duration) error { + + err := wait.PollUntilContextTimeout(context.Background(), retryInterval, timeout, true, func(ctx context.Context) (done bool, err error) { + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + err = client.Get(ctx, types.NamespacedName{Name: deployment.Name, Namespace: deployment.Namespace}, deployment) + if err != nil { + if errors.IsNotFound(err) { + return false, nil + } + return false, err + } + if *deployment.Spec.Replicas == deployment.Status.ReadyReplicas { + return true, nil + } else { + return false, nil + } + }) + if err != nil { + return fmt.Errorf("failed to wait for deployment %s in namespace %s to be ready: %v", deployment.Name, + deployment.Namespace, err) + } + + return nil +} diff --git a/test/e2e/functional/tests/e2e.go b/test/e2e/functional/tests/e2e.go index 0d54bb8a8..2d36fbd68 100644 --- a/test/e2e/functional/tests/e2e.go +++ b/test/e2e/functional/tests/e2e.go @@ -15,6 +15,7 @@ import ( inftestconsts "github.com/openshift/ingress-node-firewall/test/consts" testclient "github.com/openshift/ingress-node-firewall/test/e2e/client" "github.com/openshift/ingress-node-firewall/test/e2e/daemonset" + "github.com/openshift/ingress-node-firewall/test/e2e/deployment" "github.com/openshift/ingress-node-firewall/test/e2e/events" "github.com/openshift/ingress-node-firewall/test/e2e/exec" "github.com/openshift/ingress-node-firewall/test/e2e/icmp" @@ -36,16 +37,20 @@ import ( ) var ( - OperatorNameSpace = inftestconsts.DefaultOperatorNameSpace - retryInterval = time.Millisecond * 10 - timeout = time.Second * 40 - testInterface = "eth0" - sctpEnabled = false - isSingleStack = false - v4Enabled = false - v6Enabled = false - v4SubnetLen = "32" - v6SubnetLen = "128" + OperatorNameSpace = inftestconsts.DefaultOperatorNameSpace + retryInterval = time.Millisecond * 10 + timeout = time.Second * 40 + testInterface = "eth0" + sctpEnabled = false + isSingleStack = false + v4Enabled = false + v6Enabled = false + v4SubnetLen = "32" + v6SubnetLen = "128" + testArtifactsLabelKey = "e2e-inf-test" + testArtifactsLabelValue = "" + testArtifactsLabelMap = map[string]string{testArtifactsLabelKey: testArtifactsLabelValue} + testArtifactsLabelString = fmt.Sprintf("%s=%s", testArtifactsLabelKey, testArtifactsLabelValue) ) // testIngressNodeFirewall represents one IngressNodeFirewall object and is used to generate the sourceCIDRs and protocol @@ -112,20 +117,16 @@ func init() { v4Enabled = node.IPV4NetworkExists(testclient.Client, timeout) v6Enabled = node.IPV6NetworkExists(testclient.Client, timeout) + if !v4Enabled && !v6Enabled { + panic("Unable to detect if cluster is IPV4 or IPV6") + } } var _ = Describe("Ingress Node Firewall", func() { - var ( - testArtifactsLabelKey = "e2e-inf-test" - testArtifactsLabelValue = "" - testArtifactsLabelMap = map[string]string{testArtifactsLabelKey: testArtifactsLabelValue} - testArtifactsLabelString = fmt.Sprintf("%s=%s", testArtifactsLabelKey, testArtifactsLabelValue) - ) - // Because we don't fully use BeforeAll / AfterAll to setup/teardown test infrastructure and if an error or interrupt occurs, // we ensure a clean cluster using AfterSuite. This normally is a no-op and is only valid when user sends interrupt or test failure. AfterSuite(func() { - Expect(pods.EnsureDeletedWithLabel(testclient.Client, OperatorNameSpace, testArtifactsLabelString, timeout)).Should(Succeed()) + Expect(pods.EnsureDeletedWithLabel(testclient.Client, OperatorNameSpace, testArtifactsLabelString, retryInterval, timeout)).Should(Succeed()) Expect(infwutils.DeleteIngressNodeFirewallsWithLabels(testclient.Client, OperatorNameSpace, testArtifactsLabelString, timeout)).Should(Succeed()) }) @@ -839,8 +840,9 @@ var _ = Describe("Ingress Node Firewall", func() { Expect(err).ShouldNot(HaveOccurred()) //wait for daemonset to be rolled out infDaemonSet := &appsv1.DaemonSet{} - err = daemonset.WaitForDaemonSetReady(testclient.Client, infDaemonSet, OperatorNameSpace, - "ingress-node-firewall-daemon", retryInterval, timeout) + infDaemonSet.SetName("ingress-node-firewall-daemon") + infDaemonSet.SetNamespace(OperatorNameSpace) + err = daemonset.WaitForDaemonSetReady(testclient.Client, infDaemonSet, retryInterval, timeout) Expect(err).ShouldNot(HaveOccurred()) }) @@ -974,6 +976,161 @@ var _ = Describe("Ingress Node Firewall", func() { } }) + Context("Disruption", func() { + var ( + testName = "e2e-disruption" + clientOnePodName = "e2e-disruption-client-one" + serverOnePodName = "e2e-disruption-server-one" + serverLabelKey = "e2e-disruption-server" + serverLabelValue = "" + serverPodLabel = map[string]string{serverLabelKey: serverLabelValue, testArtifactsLabelKey: testArtifactsLabelValue} + clientLabelKey = "e2e-disruption-client" + clientLabelValue = "" + clientPodLabel = map[string]string{clientLabelKey: clientLabelValue, testArtifactsLabelKey: testArtifactsLabelValue} + ) + + It("controller manager functions after deletion", func() { + infConfigs, err := infwutils.GetIngressNodeFirewallConfigs(testclient.Client, timeout) + Expect(err).ShouldNot(HaveOccurred()) + By("Ensure IngressNodeFirewallConfigs doesn't exist") + Expect(len(infConfigs)).Should(BeNumerically("==", 0)) + By("Delete controller manager pods") + controllerManagerDeployment, err := deployment.GetDeploymentWithRetry(testclient.Client, OperatorNameSpace, + inftestconsts.IngressNodeFirewallOperatorDeploymentName, retryInterval, timeout) + Expect(err).ShouldNot(HaveOccurred()) + Expect(deployment.WaitForDeploymentSetReady(testclient.Client, controllerManagerDeployment, retryInterval, + timeout)).ShouldNot(HaveOccurred()) + Expect(pods.EnsureDeletedWithLabel(testclient.Client, OperatorNameSpace, + fmt.Sprintf("control-plane=%s", inftestconsts.IngressNodeFirewallOperatorDeploymentLabel), + retryInterval, timeout)).ShouldNot(HaveOccurred()) + Expect(deployment.WaitForDeploymentSetReady(testclient.Client, controllerManagerDeployment, retryInterval, + timeout)).ShouldNot(HaveOccurred()) + By("Ensure controller manager reacts to new IngressNodeFirewallConfig object") + config := &ingressnodefwv1alpha1.IngressNodeFirewallConfig{} + err = infwutils.LoadIngressNodeFirewallConfigFromFile(config, inftestconsts.IngressNodeFirewallConfigCRFile) + Expect(err).ToNot(HaveOccurred()) + config.SetNamespace(OperatorNameSpace) + Expect(infwutils.EnsureIngressNodeFirewallConfigExists(testclient.Client, config, timeout)).ShouldNot(HaveOccurred()) + defer infwutils.DeleteIngressNodeFirewallConfig(testclient.Client, config, retryInterval, timeout) + _, err = daemonset.GetDaemonSetWithRetry(testclient.Client, OperatorNameSpace, + inftestconsts.IngressNodeFirewallDaemonsetName, retryInterval, timeout) + Expect(err).ShouldNot(HaveOccurred()) + By("Ensure no controller manager restarts occurred") + restartCount, err := pods.GetPodWithLabelRestartCount(testclient.Client, OperatorNameSpace, + fmt.Sprintf("control-plane=%s", inftestconsts.IngressNodeFirewallOperatorDeploymentLabel), timeout) + Expect(err).ShouldNot(HaveOccurred()) + Expect(restartCount).Should(BeNumerically("==", 0)) + }) + + It("Existing IngresNodeFirewall policy persists after daemon deletion", func() { + config := &ingressnodefwv1alpha1.IngressNodeFirewallConfig{} + err := infwutils.LoadIngressNodeFirewallConfigFromFile(config, inftestconsts.IngressNodeFirewallConfigCRFile) + Expect(err).ToNot(HaveOccurred()) + config.SetNamespace(OperatorNameSpace) + Expect(infwutils.EnsureIngressNodeFirewallConfigExists(testclient.Client, config, timeout)).ShouldNot(HaveOccurred()) + defer infwutils.DeleteIngressNodeFirewallConfig(testclient.Client, config, retryInterval, timeout) + daemonSetDeployment, err := daemonset.GetDaemonSetWithRetry(testclient.Client, OperatorNameSpace, + inftestconsts.IngressNodeFirewallDaemonsetName, retryInterval, timeout) + Expect(err).ShouldNot(HaveOccurred()) + Expect(daemonset.WaitForDaemonSetReady(testclient.Client, daemonSetDeployment, retryInterval, timeout)).ShouldNot(HaveOccurred()) + clientPod, serverPod, cleanupPodsFn, err := getClientServerTestPods(testclient.Client, + OperatorNameSpace, clientOnePodName, clientPodLabel, serverOnePodName, serverPodLabel) + Expect(err).ShouldNot(HaveOccurred()) + defer cleanupPodsFn() + inf, err := getICMPEchoBlockINF(clientPod, testName, v4Enabled, v6Enabled, isSingleStack) + Expect(err).ShouldNot(HaveOccurred()) + Expect(infwutils.CreateIngressNodeFirewall(testclient.Client, inf, timeout)).ShouldNot(HaveOccurred()) + By("Confirm connectivity is affected by IngressNodeFirewall policy") + if v4Enabled { + Eventually(func() bool { + return icmp.IsConnectivityOK(testclient.Client, ingressnodefwv1alpha1.ProtocolTypeICMP, clientPod, pods.GetIPV4(serverPod.Status.PodIPs)) + }, timeout, retryInterval).Should(BeFalse()) + } + + if !isSingleStack && v6Enabled { + Eventually(func() bool { + return icmp.IsConnectivityOK(testclient.Client, ingressnodefwv1alpha1.ProtocolTypeICMP6, clientPod, pods.GetIPV6(serverPod.Status.PodIPs)) + }, timeout, retryInterval).Should(BeFalse()) + + } + By("Delete node daemon on node where policy will be applied") + daemonSetPod, err := daemonset.GetDaemonSetOnNode(testclient.Client, OperatorNameSpace, serverPod.Spec.NodeName) + Expect(err).ShouldNot(HaveOccurred()) + Expect(pods.EnsureDeleted(testclient.Client, daemonSetPod, retryInterval, timeout)).ShouldNot(HaveOccurred()) + Expect(daemonset.WaitForDaemonSetReady(testclient.Client, daemonSetDeployment, retryInterval, timeout)).ShouldNot(HaveOccurred()) + By("Confirm IngressNodeFirewall policy is unaffected after daemon restart") + if v4Enabled { + Eventually(func() bool { + return icmp.IsConnectivityOK(testclient.Client, ingressnodefwv1alpha1.ProtocolTypeICMP, clientPod, pods.GetIPV4(serverPod.Status.PodIPs)) + }, timeout, retryInterval).Should(BeFalse()) + } + + if !isSingleStack && v6Enabled { + Eventually(func() bool { + return icmp.IsConnectivityOK(testclient.Client, ingressnodefwv1alpha1.ProtocolTypeICMP6, clientPod, pods.GetIPV6(serverPod.Status.PodIPs)) + }, timeout, retryInterval).Should(BeFalse()) + + } + Expect(infwutils.DeleteIngressNodeFirewall(testclient.Client, inf, timeout)).ShouldNot(HaveOccurred()) + }) + + It("IngressNodeFirewall policy is configurable after daemon deletion", func() { + config := &ingressnodefwv1alpha1.IngressNodeFirewallConfig{} + err := infwutils.LoadIngressNodeFirewallConfigFromFile(config, inftestconsts.IngressNodeFirewallConfigCRFile) + Expect(err).ToNot(HaveOccurred()) + config.SetNamespace(OperatorNameSpace) + Expect(infwutils.EnsureIngressNodeFirewallConfigExists(testclient.Client, config, timeout)).ShouldNot(HaveOccurred()) + defer infwutils.DeleteIngressNodeFirewallConfig(testclient.Client, config, retryInterval, timeout) + daemonSetDeployment, err := daemonset.GetDaemonSetWithRetry(testclient.Client, OperatorNameSpace, + inftestconsts.IngressNodeFirewallDaemonsetName, retryInterval, timeout) + Expect(err).ShouldNot(HaveOccurred()) + Expect(daemonset.WaitForDaemonSetReady(testclient.Client, daemonSetDeployment, retryInterval, timeout)).ShouldNot(HaveOccurred()) + clientPod, serverPod, cleanupPodsFn, err := getClientServerTestPods(testclient.Client, + OperatorNameSpace, clientOnePodName, clientPodLabel, serverOnePodName, serverPodLabel) + Expect(err).ShouldNot(HaveOccurred()) + defer cleanupPodsFn() + inf, err := getICMPEchoBlockINF(clientPod, testName, v4Enabled, v6Enabled, isSingleStack) + Expect(err).ShouldNot(HaveOccurred()) + Expect(infwutils.CreateIngressNodeFirewall(testclient.Client, inf, timeout)).ShouldNot(HaveOccurred()) + By("Confirm connectivity is affected by IngressNodeFirewall policy") + if v4Enabled { + Eventually(func() bool { + return icmp.IsConnectivityOK(testclient.Client, ingressnodefwv1alpha1.ProtocolTypeICMP, clientPod, pods.GetIPV4(serverPod.Status.PodIPs)) + }, timeout, retryInterval).Should(BeFalse()) + } + + if !isSingleStack && v6Enabled { + Eventually(func() bool { + return icmp.IsConnectivityOK(testclient.Client, ingressnodefwv1alpha1.ProtocolTypeICMP6, clientPod, pods.GetIPV6(serverPod.Status.PodIPs)) + }, timeout, retryInterval).Should(BeFalse()) + + } + By("Delete node daemon on node where policy will be applied") + daemonSetPod, err := daemonset.GetDaemonSetOnNode(testclient.Client, OperatorNameSpace, serverPod.Spec.NodeName) + Expect(err).ShouldNot(HaveOccurred()) + Expect(pods.EnsureDeleted(testclient.Client, daemonSetPod, retryInterval, timeout)).ShouldNot(HaveOccurred()) + Expect(daemonset.WaitForDaemonSetReady(testclient.Client, daemonSetDeployment, retryInterval, timeout)).ShouldNot(HaveOccurred()) + By("Delete IngressNodeFirewall removes policy") + Eventually(func() bool { + err := infwutils.DeleteIngressNodeFirewall(testclient.Client, inf, timeout) + return errors.IsNotFound(err) + }, timeout, retryInterval).Should(BeTrue(), "Failed to delete IngressNodeFirewall rules") + + if v4Enabled { + Eventually(func() bool { + return icmp.IsConnectivityOK(testclient.Client, ingressnodefwv1alpha1.ProtocolTypeICMP, clientPod, pods.GetIPV4(serverPod.Status.PodIPs)) + }, timeout, retryInterval).Should(BeTrue()) + } + + if !isSingleStack && v6Enabled { + Eventually(func() bool { + return icmp.IsConnectivityOK(testclient.Client, ingressnodefwv1alpha1.ProtocolTypeICMP6, clientPod, pods.GetIPV6(serverPod.Status.PodIPs)) + }, timeout, retryInterval).Should(BeTrue()) + + } + }) + }) + Context("Statistics", func() { var config *ingressnodefwv1alpha1.IngressNodeFirewallConfig var configCRExisted bool @@ -1010,7 +1167,7 @@ var _ = Describe("Ingress Node Firewall", func() { }) It("should expose at least one endpoint via a daemon metrics service", func() { - err := wait.PollImmediate(1*time.Second, 10*time.Second, func() (done bool, err error) { + err := wait.PollUntilContextTimeout(context.Background(), 1*time.Second, 10*time.Second, true, func(ctx context.Context) (done bool, err error) { endpointSliceList, err := testclient.Client.Endpoints(OperatorNameSpace).List(context.TODO(), metav1.ListOptions{ LabelSelector: "app=ingress-node-firewall-daemon", }) @@ -1136,7 +1293,7 @@ var _ = Describe("Ingress Node Firewall", func() { Expect(err).ShouldNot(HaveOccurred()) var stdOut, stdError string var metrics testutil.Metrics - err = wait.PollImmediate(1*time.Second, 60*time.Second, func() (done bool, err error) { + err = wait.PollUntilContextTimeout(context.Background(), 1*time.Second, 30*time.Second, true, func(ctx context.Context) (done bool, err error) { stdOut, stdError, err = exec.RunExecCommand(testclient.Client, daemonSetPod, "/usr/bin/curl", "127.0.0.1:39301/metrics") if err != nil { return false, err @@ -1463,3 +1620,70 @@ func checkNodeStateCreate(client *testclient.ClientSet, nodeStateList *ingressno return len(nodeStateList.Items) == node.GetNumOfNodesWithMatchingLabel(testclient.Client, timeout) }, timeout, retryInterval).Should(BeTrue()) } + +func getClientServerTestPods(client *testclient.ClientSet, namespace, clientName string, clientLabel map[string]string, + serverName string, serverLabel map[string]string) (*corev1.Pod, *corev1.Pod, func(), error) { + var clientPod, serverPod *corev1.Pod + var clientCleanupFn, serverCleanupFn func() + var err error + + Eventually(func() error { + clientPod, clientCleanupFn, err = transport.GetAndEnsureRunningClient(client, clientName, namespace, clientLabel, clientLabel, + serverLabel, retryInterval, timeout) + return err + }, time.Minute, time.Second).ShouldNot(HaveOccurred(), "Failed to setup client test pod") + + Eventually(func() error { + serverPod, serverCleanupFn, err = transport.GetAndEnsureRunningTransportServer(client, serverName, + OperatorNameSpace, serverLabel, serverLabel, clientLabel, retryInterval, timeout) + return err + }, time.Minute, time.Second).ShouldNot(HaveOccurred(), "Failed to setup server test pod") + + return clientPod, serverPod, func() { + clientCleanupFn() + serverCleanupFn() + }, nil +} + +func getPodSourceCIDRs(pod *corev1.Pod, v4, v6, singleStack bool) ([]string, error) { + sourceCIDRs := make([]string, 0) + if v4 { + _, v4CIDR, err := net.ParseCIDR(fmt.Sprintf("%s/%s", pods.GetIPV4(pod.Status.PodIPs), "32")) + if err != nil { + return nil, err + } + sourceCIDRs = append(sourceCIDRs, v4CIDR.String()) + } + if !singleStack && v6 { + _, v6CIDR, err := net.ParseCIDR(fmt.Sprintf("%s/%s", pods.GetIPV6(pod.Status.PodIPs), "128")) + if err != nil { + return nil, err + } + sourceCIDRs = append(sourceCIDRs, v6CIDR.String()) + } + return sourceCIDRs, nil +} + +func getICMPEchoBlockINF(pod *corev1.Pod, infName string, v4, v6, singleStack bool) (*ingressnodefwv1alpha1.IngressNodeFirewall, error) { + inf := &ingressnodefwv1alpha1.IngressNodeFirewall{} + inf.SetName(infName) + inf.SetLabels(testArtifactsLabelMap) + infwutils.DefineWithWorkerNodeSelector(inf) + infwutils.DefineWithInterface(inf, testInterface) + sourceCIDRs, err := getPodSourceCIDRs(pod, v4, v6, singleStack) + if err != nil { + return nil, err + } + protoRules := make([]ingressnodefwv1alpha1.IngressNodeFirewallProtocolRule, 0) + if v4 { + protoRules = append(protoRules, infwutils.GetICMPBlockRule(ingressnodefwv1alpha1.ProtocolTypeICMP, 1, 8, 0)) + } + if !singleStack && v6 { + protoRules = append(protoRules, infwutils.GetICMPBlockRule(ingressnodefwv1alpha1.ProtocolTypeICMP6, 2, 128, 0)) + } + inf.Spec.Ingress = append(inf.Spec.Ingress, ingressnodefwv1alpha1.IngressNodeFirewallRules{ + SourceCIDRs: sourceCIDRs, + FirewallProtocolRules: protoRules, + }) + return inf, nil +} diff --git a/test/e2e/ingress-node-firewall/ingress-node-firewall.go b/test/e2e/ingress-node-firewall/ingress-node-firewall.go index 543b624d6..11b549b76 100644 --- a/test/e2e/ingress-node-firewall/ingress-node-firewall.go +++ b/test/e2e/ingress-node-firewall/ingress-node-firewall.go @@ -77,6 +77,16 @@ func EnsureIngressNodeFirewallConfigExists(client *testclient.ClientSet, config return err } +func GetIngressNodeFirewallConfigs(client *testclient.ClientSet, timeout time.Duration) ([]ingressnodefwv1alpha1.IngressNodeFirewallConfig, error) { + var infcList ingressnodefwv1alpha1.IngressNodeFirewallConfigList + ctx, cancel := context.WithTimeout(context.Background(), timeout) + defer cancel() + if err := client.List(ctx, &infcList); err != nil { + return nil, err + } + return infcList.Items, nil +} + func CreateIngressNodeFirewall(client *testclient.ClientSet, inf *ingressnodefwv1alpha1.IngressNodeFirewall, timeout time.Duration) error { ctx, cancel := context.WithTimeout(context.Background(), timeout) diff --git a/test/e2e/namespaces/namespaces.go b/test/e2e/namespaces/namespaces.go index c0753fc8c..30a94e614 100644 --- a/test/e2e/namespaces/namespaces.go +++ b/test/e2e/namespaces/namespaces.go @@ -19,8 +19,8 @@ import ( // WaitForDeletion waits until the namespace will be removed from the cluster func WaitForDeletion(cs *testclient.ClientSet, nsName string, timeout time.Duration) error { - return wait.PollImmediate(time.Second, timeout, func() (bool, error) { - _, err := cs.Namespaces().Get(context.Background(), nsName, metav1.GetOptions{}) + return wait.PollUntilContextTimeout(context.Background(), time.Second, timeout, true, func(ctx context.Context) (done bool, err error) { + _, err = cs.Namespaces().Get(context.Background(), nsName, metav1.GetOptions{}) if errors.IsNotFound(err) { return true, nil } diff --git a/test/e2e/pods/pods.go b/test/e2e/pods/pods.go index e5ad5dfe7..5bd63f5e3 100644 --- a/test/e2e/pods/pods.go +++ b/test/e2e/pods/pods.go @@ -23,7 +23,7 @@ func EnsureRunning(client *testclient.ClientSet, pod *corev1.Pod, namespace stri return nil, err } } - err = wait.PollImmediate(retryInterval, timeout, func() (done bool, err error) { + err = wait.PollUntilContextTimeout(context.Background(), retryInterval, timeout, true, func(ctx context.Context) (done bool, err error) { testPod, err = client.Pods(namespace).Get(context.Background(), created.Name, metav1.GetOptions{}) if err != nil { return false, err @@ -36,17 +36,20 @@ func EnsureRunning(client *testclient.ClientSet, pod *corev1.Pod, namespace stri return testPod, err } -func EnsureDeleted(client *testclient.ClientSet, pod *corev1.Pod, timeout time.Duration) error { - err := client.Pods(pod.Namespace).Delete(context.Background(), pod.Name, metav1.DeleteOptions{}) - if err != nil { - if errors.IsNotFound(err) { - return nil +func EnsureDeleted(client *testclient.ClientSet, pod *corev1.Pod, retryInterval, timeout time.Duration) error { + err := wait.PollUntilContextTimeout(context.Background(), retryInterval, timeout, true, func(ctx context.Context) (done bool, err error) { + err = client.Pods(pod.Namespace).Delete(context.Background(), pod.Name, metav1.DeleteOptions{}) + if err != nil { + if errors.IsNotFound(err) { + return true, nil + } } - } + return false, nil + }) return err } -func EnsureDeletedWithLabel(client *testclient.ClientSet, ns, label string, timeout time.Duration) error { +func EnsureDeletedWithLabel(client *testclient.ClientSet, ns, label string, retryInterval, timeout time.Duration) error { podList, err := client.Pods(ns).List(context.TODO(), metav1.ListOptions{ LabelSelector: label, }) @@ -54,13 +57,27 @@ func EnsureDeletedWithLabel(client *testclient.ClientSet, ns, label string, time return err } for _, pod := range podList.Items { - if err = EnsureDeleted(client, &pod, timeout); err != nil { + if err = EnsureDeleted(client, &pod, retryInterval, timeout); err != nil { return err } } return nil } +func GetPodWithLabelRestartCount(client *testclient.ClientSet, namespace, label string, timeout time.Duration) (int, error) { + podList, err := client.Pods(namespace).List(context.TODO(), metav1.ListOptions{LabelSelector: label}) + if err != nil { + return 0, err + } + var count int + for _, pod := range podList.Items { + for _, containerStatus := range pod.Status.ContainerStatuses { + count += int(containerStatus.RestartCount) + } + } + return count, nil +} + func GetIPV4(ips []corev1.PodIP) string { for _, ip := range ips { parsedIP := net.ParseIP(ip.IP) diff --git a/test/e2e/transport/transport.go b/test/e2e/transport/transport.go index ce2ccd3d8..04fa4ce1f 100644 --- a/test/e2e/transport/transport.go +++ b/test/e2e/transport/transport.go @@ -26,7 +26,7 @@ func GetAndEnsureRunningClient(client *testclient.ClientSet, podName, namespace return nil, nil, err } return pod, func() { - if err = pods.EnsureDeleted(client, pod, timeout); err != nil { + if err = pods.EnsureDeleted(client, pod, retryInterval, timeout); err != nil { panic(err) } }, nil @@ -85,7 +85,7 @@ func GetAndEnsureRunningTransportServer(client *testclient.ClientSet, podName, n return nil, nil, err } return pod, func() { - if err = pods.EnsureDeleted(client, pod, timeout); err != nil { + if err = pods.EnsureDeleted(client, pod, retryInterval, timeout); err != nil { panic(err) } }, nil