From 26abce8b6aa4d1870acf2ead90b17702b964b469 Mon Sep 17 00:00:00 2001 From: changzhen Date: Fri, 8 Mar 2024 18:29:17 +0800 Subject: [PATCH 1/2] add e2e for remedy Signed-off-by: changzhen --- test/e2e/framework/resource/karmada/remedy.go | 43 +++++++ test/e2e/remedy_test.go | 105 ++++++++++++++++++ test/e2e/suite_test.go | 1 + 3 files changed, 149 insertions(+) create mode 100644 test/e2e/framework/resource/karmada/remedy.go create mode 100644 test/e2e/remedy_test.go diff --git a/test/e2e/framework/resource/karmada/remedy.go b/test/e2e/framework/resource/karmada/remedy.go new file mode 100644 index 000000000000..cacfbfafd4bd --- /dev/null +++ b/test/e2e/framework/resource/karmada/remedy.go @@ -0,0 +1,43 @@ +/* +Copyright 2024 The Karmada Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package karmada + +import ( + "context" + "fmt" + + "github.com/onsi/ginkgo/v2" + "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + remedyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/remedy/v1alpha1" + karmada "github.com/karmada-io/karmada/pkg/generated/clientset/versioned" +) + +// CreateRemedy create Remedy with karmada client. +func CreateRemedy(client karmada.Interface, remedy *remedyv1alpha1.Remedy) { + ginkgo.By(fmt.Sprintf("Creating Remedy(%s)", remedy.Name), func() { + _, err := client.RemedyV1alpha1().Remedies().Create(context.TODO(), remedy, metav1.CreateOptions{}) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + }) +} + +// RemoveRemedy delete Remedy with karmada client. +func RemoveRemedy(client karmada.Interface, name string) { + err := client.RemedyV1alpha1().Remedies().Delete(context.TODO(), name, metav1.DeleteOptions{}) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) +} diff --git a/test/e2e/remedy_test.go b/test/e2e/remedy_test.go new file mode 100644 index 000000000000..7f28623bc098 --- /dev/null +++ b/test/e2e/remedy_test.go @@ -0,0 +1,105 @@ +/* +Copyright 2024 The Karmada Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package e2e + +import ( + "context" + + "github.com/onsi/ginkgo/v2" + "github.com/onsi/gomega" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/rand" + + clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1" + remedyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/remedy/v1alpha1" + "github.com/karmada-io/karmada/test/e2e/framework" + karmadaresource "github.com/karmada-io/karmada/test/e2e/framework/resource/karmada" +) + +var _ = ginkgo.Describe("remedy testing", func() { + ginkgo.Context("remedy.spec.decisionMatches is not empty", func() { + var remedyName string + var remedy *remedyv1alpha1.Remedy + var targetCluster string + + ginkgo.BeforeEach(func() { + targetCluster = framework.ClusterNames()[0] + remedyName = remedyNamePrefix + rand.String(RandomStrLength) + remedy = &remedyv1alpha1.Remedy{ + ObjectMeta: metav1.ObjectMeta{Name: remedyName}, + Spec: remedyv1alpha1.RemedySpec{ + DecisionMatches: []remedyv1alpha1.DecisionMatch{ + { + ClusterConditionMatch: &remedyv1alpha1.ClusterConditionRequirement{ + ConditionType: remedyv1alpha1.ServiceDomainNameResolutionReady, + Operator: remedyv1alpha1.ClusterConditionEqual, + ConditionStatus: string(metav1.ConditionFalse), + }, + }, + }, + Actions: []remedyv1alpha1.RemedyAction{remedyv1alpha1.TrafficControl}, + }, + } + + karmadaresource.CreateRemedy(karmadaClient, remedy) + }) + + ginkgo.It("The domain name resolution function of the cluster encounters an exception and recover", func() { + ginkgo.By("update cluster ServiceDomainNameResolutionReady condition to false", func() { + clusterObj, err := karmadaClient.ClusterV1alpha1().Clusters().Get(context.TODO(), targetCluster, metav1.GetOptions{}) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + + meta.SetStatusCondition(&clusterObj.Status.Conditions, metav1.Condition{ + Type: string(remedyv1alpha1.ServiceDomainNameResolutionReady), + Status: metav1.ConditionFalse, + }) + _, err = karmadaClient.ClusterV1alpha1().Clusters().UpdateStatus(context.TODO(), clusterObj, metav1.UpdateOptions{}) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + }) + + ginkgo.By("wait cluster status has TrafficControl RemedyAction", func() { + framework.WaitClusterFitWith(controlPlaneClient, targetCluster, func(cluster *clusterv1alpha1.Cluster) bool { + for _, action := range cluster.Status.RemedyActions { + if action == string(remedyv1alpha1.TrafficControl) { + return true + } + } + return false + }) + }) + + ginkgo.By("recover cluster ServiceDomainNameResolutionReady to true", func() { + clusterObj, err := karmadaClient.ClusterV1alpha1().Clusters().Get(context.TODO(), targetCluster, metav1.GetOptions{}) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + + meta.SetStatusCondition(&clusterObj.Status.Conditions, metav1.Condition{ + Type: string(remedyv1alpha1.ServiceDomainNameResolutionReady), + Status: metav1.ConditionFalse, + }) + _, err = karmadaClient.ClusterV1alpha1().Clusters().UpdateStatus(context.TODO(), clusterObj, metav1.UpdateOptions{}) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + }) + }) + + ginkgo.It("The domain name resolution function of the cluster encounters an exception, then remove the remedy resource", func() {}) + }) + + ginkgo.Context("test with nil decision matches remedy", func() { + + }) +}) diff --git a/test/e2e/suite_test.go b/test/e2e/suite_test.go index b581a93490df..842569206ebf 100644 --- a/test/e2e/suite_test.go +++ b/test/e2e/suite_test.go @@ -81,6 +81,7 @@ const ( ppNamePrefix = "pp-" cppNamePrefix = "cpp-" workloadRebalancerPrefix = "rebalancer-" + remedyNamePrefix = "remedy-" updateDeploymentReplicas = 2 updateStatefulSetReplicas = 2 From 87a193864314b80b3a7389609cdbf5b0c187e419 Mon Sep 17 00:00:00 2001 From: changzhen Date: Fri, 31 May 2024 16:56:57 +0800 Subject: [PATCH 2/2] add e2e for remedy Signed-off-by: changzhen --- test/e2e/remedy_test.go | 117 ++++++++++++++++++++++++++++++++++------ 1 file changed, 101 insertions(+), 16 deletions(-) diff --git a/test/e2e/remedy_test.go b/test/e2e/remedy_test.go index 7f28623bc098..acaf9c66e693 100644 --- a/test/e2e/remedy_test.go +++ b/test/e2e/remedy_test.go @@ -18,12 +18,14 @@ package e2e import ( "context" + "fmt" "github.com/onsi/ginkgo/v2" "github.com/onsi/gomega" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/rand" + "k8s.io/apimachinery/pkg/util/sets" clusterv1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1" remedyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/remedy/v1alpha1" @@ -31,12 +33,12 @@ import ( karmadaresource "github.com/karmada-io/karmada/test/e2e/framework/resource/karmada" ) -var _ = ginkgo.Describe("remedy testing", func() { - ginkgo.Context("remedy.spec.decisionMatches is not empty", func() { - var remedyName string - var remedy *remedyv1alpha1.Remedy - var targetCluster string +var _ = framework.SerialDescribe("remedy testing", func() { + var remedyName string + var remedy *remedyv1alpha1.Remedy + var targetCluster string + ginkgo.Context("remedy.spec.decisionMatches is not empty", func() { ginkgo.BeforeEach(func() { targetCluster = framework.ClusterNames()[0] remedyName = remedyNamePrefix + rand.String(RandomStrLength) @@ -59,8 +61,8 @@ var _ = ginkgo.Describe("remedy testing", func() { karmadaresource.CreateRemedy(karmadaClient, remedy) }) - ginkgo.It("The domain name resolution function of the cluster encounters an exception and recover", func() { - ginkgo.By("update cluster ServiceDomainNameResolutionReady condition to false", func() { + ginkgo.It("Cluster domain name resolution function encounters an exception and recover", func() { + ginkgo.By(fmt.Sprintf("update Cluster(%s) %s condition to false", targetCluster, remedyv1alpha1.ServiceDomainNameResolutionReady), func() { clusterObj, err := karmadaClient.ClusterV1alpha1().Clusters().Get(context.TODO(), targetCluster, metav1.GetOptions{}) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) @@ -74,32 +76,115 @@ var _ = ginkgo.Describe("remedy testing", func() { ginkgo.By("wait cluster status has TrafficControl RemedyAction", func() { framework.WaitClusterFitWith(controlPlaneClient, targetCluster, func(cluster *clusterv1alpha1.Cluster) bool { - for _, action := range cluster.Status.RemedyActions { - if action == string(remedyv1alpha1.TrafficControl) { - return true - } - } - return false + actions := sets.NewString(cluster.Status.RemedyActions...) + return actions.Has(string(remedyv1alpha1.TrafficControl)) }) }) - ginkgo.By("recover cluster ServiceDomainNameResolutionReady to true", func() { + ginkgo.By(fmt.Sprintf("recover Cluster(%s) %s condition to true", targetCluster, remedyv1alpha1.ServiceDomainNameResolutionReady), func() { clusterObj, err := karmadaClient.ClusterV1alpha1().Clusters().Get(context.TODO(), targetCluster, metav1.GetOptions{}) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) meta.SetStatusCondition(&clusterObj.Status.Conditions, metav1.Condition{ Type: string(remedyv1alpha1.ServiceDomainNameResolutionReady), - Status: metav1.ConditionFalse, + Status: metav1.ConditionTrue, }) _, err = karmadaClient.ClusterV1alpha1().Clusters().UpdateStatus(context.TODO(), clusterObj, metav1.UpdateOptions{}) gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) }) + + ginkgo.By("wait cluster status doesn't has TrafficControl RemedyAction", func() { + framework.WaitClusterFitWith(controlPlaneClient, targetCluster, func(cluster *clusterv1alpha1.Cluster) bool { + actions := sets.NewString(cluster.Status.RemedyActions...) + return !actions.Has(string(remedyv1alpha1.TrafficControl)) + }) + }) + + ginkgo.By("cleanup: remove Remedy resource", func() { + karmadaresource.RemoveRemedy(karmadaClient, remedyName) + }) }) - ginkgo.It("The domain name resolution function of the cluster encounters an exception, then remove the remedy resource", func() {}) + ginkgo.It("Cluster domain name resolution function encounters an exception, then remove the remedy resource", func() { + ginkgo.By(fmt.Sprintf("update Cluster(%s) %s condition to false", targetCluster, remedyv1alpha1.ServiceDomainNameResolutionReady), func() { + clusterObj, err := karmadaClient.ClusterV1alpha1().Clusters().Get(context.TODO(), targetCluster, metav1.GetOptions{}) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + + meta.SetStatusCondition(&clusterObj.Status.Conditions, metav1.Condition{ + Type: string(remedyv1alpha1.ServiceDomainNameResolutionReady), + Status: metav1.ConditionFalse, + }) + _, err = karmadaClient.ClusterV1alpha1().Clusters().UpdateStatus(context.TODO(), clusterObj, metav1.UpdateOptions{}) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + }) + + ginkgo.By("wait cluster status has TrafficControl RemedyAction", func() { + framework.WaitClusterFitWith(controlPlaneClient, targetCluster, func(cluster *clusterv1alpha1.Cluster) bool { + actions := sets.NewString(cluster.Status.RemedyActions...) + return actions.Has(string(remedyv1alpha1.TrafficControl)) + }) + }) + + ginkgo.By("remove Remedy resource", func() { + karmadaresource.RemoveRemedy(karmadaClient, remedyName) + }) + + ginkgo.By("wait cluster status doesn't has TrafficControl RemedyAction", func() { + framework.WaitClusterFitWith(controlPlaneClient, targetCluster, func(cluster *clusterv1alpha1.Cluster) bool { + actions := sets.NewString(cluster.Status.RemedyActions...) + return !actions.Has(string(remedyv1alpha1.TrafficControl)) + }) + }) + + ginkgo.By(fmt.Sprintf("cleanup: recover Cluster(%s) %s to true", targetCluster, remedyv1alpha1.ServiceDomainNameResolutionReady), func() { + clusterObj, err := karmadaClient.ClusterV1alpha1().Clusters().Get(context.TODO(), targetCluster, metav1.GetOptions{}) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + + meta.SetStatusCondition(&clusterObj.Status.Conditions, metav1.Condition{ + Type: string(remedyv1alpha1.ServiceDomainNameResolutionReady), + Status: metav1.ConditionTrue, + }) + _, err = karmadaClient.ClusterV1alpha1().Clusters().UpdateStatus(context.TODO(), clusterObj, metav1.UpdateOptions{}) + gomega.Expect(err).ShouldNot(gomega.HaveOccurred()) + }) + }) }) ginkgo.Context("test with nil decision matches remedy", func() { + ginkgo.BeforeEach(func() { + targetCluster = framework.ClusterNames()[0] + remedyName = remedyNamePrefix + rand.String(RandomStrLength) + remedy = &remedyv1alpha1.Remedy{ + ObjectMeta: metav1.ObjectMeta{Name: remedyName}, + Spec: remedyv1alpha1.RemedySpec{ + Actions: []remedyv1alpha1.RemedyAction{remedyv1alpha1.TrafficControl}, + }, + } + + }) + + ginkgo.It("Create an immediately type remedy, then remove it", func() { + ginkgo.By("create Remedy resource", func() { + karmadaresource.CreateRemedy(karmadaClient, remedy) + }) + + ginkgo.By("wait cluster status has TrafficControl RemedyAction", func() { + framework.WaitClusterFitWith(controlPlaneClient, targetCluster, func(cluster *clusterv1alpha1.Cluster) bool { + actions := sets.NewString(cluster.Status.RemedyActions...) + return actions.Has(string(remedyv1alpha1.TrafficControl)) + }) + }) + + ginkgo.By("remove Remedy resource", func() { + karmadaresource.RemoveRemedy(karmadaClient, remedyName) + }) + ginkgo.By("wait cluster status doesn't has TrafficControl RemedyAction", func() { + framework.WaitClusterFitWith(controlPlaneClient, targetCluster, func(cluster *clusterv1alpha1.Cluster) bool { + actions := sets.NewString(cluster.Status.RemedyActions...) + return !actions.Has(string(remedyv1alpha1.TrafficControl)) + }) + }) + }) }) })