Skip to content

Commit

Permalink
test: add e2e test for seamless migration
Browse files Browse the repository at this point in the history
Signed-off-by: chaosi-zju <chaosi@zju.edu.cn>
  • Loading branch information
chaosi-zju committed Jul 26, 2023
1 parent 796a6ca commit 139832d
Showing 1 changed file with 247 additions and 0 deletions.
247 changes: 247 additions & 0 deletions test/e2e/seamless_migration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
package e2e

import (
"context"
"fmt"

"github.com/onsi/ginkgo/v2"
"github.com/onsi/gomega"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/rand"
"k8s.io/client-go/kubernetes"
"k8s.io/klog/v2"

policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
"github.com/karmada-io/karmada/pkg/util/names"
"github.com/karmada-io/karmada/test/e2e/framework"
"github.com/karmada-io/karmada/test/helper"
)

var _ = ginkgo.Describe("Seamless migration testing", func() {
var member1 string
var member1Client kubernetes.Interface

ginkgo.BeforeEach(func() {
member1 = "member1"
member1Client = framework.GetClusterClient(member1)
})

ginkgo.Context("Test migrate namespaced resource: Deployment", func() {
var deployment *appsv1.Deployment
var propagationPolicy *policyv1alpha1.PropagationPolicy
var bindingName string

ginkgo.BeforeEach(func() {
deployment = helper.NewDeployment(testNamespace, deploymentNamePrefix+rand.String(RandomStrLength))
propagationPolicy = helper.NewPropagationPolicy(deployment.Namespace, deployment.Name, []policyv1alpha1.ResourceSelector{
{
APIVersion: deployment.APIVersion,
Kind: deployment.Kind,
Name: deployment.Name,
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{ClusterNames: []string{member1}},
})
bindingName = names.GenerateBindingName(deployment.Kind, deployment.Name)
})

ginkgo.AfterEach(func() {
framework.RemoveDeployment(kubeClient, deployment.Namespace, deployment.Name)
framework.RemovePropagationPolicy(karmadaClient, propagationPolicy.Namespace, propagationPolicy.Name)

ginkgo.By("Verify Deployment in member cluster will be deleted automatically after promotion since it be deleted from Karmada", func() {
klog.Infof("Waiting for Deployment deleted from cluster(%s)", member1)
gomega.Eventually(func() bool {
_, err := member1Client.AppsV1().Deployments(deployment.Namespace).Get(context.TODO(), deployment.Name, metav1.GetOptions{})
return err != nil && apierrors.IsNotFound(err)
}, pollTimeout, pollInterval).Should(gomega.Equal(true))
})
})

// referring to related manual steps: https://github.com/karmada-io/karmada/pull/3821#issuecomment-1649238940
ginkgo.It("Test migrate a Deployment from member cluster", func() {
// Step 1, Create Deployment in member1 cluster
ginkgo.By("Creating Deployment in member1 cluster", func() {
framework.CreateDeployment(member1Client, deployment)
})

// Step 2, Create Deployment in karmada control plane
ginkgo.By("Creating Deployment in karmada control plane", func() {
framework.CreateDeployment(kubeClient, deployment)
})

// Step 3, Create PropagationPolicy in karmada control plane without conflictResolution field
ginkgo.By("Creating PropagationPolicy in karmada control plane without conflictResolution field", func() {
framework.CreatePropagationPolicy(karmadaClient, propagationPolicy)
})

// Step 4, Verify ResourceBinding got unHealthy for resource already exist
ginkgo.By(fmt.Sprintf("Verify ResourceBinding %s got unApplied for resource already exist", bindingName), func() {
klog.Infof("Waiting to verify ResourceBinding %s got unApplied for resource already exist", bindingName)
gomega.Eventually(func() bool {
binding, err := karmadaClient.WorkV1alpha2().ResourceBindings(deployment.Namespace).Get(context.TODO(), bindingName, metav1.GetOptions{})
if err != nil && apierrors.IsNotFound(err) {
return false
}
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())

items := binding.Status.AggregatedStatus
return len(items) > 0 && items[0].Applied == false && items[0].Health != workv1alpha2.ResourceHealthy
}, pollTimeout, pollInterval).Should(gomega.Equal(true))
})

// Step 5, Update PropagationPolicy in karmada control plane with conflictResolution=Overwrite
ginkgo.By(fmt.Sprintf("Update PropagationPolicy %s in karmada control plane with conflictResolution=Overwrite", propagationPolicy.Name), func() {
propagationPolicy.Spec.ConflictResolution = policyv1alpha1.ConflictOverwrite
framework.UpdatePropagationPolicyWithSpec(karmadaClient, propagationPolicy.Namespace, propagationPolicy.Name, propagationPolicy.Spec)
})

// Step 6, Verify Deployment Replicas all ready and ResourceBinding got Healthy for overwriting conflict resource
ginkgo.By(fmt.Sprintf("Verify Deployment Replicas all ready and ResourceBinding %s got Healthy for overwriting conflict resource", bindingName), func() {
klog.Infof("Waiting for Deployment ready on Karmada control plane")
gomega.Eventually(func() bool {
updatedDeploy, err := kubeClient.AppsV1().Deployments(deployment.Namespace).Get(context.TODO(), deployment.Name, metav1.GetOptions{})
return err == nil && updatedDeploy.Status.ReadyReplicas == *updatedDeploy.Spec.Replicas
}, pollTimeout, pollInterval).Should(gomega.Equal(true))

binding, err := karmadaClient.WorkV1alpha2().ResourceBindings(deployment.Namespace).Get(context.TODO(), bindingName, metav1.GetOptions{})
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())

items := binding.Status.AggregatedStatus
gomega.Expect(len(items)).ShouldNot(gomega.Equal(0))
gomega.Expect(items[0].Applied).Should(gomega.BeTrue())
gomega.Expect(items[0].Health).Should(gomega.Equal(workv1alpha2.ResourceHealthy))
})
})
})

ginkgo.Context("Test migrate cluster resources: ClusterRole", func() {
var clusterRoleName string
var clusterRole *rbacv1.ClusterRole
var cpp *policyv1alpha1.ClusterPropagationPolicy
var bindingName string

ginkgo.BeforeEach(func() {
clusterRoleName = fmt.Sprintf("test-clusterrole-%s", rand.String(RandomStrLength))
clusterRole = helper.NewClusterRole(clusterRoleName, []rbacv1.PolicyRule{
{
APIGroups: []string{"cluster.karmada.io"},
Verbs: []string{"*"},
Resources: []string{"clusters/proxy"},
ResourceNames: []string{member1},
},
})
cpp = helper.NewClusterPropagationPolicy(clusterRole.Name, []policyv1alpha1.ResourceSelector{
{
APIVersion: clusterRole.APIVersion,
Kind: clusterRole.Kind,
Name: clusterRole.Name,
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{ClusterNames: []string{member1}},
})
bindingName = names.GenerateBindingName(clusterRole.Kind, clusterRole.Name)
})

ginkgo.AfterEach(func() {
framework.RemoveClusterRole(kubeClient, clusterRoleName)
framework.RemoveClusterPropagationPolicy(karmadaClient, cpp.Name)

ginkgo.By("Verify ClusterRole in member cluster will be deleted automatically after promotion since it be deleted from Karmada", func() {
klog.Infof("Waiting for ClusterRole deleted from cluster(%s)", member1)
gomega.Eventually(func() bool {
_, err := member1Client.RbacV1().ClusterRoles().Get(context.TODO(), clusterRoleName, metav1.GetOptions{})
return err != nil && apierrors.IsNotFound(err)
}, pollTimeout, pollInterval).Should(gomega.Equal(true))
})
})

ginkgo.It("Test migrate a ClusterRole from member cluster", func() {
ginkgo.By("Creating ClusterRole in member1 cluster and karmada control plane", func() {
framework.CreateClusterRole(member1Client, clusterRole)
framework.CreateClusterRole(kubeClient, clusterRole)
})

ginkgo.By("Creating ClusterPropagationPolicy in karmada control plane with conflictResolution=Overwrite", func() {
cpp.Spec.ConflictResolution = policyv1alpha1.ConflictOverwrite
framework.CreateClusterPropagationPolicy(karmadaClient, cpp)
})

ginkgo.By(fmt.Sprintf("Verify ClusterResourceBinding %s got Applied by overwriting conflict resource", bindingName), func() {
klog.Infof("Waiting to verify ResourceBinding %s got Applied by overwriting conflict resource", bindingName)
gomega.Eventually(func() bool {
_, e1 := member1Client.RbacV1().ClusterRoles().Get(context.TODO(), clusterRoleName, metav1.GetOptions{})
_, e2 := kubeClient.RbacV1().ClusterRoles().Get(context.TODO(), clusterRoleName, metav1.GetOptions{})

binding, e3 := karmadaClient.WorkV1alpha2().ClusterResourceBindings().Get(context.TODO(), bindingName, metav1.GetOptions{})

return e1 == nil && e2 == nil && e3 == nil && len(binding.Status.AggregatedStatus) > 0 && binding.Status.AggregatedStatus[0].Applied
}, pollTimeout, pollInterval).Should(gomega.Equal(true))
})
})
})

ginkgo.Context("Test migrate namespaced resource: Service (NodePort)", func() {
var serviceName string
var service *corev1.Service
var pp *policyv1alpha1.PropagationPolicy
var bindingName string

ginkgo.BeforeEach(func() {
serviceName = serviceNamePrefix + rand.String(RandomStrLength)
service = helper.NewService(testNamespace, serviceName, corev1.ServiceTypeNodePort)
pp = helper.NewPropagationPolicy(testNamespace, service.Name, []policyv1alpha1.ResourceSelector{
{
APIVersion: service.APIVersion,
Kind: service.Kind,
Name: service.Name,
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{ClusterNames: []string{member1}},
})
bindingName = names.GenerateBindingName(service.Kind, service.Name)
})

ginkgo.AfterEach(func() {
framework.RemoveService(kubeClient, testNamespace, serviceName)
framework.RemovePropagationPolicy(karmadaClient, testNamespace, pp.Name)

ginkgo.By("Verify Service in member cluster will be deleted automatically after promotion since it be deleted from Karmada", func() {
klog.Infof("Waiting for Service deleted from cluster(%s)", member1)
gomega.Eventually(func() bool {
_, err := member1Client.CoreV1().Services(testNamespace).Get(context.TODO(), serviceName, metav1.GetOptions{})
return err != nil && apierrors.IsNotFound(err)
}, pollTimeout, pollInterval).Should(gomega.Equal(true))
})
})

ginkgo.It("Test migrate a Service from member cluster", func() {
ginkgo.By("Creating Service in member1 cluster and karmada control plane", func() {
framework.CreateService(member1Client, service)
framework.CreateService(kubeClient, service)
})

ginkgo.By("Creating PropagationPolicy in karmada control plane with conflictResolution=Overwrite", func() {
pp.Spec.ConflictResolution = policyv1alpha1.ConflictOverwrite
framework.CreatePropagationPolicy(karmadaClient, pp)
})

ginkgo.By(fmt.Sprintf("Verify PropagationPolicy %s got Applied by overwriting conflict resource", bindingName), func() {
klog.Infof("Waiting to verify ResourceBinding %s got Applied by overwriting conflict resource", bindingName)
gomega.Eventually(func() bool {
_, e1 := member1Client.CoreV1().Services(testNamespace).Get(context.TODO(), serviceName, metav1.GetOptions{})
_, e2 := kubeClient.CoreV1().Services(testNamespace).Get(context.TODO(), serviceName, metav1.GetOptions{})

binding, e3 := karmadaClient.WorkV1alpha2().ResourceBindings(testNamespace).Get(context.TODO(), bindingName, metav1.GetOptions{})

return e1 == nil && e2 == nil && e3 == nil && len(binding.Status.AggregatedStatus) > 0 && binding.Status.AggregatedStatus[0].Applied
}, pollTimeout, pollInterval).Should(gomega.Equal(true))
})
})
})
})

0 comments on commit 139832d

Please sign in to comment.