karmada/test/e2e/propagationpolicy_test.go

1267 lines
51 KiB
Go

/*
Copyright 2020 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"
"encoding/json"
"fmt"
"time"
"github.com/onsi/ginkgo/v2"
"github.com/onsi/gomega"
appsv1 "k8s.io/api/apps/v1"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/rand"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/klog/v2"
"k8s.io/utils/ptr"
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
workv1alpha1 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha1"
workv1alpha2 "github.com/karmada-io/karmada/pkg/apis/work/v1alpha2"
"github.com/karmada-io/karmada/pkg/controllers/execution"
"github.com/karmada-io/karmada/pkg/events"
"github.com/karmada-io/karmada/pkg/util/helper"
"github.com/karmada-io/karmada/pkg/util/names"
"github.com/karmada-io/karmada/test/e2e/framework"
testhelper "github.com/karmada-io/karmada/test/helper"
)
// BasicPropagation focus on basic propagation functionality testing.
var _ = ginkgo.Describe("[BasicCase] PropagationPolicy testing", func() {
var policyNamespace, policyName string
var policy *policyv1alpha1.PropagationPolicy
ginkgo.JustBeforeEach(func() {
framework.CreatePropagationPolicy(karmadaClient, policy)
ginkgo.DeferCleanup(func() {
framework.RemovePropagationPolicy(karmadaClient, policy.Namespace, policy.Name)
})
})
ginkgo.Context("Deployment propagation testing", func() {
var deploymentNamespace, deploymentName string
var deployment *appsv1.Deployment
ginkgo.BeforeEach(func() {
policyNamespace = testNamespace
policyName = deploymentNamePrefix + rand.String(RandomStrLength)
deploymentNamespace = testNamespace
deploymentName = policyName
deployment = testhelper.NewDeployment(deploymentNamespace, deploymentName)
policy = testhelper.NewPropagationPolicy(policyNamespace, policyName, []policyv1alpha1.ResourceSelector{
{
APIVersion: deployment.APIVersion,
Kind: deployment.Kind,
Name: deployment.Name,
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: framework.ClusterNames(),
},
})
})
ginkgo.BeforeEach(func() {
framework.CreateDeployment(kubeClient, deployment)
ginkgo.DeferCleanup(func() {
framework.RemoveDeployment(kubeClient, deployment.Namespace, deployment.Name)
framework.WaitDeploymentDisappearOnClusters(framework.ClusterNames(), deployment.Namespace, deployment.Name)
})
})
ginkgo.It("deployment propagation testing", func() {
framework.WaitDeploymentPresentOnClustersFitWith(framework.ClusterNames(), deployment.Namespace, deployment.Name,
func(*appsv1.Deployment) bool {
return true
})
framework.UpdateDeploymentReplicas(kubeClient, deployment, updateDeploymentReplicas)
framework.WaitDeploymentPresentOnClustersFitWith(framework.ClusterNames(), deployment.Namespace, deployment.Name,
func(deployment *appsv1.Deployment) bool {
return *deployment.Spec.Replicas == updateDeploymentReplicas
})
})
ginkgo.It("adds dispatching event with a dispatching message", func() {
workName := names.GenerateWorkName(deployment.Kind, deployment.Name, deployment.Namespace)
esName := names.GenerateExecutionSpaceName(framework.ClusterNames()[0])
framework.WaitEventFitWith(kubeClient, esName, workName, func(event corev1.Event) bool {
return event.Reason == events.EventReasonWorkDispatching &&
event.Message == execution.WorkDispatchingConditionMessage
})
})
})
ginkgo.Context("Service propagation testing", func() {
var serviceNamespace, serviceName string
var service *corev1.Service
ginkgo.BeforeEach(func() {
policyNamespace = testNamespace
policyName = serviceNamePrefix + rand.String(RandomStrLength)
serviceNamespace = policyNamespace
serviceName = policyName
service = testhelper.NewService(serviceNamespace, serviceName, corev1.ServiceTypeClusterIP)
policy = testhelper.NewPropagationPolicy(policyNamespace, policyName, []policyv1alpha1.ResourceSelector{
{
APIVersion: service.APIVersion,
Kind: service.Kind,
Name: service.Name,
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: framework.ClusterNames(),
},
})
})
ginkgo.BeforeEach(func() {
framework.CreateService(kubeClient, service)
ginkgo.DeferCleanup(func() {
framework.RemoveService(kubeClient, service.Namespace, service.Name)
framework.WaitServiceDisappearOnClusters(framework.ClusterNames(), service.Namespace, service.Name)
})
})
ginkgo.It("service propagation testing", func() {
framework.WaitServicePresentOnClustersFitWith(framework.ClusterNames(), service.Namespace, service.Name,
func(*corev1.Service) bool {
return true
})
patch := []map[string]interface{}{{"op": "replace", "path": "/spec/ports/0/port", "value": updateServicePort}}
framework.UpdateServiceWithPatch(kubeClient, service.Namespace, service.Name, patch, types.JSONPatchType)
framework.WaitServicePresentOnClustersFitWith(framework.ClusterNames(), service.Namespace, service.Name,
func(service *corev1.Service) bool {
return service.Spec.Ports[0].Port == updateServicePort
})
})
})
ginkgo.Context("Pod propagation testing", func() {
var podNamespace, podName string
var pod *corev1.Pod
ginkgo.BeforeEach(func() {
policyNamespace = testNamespace
policyName = podNamePrefix + rand.String(RandomStrLength)
podNamespace = policyNamespace
podName = policyName
pod = testhelper.NewPod(podNamespace, podName)
policy = testhelper.NewPropagationPolicy(policyNamespace, policyName, []policyv1alpha1.ResourceSelector{
{
APIVersion: pod.APIVersion,
Kind: pod.Kind,
Name: pod.Name,
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: framework.ClusterNames(),
},
})
})
ginkgo.BeforeEach(func() {
framework.CreatePod(kubeClient, pod)
ginkgo.DeferCleanup(func() {
framework.RemovePod(kubeClient, pod.Namespace, pod.Name)
framework.WaitPodDisappearOnClusters(framework.ClusterNames(), pod.Namespace, pod.Name)
})
})
ginkgo.It("pod propagation testing", func() {
framework.WaitPodPresentOnClustersFitWith(framework.ClusterNames(), pod.Namespace, pod.Name,
func(*corev1.Pod) bool {
return true
})
patch := []map[string]interface{}{{"op": "replace", "path": "/spec/containers/0/image", "value": updatePodImage}}
framework.UpdatePodWithPatch(kubeClient, pod.Namespace, pod.Name, patch, types.JSONPatchType)
framework.WaitPodPresentOnClustersFitWith(framework.ClusterNames(), pod.Namespace, pod.Name,
func(pod *corev1.Pod) bool {
return pod.Spec.Containers[0].Image == updatePodImage
})
})
})
ginkgo.Context("NamespaceScoped CustomResource propagation testing", func() {
var crdGroup string
var randStr string
var crdSpecNames apiextensionsv1.CustomResourceDefinitionNames
var crd *apiextensionsv1.CustomResourceDefinition
var crdPolicy *policyv1alpha1.ClusterPropagationPolicy
var crNamespace, crName string
var crGVR schema.GroupVersionResource
var crAPIVersion string
var cr *unstructured.Unstructured
ginkgo.BeforeEach(func() {
crdGroup = fmt.Sprintf("example-%s.karmada.io", rand.String(RandomStrLength))
randStr = rand.String(RandomStrLength)
crdSpecNames = apiextensionsv1.CustomResourceDefinitionNames{
Kind: fmt.Sprintf("Foo%s", randStr),
ListKind: fmt.Sprintf("Foo%sList", randStr),
Plural: fmt.Sprintf("foo%ss", randStr),
Singular: fmt.Sprintf("foo%s", randStr),
}
crd = testhelper.NewCustomResourceDefinition(crdGroup, crdSpecNames, apiextensionsv1.NamespaceScoped)
crdPolicy = testhelper.NewClusterPropagationPolicy(crd.Name, []policyv1alpha1.ResourceSelector{
{
APIVersion: crd.APIVersion,
Kind: crd.Kind,
Name: crd.Name,
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: framework.ClusterNames(),
},
})
crNamespace = testNamespace
crName = crdNamePrefix + rand.String(RandomStrLength)
crGVR = schema.GroupVersionResource{Group: crd.Spec.Group, Version: "v1alpha1", Resource: crd.Spec.Names.Plural}
crAPIVersion = fmt.Sprintf("%s/%s", crd.Spec.Group, "v1alpha1")
cr = testhelper.NewCustomResource(crAPIVersion, crd.Spec.Names.Kind, crNamespace, crName)
policy = testhelper.NewPropagationPolicy(crNamespace, crName, []policyv1alpha1.ResourceSelector{
{
APIVersion: crAPIVersion,
Kind: crd.Spec.Names.Kind,
Name: crName,
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: framework.ClusterNames(),
},
})
})
ginkgo.BeforeEach(func() {
framework.CreateClusterPropagationPolicy(karmadaClient, crdPolicy)
framework.CreateCRD(dynamicClient, crd)
framework.WaitCRDPresentOnClusters(karmadaClient, framework.ClusterNames(),
fmt.Sprintf("%s/%s", crd.Spec.Group, "v1alpha1"), crd.Spec.Names.Kind)
ginkgo.DeferCleanup(func() {
framework.RemoveClusterPropagationPolicy(karmadaClient, crdPolicy.Name)
framework.RemoveCRD(dynamicClient, crd.Name)
})
})
ginkgo.It("namespaceScoped cr propagation testing", func() {
ginkgo.By(fmt.Sprintf("creating cr(%s/%s)", crNamespace, crName), func() {
_, err := dynamicClient.Resource(crGVR).Namespace(crNamespace).Create(context.TODO(), cr, metav1.CreateOptions{})
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
})
ginkgo.By("check if cr present on member clusters", func() {
for _, cluster := range framework.Clusters() {
clusterDynamicClient := framework.GetClusterDynamicClient(cluster.Name)
gomega.Expect(clusterDynamicClient).ShouldNot(gomega.BeNil())
klog.Infof("Waiting for cr(%s/%s) present on cluster(%s)", crNamespace, crName, cluster.Name)
err := wait.PollUntilContextTimeout(context.TODO(), pollInterval, pollTimeout, true, func(ctx context.Context) (done bool, err error) {
_, err = clusterDynamicClient.Resource(crGVR).Namespace(crNamespace).Get(ctx, crName, metav1.GetOptions{})
if err != nil {
if apierrors.IsNotFound(err) {
return false, nil
}
return false, err
}
return true, nil
})
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
}
})
ginkgo.By("updating cr", func() {
patch := []map[string]interface{}{
{
"op": "replace",
"path": "/spec/resource/namespace",
"value": updateCRnamespace,
},
}
bytes, err := json.Marshal(patch)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
_, err = dynamicClient.Resource(crGVR).Namespace(crNamespace).Patch(context.TODO(), crName, types.JSONPatchType, bytes, metav1.PatchOptions{})
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
})
ginkgo.By("check if update has been synced to member clusters", func() {
for _, cluster := range framework.Clusters() {
clusterDynamicClient := framework.GetClusterDynamicClient(cluster.Name)
gomega.Expect(clusterDynamicClient).ShouldNot(gomega.BeNil())
klog.Infof("Waiting for cr(%s/%s) synced on cluster(%s)", crNamespace, crName, cluster.Name)
err := wait.PollUntilContextTimeout(context.TODO(), pollInterval, pollTimeout, true, func(ctx context.Context) (done bool, err error) {
cr, err := clusterDynamicClient.Resource(crGVR).Namespace(crNamespace).Get(ctx, crName, metav1.GetOptions{})
if err != nil {
return false, err
}
namespace, found, err := unstructured.NestedString(cr.Object, "spec", "resource", "namespace")
if err != nil || !found {
return false, err
}
if namespace == updateCRnamespace {
return true, nil
}
return false, nil
})
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
}
})
ginkgo.By(fmt.Sprintf("removing cr(%s/%s)", crNamespace, crName), func() {
err := dynamicClient.Resource(crGVR).Namespace(crNamespace).Delete(context.TODO(), crName, metav1.DeleteOptions{})
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
})
ginkgo.By("check if cr has been deleted from member clusters", func() {
for _, cluster := range framework.Clusters() {
clusterDynamicClient := framework.GetClusterDynamicClient(cluster.Name)
gomega.Expect(clusterDynamicClient).ShouldNot(gomega.BeNil())
klog.Infof("Waiting for cr(%s/%s) disappear on cluster(%s)", crNamespace, crName, cluster.Name)
err := wait.PollUntilContextTimeout(context.TODO(), pollInterval, pollTimeout, true, func(ctx context.Context) (done bool, err error) {
_, err = clusterDynamicClient.Resource(crGVR).Namespace(crNamespace).Get(ctx, crName, metav1.GetOptions{})
if err != nil {
if apierrors.IsNotFound(err) {
return true, nil
}
return false, err
}
return false, nil
})
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
}
})
})
})
ginkgo.Context("Job propagation testing", func() {
var jobNamespace, jobName string
var job *batchv1.Job
ginkgo.BeforeEach(func() {
policyNamespace = testNamespace
policyName = jobNamePrefix + rand.String(RandomStrLength)
jobNamespace = testNamespace
jobName = policyName
job = testhelper.NewJob(jobNamespace, jobName)
policy = testhelper.NewPropagationPolicy(policyNamespace, policyName, []policyv1alpha1.ResourceSelector{
{
APIVersion: job.APIVersion,
Kind: job.Kind,
Name: job.Name,
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: framework.ClusterNames(),
},
})
})
ginkgo.BeforeEach(func() {
framework.CreateJob(kubeClient, job)
ginkgo.DeferCleanup(func() {
framework.RemoveJob(kubeClient, job.Namespace, job.Name)
framework.WaitJobDisappearOnClusters(framework.ClusterNames(), job.Namespace, job.Name)
})
})
ginkgo.It("job propagation testing", func() {
framework.WaitJobPresentOnClustersFitWith(framework.ClusterNames(), job.Namespace, job.Name,
func(*batchv1.Job) bool {
return true
})
patch := []map[string]interface{}{{"op": "replace", "path": "/spec/backoffLimit", "value": ptr.To[int32](updateBackoffLimit)}}
bytes, err := json.Marshal(patch)
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
framework.UpdateJobWithPatchBytes(kubeClient, job.Namespace, job.Name, bytes, types.JSONPatchType)
framework.WaitJobPresentOnClustersFitWith(framework.ClusterNames(), job.Namespace, job.Name,
func(job *batchv1.Job) bool {
return *job.Spec.BackoffLimit == updateBackoffLimit
})
})
})
ginkgo.Context("Role propagation testing", func() {
var (
roleNamespace, roleName string
role *rbacv1.Role
)
ginkgo.BeforeEach(func() {
roleNamespace = testNamespace
policyName = roleNamePrefix + rand.String(RandomStrLength)
roleName = fmt.Sprintf("system:test:%s", policyName)
role = testhelper.NewRole(roleNamespace, roleName, nil)
policy = testhelper.NewPropagationPolicy(roleNamespace, policyName, []policyv1alpha1.ResourceSelector{
{
APIVersion: role.APIVersion,
Kind: role.Kind,
Name: role.Name,
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: framework.ClusterNames(),
},
})
})
ginkgo.BeforeEach(func() {
framework.CreateRole(kubeClient, role)
ginkgo.DeferCleanup(func() {
framework.RemoveRole(kubeClient, role.Namespace, role.Name)
framework.WaitRoleDisappearOnClusters(framework.ClusterNames(), role.Namespace, role.Name)
})
})
ginkgo.It("role propagation testing", func() {
framework.WaitRolePresentOnClustersFitWith(framework.ClusterNames(), role.Namespace, role.Name,
func(*rbacv1.Role) bool {
return true
})
})
})
ginkgo.Context("RoleBinding propagation testing", func() {
var (
roleBindingNamespace, roleBindingName string
roleBinding *rbacv1.RoleBinding
)
ginkgo.BeforeEach(func() {
roleBindingNamespace = testNamespace
policyName = roleBindingNamePrefix + rand.String(RandomStrLength)
roleBindingName = fmt.Sprintf("system:test.%s", policyName)
roleBinding = testhelper.NewRoleBinding(roleBindingNamespace, roleBindingName, roleBindingName, nil)
policy = testhelper.NewPropagationPolicy(roleBindingNamespace, policyName, []policyv1alpha1.ResourceSelector{
{
APIVersion: roleBinding.APIVersion,
Kind: roleBinding.Kind,
Name: roleBinding.Name,
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: framework.ClusterNames(),
},
})
})
ginkgo.BeforeEach(func() {
framework.CreateRoleBinding(kubeClient, roleBinding)
ginkgo.DeferCleanup(func() {
framework.RemoveRoleBinding(kubeClient, roleBinding.Namespace, roleBinding.Name)
framework.WaitRoleBindingDisappearOnClusters(framework.ClusterNames(), roleBinding.Namespace, roleBinding.Name)
})
})
ginkgo.It("roleBinding propagation testing", func() {
framework.WaitRoleBindingPresentOnClustersFitWith(framework.ClusterNames(), roleBinding.Namespace, roleBinding.Name,
func(*rbacv1.RoleBinding) bool {
return true
})
})
})
})
var _ = ginkgo.Describe("[CornerCase] PropagationPolicy testing", func() {
var policyNamespace, policyName string
var policy *policyv1alpha1.PropagationPolicy
ginkgo.JustBeforeEach(func() {
framework.CreatePropagationPolicy(karmadaClient, policy)
ginkgo.DeferCleanup(func() {
framework.RemovePropagationPolicy(karmadaClient, policy.Namespace, policy.Name)
})
})
ginkgo.Context("Propagate Deployment with long pp name (exceed 63 character)", func() {
var deploymentNamespace, deploymentName string
var deployment *appsv1.Deployment
ginkgo.BeforeEach(func() {
policyNamespace = testNamespace
policyName = deploymentNamePrefix + "-longname-longname-longname-longname-longname-longname-" + rand.String(RandomStrLength)
deploymentNamespace = testNamespace
deploymentName = policyName
deployment = testhelper.NewDeployment(deploymentNamespace, deploymentName)
policy = testhelper.NewPropagationPolicy(policyNamespace, policyName, []policyv1alpha1.ResourceSelector{
{
APIVersion: deployment.APIVersion,
Kind: deployment.Kind,
Name: deployment.Name,
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: framework.ClusterNames(),
},
})
})
ginkgo.BeforeEach(func() {
framework.CreateDeployment(kubeClient, deployment)
ginkgo.DeferCleanup(func() {
framework.RemoveDeployment(kubeClient, deployment.Namespace, deployment.Name)
framework.WaitDeploymentDisappearOnClusters(framework.ClusterNames(), deployment.Namespace, deployment.Name)
})
})
ginkgo.It("deployment propagation testing", func() {
framework.WaitDeploymentPresentOnClustersFitWith(framework.ClusterNames(), deployment.Namespace, deployment.Name,
func(*appsv1.Deployment) bool {
return true
})
framework.UpdateDeploymentReplicas(kubeClient, deployment, updateDeploymentReplicas)
framework.WaitDeploymentPresentOnClustersFitWith(framework.ClusterNames(), deployment.Namespace, deployment.Name,
func(deployment *appsv1.Deployment) bool {
return *deployment.Spec.Replicas == updateDeploymentReplicas
})
})
})
})
// ImplicitPriority more than one PP matches the object, we should choose the most suitable one.
// Set it to run sequentially to avoid affecting other test cases.
var _ = framework.SerialDescribe("[ImplicitPriority] PropagationPolicy testing", func() {
ginkgo.Context("priorityMatchName propagation testing", func() {
var policyNamespace, priorityMatchName, priorityMatchLabelSelector, priorityMatchAll string
var deploymentNamespace, deploymentName string
var deployment *appsv1.Deployment
var policyMatchName, policyMatchLabelSelector, policyPriorityMatchAll *policyv1alpha1.PropagationPolicy
var implicitPriorityLabelKey = "priority"
var implicitPriorityLabelValue = "implicit-priority"
ginkgo.BeforeEach(func() {
policyNamespace = testNamespace
priorityMatchName = deploymentNamePrefix + rand.String(RandomStrLength)
priorityMatchLabelSelector = deploymentNamePrefix + rand.String(RandomStrLength)
priorityMatchAll = deploymentNamePrefix + rand.String(RandomStrLength)
deploymentNamespace = testNamespace
deploymentName = deploymentNamePrefix + rand.String(RandomStrLength)
deployment = testhelper.NewDeployment(deploymentNamespace, deploymentName)
deployment.SetLabels(map[string]string{implicitPriorityLabelKey: implicitPriorityLabelValue})
policyMatchName = testhelper.NewPropagationPolicy(policyNamespace, priorityMatchName, []policyv1alpha1.ResourceSelector{
{
APIVersion: deployment.APIVersion,
Kind: deployment.Kind,
Name: deployment.Name,
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: framework.ClusterNames(),
},
})
policyMatchLabelSelector = testhelper.NewPropagationPolicy(policyNamespace, priorityMatchLabelSelector, []policyv1alpha1.ResourceSelector{
{
APIVersion: deployment.APIVersion,
Kind: deployment.Kind,
LabelSelector: metav1.SetAsLabelSelector(labels.Set{implicitPriorityLabelKey: implicitPriorityLabelValue}),
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: framework.ClusterNames(),
},
})
policyPriorityMatchAll = testhelper.NewPropagationPolicy(policyNamespace, priorityMatchAll, []policyv1alpha1.ResourceSelector{
{
APIVersion: deployment.APIVersion,
Kind: deployment.Kind,
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: framework.ClusterNames(),
},
})
})
ginkgo.BeforeEach(func() {
framework.CreatePropagationPolicy(karmadaClient, policyMatchName)
framework.CreatePropagationPolicy(karmadaClient, policyMatchLabelSelector)
framework.CreatePropagationPolicy(karmadaClient, policyPriorityMatchAll)
framework.CreateDeployment(kubeClient, deployment)
ginkgo.DeferCleanup(func() {
framework.RemoveDeployment(kubeClient, deployment.Namespace, deployment.Name)
framework.WaitDeploymentDisappearOnClusters(framework.ClusterNames(), deployment.Namespace, deployment.Name)
})
})
ginkgo.It("priorityMatchName/priorityMatchLabel/priorityMatchAll testing", func() {
ginkgo.By("check whether the deployment uses the highest priority propagationPolicy (priorityMatchName)", func() {
defer framework.RemovePropagationPolicy(karmadaClient, policyMatchLabelSelector.Namespace, policyMatchName.Name)
framework.WaitDeploymentPresentOnClustersFitWith(framework.ClusterNames(), deployment.Namespace, deployment.Name,
func(deployment *appsv1.Deployment) bool {
return deployment.GetAnnotations()[policyv1alpha1.PropagationPolicyNameAnnotation] == priorityMatchName
})
})
ginkgo.By("check whether the deployment uses the highest priority propagationPolicy (priorityMatchLabel)", func() {
defer framework.RemovePropagationPolicy(karmadaClient, policyMatchLabelSelector.Namespace, policyMatchLabelSelector.Name)
framework.WaitDeploymentPresentOnClustersFitWith(framework.ClusterNames(), deployment.Namespace, deployment.Name,
func(deployment *appsv1.Deployment) bool {
return deployment.GetAnnotations()[policyv1alpha1.PropagationPolicyNameAnnotation] == priorityMatchLabelSelector
})
})
ginkgo.By("check whether the deployment uses the highest priority propagationPolicy (priorityMatchAll)", func() {
defer framework.RemovePropagationPolicy(karmadaClient, policyMatchLabelSelector.Namespace, policyPriorityMatchAll.Name)
framework.WaitDeploymentPresentOnClustersFitWith(framework.ClusterNames(), deployment.Namespace, deployment.Name,
func(deployment *appsv1.Deployment) bool {
return deployment.GetAnnotations()[policyv1alpha1.PropagationPolicyNameAnnotation] == priorityMatchAll
})
})
})
})
})
// ExplicitPriority more than one PP matches the object, we should select the one with the highest explicit priority, if the
// explicit priority is same, select the one with the highest implicit priority.
var _ = ginkgo.Describe("[ExplicitPriority] PropagationPolicy testing", func() {
ginkgo.Context("high explicit/low priority/implicit priority PropagationPolicy propagation testing", func() {
var policyNamespace, higherPriorityLabelSelector, lowerPriorityMatchName, implicitPriorityMatchName string
var deploymentNamespace, deploymentName string
var deployment *appsv1.Deployment
var policyHigherPriorityLabelSelector, policyLowerPriorityMatchMatchName, policyImplicitPriorityMatchMatchName *policyv1alpha1.PropagationPolicy
ginkgo.BeforeEach(func() {
policyNamespace = testNamespace
higherPriorityLabelSelector = deploymentNamePrefix + "higherprioritylabelselector" + rand.String(RandomStrLength)
lowerPriorityMatchName = deploymentNamePrefix + "lowerprioritymatchame" + rand.String(RandomStrLength)
implicitPriorityMatchName = deploymentNamePrefix + "implicitprioritymatchname" + rand.String(RandomStrLength)
deploymentNamespace = testNamespace
deploymentName = deploymentNamePrefix + rand.String(RandomStrLength)
var priorityLabelKey = "priority"
var priorityLabelValue = "priority" + rand.String(RandomStrLength)
deployment = testhelper.NewDeployment(deploymentNamespace, deploymentName)
deployment.SetLabels(map[string]string{priorityLabelKey: priorityLabelValue})
policyHigherPriorityLabelSelector = testhelper.NewExplicitPriorityPropagationPolicy(policyNamespace, higherPriorityLabelSelector, []policyv1alpha1.ResourceSelector{
{
APIVersion: deployment.APIVersion,
Kind: deployment.Kind,
LabelSelector: metav1.SetAsLabelSelector(labels.Set{priorityLabelKey: priorityLabelValue}),
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: framework.ClusterNames(),
},
}, 2)
policyLowerPriorityMatchMatchName = testhelper.NewExplicitPriorityPropagationPolicy(policyNamespace, lowerPriorityMatchName, []policyv1alpha1.ResourceSelector{
{
APIVersion: deployment.APIVersion,
Kind: deployment.Kind,
Name: deployment.Name,
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: framework.ClusterNames(),
},
}, 1)
policyImplicitPriorityMatchMatchName = testhelper.NewPropagationPolicy(policyNamespace, implicitPriorityMatchName, []policyv1alpha1.ResourceSelector{
{
APIVersion: deployment.APIVersion,
Kind: deployment.Kind,
Name: deployment.Name,
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: framework.ClusterNames(),
},
})
})
ginkgo.BeforeEach(func() {
framework.CreatePropagationPolicy(karmadaClient, policyHigherPriorityLabelSelector)
framework.CreatePropagationPolicy(karmadaClient, policyLowerPriorityMatchMatchName)
framework.CreatePropagationPolicy(karmadaClient, policyImplicitPriorityMatchMatchName)
// Wait till the informer's cache is synced in karmada-controller.
// Note: We tested and find that it takes about 1s before cache synced.
time.Sleep(time.Second * 5)
framework.CreateDeployment(kubeClient, deployment)
ginkgo.DeferCleanup(func() {
framework.RemoveDeployment(kubeClient, deployment.Namespace, deployment.Name)
framework.WaitDeploymentDisappearOnClusters(framework.ClusterNames(), deployment.Namespace, deployment.Name)
})
ginkgo.DeferCleanup(func() {
framework.RemovePropagationPolicy(karmadaClient, policyHigherPriorityLabelSelector.Namespace, policyHigherPriorityLabelSelector.Name)
framework.RemovePropagationPolicy(karmadaClient, policyLowerPriorityMatchMatchName.Namespace, policyLowerPriorityMatchMatchName.Name)
})
})
ginkgo.It("high explicit/low priority/implicit priority PropagationPolicy propagation testing", func() {
ginkgo.By("check whether the deployment uses the highest explicit priority PropagationPolicy", func() {
framework.WaitDeploymentPresentOnClustersFitWith(framework.ClusterNames(), deployment.Namespace, deployment.Name,
func(deployment *appsv1.Deployment) bool {
klog.Infof("Match PropagationPolicy:%s/%s", deployment.GetAnnotations()[policyv1alpha1.PropagationPolicyNamespaceAnnotation],
deployment.GetAnnotations()[policyv1alpha1.PropagationPolicyNameAnnotation])
return deployment.GetAnnotations()[policyv1alpha1.PropagationPolicyNameAnnotation] == higherPriorityLabelSelector
})
})
})
})
ginkgo.Context("same explicit priority PropagationPolicy propagation testing", func() {
var policyNamespace, explicitPriorityLabelSelector, explicitPriorityMatchName string
var deploymentNamespace, deploymentName string
var deployment *appsv1.Deployment
var policyExplicitPriorityLabelSelector, policyExplicitPriorityMatchName *policyv1alpha1.PropagationPolicy
ginkgo.BeforeEach(func() {
policyNamespace = testNamespace
explicitPriorityLabelSelector = deploymentNamePrefix + "explicitprioritylabelselector" + rand.String(RandomStrLength)
explicitPriorityMatchName = deploymentNamePrefix + "explicitprioritymatchname" + rand.String(RandomStrLength)
deploymentNamespace = testNamespace
deploymentName = deploymentNamePrefix + rand.String(RandomStrLength)
var priorityLabelKey = "priority"
var priorityLabelValue = "priority" + rand.String(RandomStrLength)
deployment = testhelper.NewDeployment(deploymentNamespace, deploymentName)
deployment.SetLabels(map[string]string{priorityLabelKey: priorityLabelValue})
policyExplicitPriorityLabelSelector = testhelper.NewExplicitPriorityPropagationPolicy(policyNamespace, explicitPriorityLabelSelector, []policyv1alpha1.ResourceSelector{
{
APIVersion: deployment.APIVersion,
Kind: deployment.Kind,
LabelSelector: metav1.SetAsLabelSelector(labels.Set{priorityLabelKey: priorityLabelValue}),
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: framework.ClusterNames(),
},
}, 1)
policyExplicitPriorityMatchName = testhelper.NewExplicitPriorityPropagationPolicy(policyNamespace, explicitPriorityMatchName, []policyv1alpha1.ResourceSelector{
{
APIVersion: deployment.APIVersion,
Kind: deployment.Kind,
Name: deployment.Name,
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: framework.ClusterNames(),
},
}, 1)
})
ginkgo.BeforeEach(func() {
framework.CreatePropagationPolicy(karmadaClient, policyExplicitPriorityLabelSelector)
framework.CreatePropagationPolicy(karmadaClient, policyExplicitPriorityMatchName)
// Wait till the informer's cache is synced in karmada-controller.
// Note: We tested and find that it takes about 1s before cache synced.
time.Sleep(time.Second * 5)
framework.CreateDeployment(kubeClient, deployment)
ginkgo.DeferCleanup(func() {
framework.RemoveDeployment(kubeClient, deployment.Namespace, deployment.Name)
framework.WaitDeploymentDisappearOnClusters(framework.ClusterNames(), deployment.Namespace, deployment.Name)
})
ginkgo.DeferCleanup(func() {
framework.RemovePropagationPolicy(karmadaClient, policyExplicitPriorityLabelSelector.Namespace, policyExplicitPriorityLabelSelector.Name)
framework.RemovePropagationPolicy(karmadaClient, policyExplicitPriorityMatchName.Namespace, policyExplicitPriorityMatchName.Name)
})
})
ginkgo.It("same explicit priority PropagationPolicy propagation testing", func() {
ginkgo.By("check whether the deployment uses the PropagationPolicy with name matched", func() {
framework.WaitDeploymentPresentOnClustersFitWith(framework.ClusterNames(), deployment.Namespace, deployment.Name,
func(deployment *appsv1.Deployment) bool {
klog.Infof("Match PropagationPolicy:%s/%s", deployment.GetAnnotations()[policyv1alpha1.PropagationPolicyNamespaceAnnotation],
deployment.GetAnnotations()[policyv1alpha1.PropagationPolicyNameAnnotation])
return deployment.GetAnnotations()[policyv1alpha1.PropagationPolicyNameAnnotation] == explicitPriorityMatchName
})
})
})
})
})
// AdvancedPropagation focus on some advanced propagation testing.
var _ = ginkgo.Describe("[AdvancedCase] PropagationPolicy testing", func() {
ginkgo.Context("Edit PropagationPolicy ResourceSelectors", func() {
var policy *policyv1alpha1.PropagationPolicy
var deployment01, deployment02 *appsv1.Deployment
var targetMember string
ginkgo.BeforeEach(func() {
targetMember = framework.ClusterNames()[0]
policyNamespace := testNamespace
policyName := deploymentNamePrefix + rand.String(RandomStrLength)
deployment01 = testhelper.NewDeployment(testNamespace, policyName+"01")
deployment02 = testhelper.NewDeployment(testNamespace, policyName+"02")
policy = testhelper.NewPropagationPolicy(policyNamespace, policyName, []policyv1alpha1.ResourceSelector{
{
APIVersion: deployment01.APIVersion,
Kind: deployment01.Kind,
Name: deployment01.Name,
}}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: []string{targetMember},
},
})
})
ginkgo.BeforeEach(func() {
framework.CreatePropagationPolicy(karmadaClient, policy)
framework.CreateDeployment(kubeClient, deployment01)
framework.CreateDeployment(kubeClient, deployment02)
ginkgo.DeferCleanup(func() {
framework.RemovePropagationPolicy(karmadaClient, policy.Namespace, policy.Name)
framework.RemoveDeployment(kubeClient, deployment01.Namespace, deployment01.Name)
framework.RemoveDeployment(kubeClient, deployment02.Namespace, deployment02.Name)
})
framework.WaitDeploymentPresentOnClusterFitWith(targetMember, deployment01.Namespace, deployment01.Name,
func(*appsv1.Deployment) bool { return true })
})
ginkgo.It("add resourceSelectors item", func() {
policy.Spec.ResourceSelectors = []policyv1alpha1.ResourceSelector{
{
APIVersion: deployment01.APIVersion,
Kind: deployment01.Kind,
Name: deployment01.Name,
},
{
APIVersion: deployment02.APIVersion,
Kind: deployment02.Kind,
Name: deployment02.Name,
},
}
framework.UpdatePropagationPolicyWithSpec(karmadaClient, policy.Namespace, policy.Name, policy.Spec)
framework.WaitDeploymentPresentOnClusterFitWith(targetMember, deployment02.Namespace, deployment02.Name,
func(*appsv1.Deployment) bool { return true })
})
ginkgo.It("update resourceSelectors item", func() {
policySpec := policyv1alpha1.PropagationSpec{
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: deployment02.APIVersion,
Kind: deployment02.Kind,
Name: deployment02.Name,
},
},
}
framework.UpdatePropagationPolicyWithSpec(karmadaClient, policy.Namespace, policy.Name, policySpec)
framework.WaitDeploymentPresentOnClusterFitWith(targetMember, deployment02.Namespace, deployment02.Name,
func(*appsv1.Deployment) bool { return true })
framework.WaitDeploymentGetByClientFitWith(kubeClient, deployment01.Namespace, deployment01.Name,
func(deployment *appsv1.Deployment) bool {
if deployment.Annotations == nil {
return true
}
_, namespaceExist := deployment.Annotations[policyv1alpha1.PropagationPolicyNamespaceAnnotation]
_, nameExist := deployment.Annotations[policyv1alpha1.PropagationPolicyNameAnnotation]
if namespaceExist || nameExist {
return false
}
return true
})
})
})
ginkgo.Context("Edit PropagationPolicy fields other than resourceSelectors", func() {
var policy *policyv1alpha1.PropagationPolicy
var deployment *appsv1.Deployment
var targetMember, updatedMember string
ginkgo.BeforeEach(func() {
targetMember = framework.ClusterNames()[0]
updatedMember = framework.ClusterNames()[1]
policyNamespace := testNamespace
policyName := deploymentNamePrefix + rand.String(RandomStrLength)
deployment = testhelper.NewDeployment(testNamespace, policyName+"01")
policy = testhelper.NewPropagationPolicy(policyNamespace, policyName, []policyv1alpha1.ResourceSelector{
{
APIVersion: deployment.APIVersion,
Kind: deployment.Kind,
Name: deployment.Name,
}}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: []string{targetMember},
},
})
})
ginkgo.BeforeEach(func() {
framework.CreatePropagationPolicy(karmadaClient, policy)
framework.CreateDeployment(kubeClient, deployment)
ginkgo.DeferCleanup(func() {
framework.RemovePropagationPolicy(karmadaClient, policy.Namespace, policy.Name)
framework.RemoveDeployment(kubeClient, deployment.Namespace, deployment.Name)
})
gomega.Eventually(func() bool {
observedPolicy, err := karmadaClient.PolicyV1alpha1().PropagationPolicies(policy.Namespace).Get(context.TODO(), policy.Name, metav1.GetOptions{})
if err != nil {
return false
}
bindings, err := karmadaClient.WorkV1alpha2().ResourceBindings(testNamespace).List(context.TODO(), metav1.ListOptions{
LabelSelector: labels.SelectorFromSet(labels.Set{
policyv1alpha1.PropagationPolicyPermanentIDLabel: observedPolicy.Labels[policyv1alpha1.PropagationPolicyPermanentIDLabel],
}).String(),
})
if err != nil {
return false
}
return len(bindings.Items) != 0
}, pollTimeout, pollInterval).Should(gomega.Equal(true))
})
ginkgo.It("update policy propagateDeps", func() {
patch := []map[string]interface{}{
{
"op": "replace",
"path": "/spec/propagateDeps",
"value": true,
},
}
framework.PatchPropagationPolicy(karmadaClient, policy.Namespace, policy.Name, patch, types.JSONPatchType)
gomega.Eventually(func() bool {
observedPolicy, err := karmadaClient.PolicyV1alpha1().PropagationPolicies(policy.Namespace).Get(context.TODO(), policy.Name, metav1.GetOptions{})
if err != nil {
return false
}
bindings, err := karmadaClient.WorkV1alpha2().ResourceBindings(testNamespace).List(context.TODO(), metav1.ListOptions{
LabelSelector: labels.SelectorFromSet(labels.Set{
policyv1alpha1.PropagationPolicyPermanentIDLabel: observedPolicy.Labels[policyv1alpha1.PropagationPolicyPermanentIDLabel],
}).String(),
})
if err != nil {
return false
}
return bindings.Items[0].Spec.PropagateDeps == true
}, pollTimeout, pollInterval).Should(gomega.Equal(true))
})
ginkgo.It("update policy placement", func() {
updatedPlacement := policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: []string{updatedMember},
}}
patch := []map[string]interface{}{
{
"op": "replace",
"path": "/spec/placement",
"value": updatedPlacement,
},
}
framework.PatchPropagationPolicy(karmadaClient, policy.Namespace, policy.Name, patch, types.JSONPatchType)
framework.WaitDeploymentDisappearOnCluster(targetMember, deployment.Namespace, deployment.Name)
framework.WaitDeploymentPresentOnClusterFitWith(updatedMember, deployment.Namespace, deployment.Name,
func(*appsv1.Deployment) bool { return true })
})
})
ginkgo.Context("Delete the propagationPolicy", func() {
var policy *policyv1alpha1.PropagationPolicy
var deployment *appsv1.Deployment
var targetMember string
ginkgo.BeforeEach(func() {
targetMember = framework.ClusterNames()[0]
policyNamespace := testNamespace
policyName := deploymentNamePrefix + rand.String(RandomStrLength)
deployment = testhelper.NewDeployment(testNamespace, policyName+"01")
policy = testhelper.NewPropagationPolicy(policyNamespace, policyName, []policyv1alpha1.ResourceSelector{
{
APIVersion: deployment.APIVersion,
Kind: deployment.Kind,
Name: deployment.Name,
}}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: []string{targetMember},
},
})
})
ginkgo.BeforeEach(func() {
framework.CreatePropagationPolicy(karmadaClient, policy)
framework.CreateDeployment(kubeClient, deployment)
ginkgo.DeferCleanup(func() {
// PropagationPolicy will be removed in subsequent test cases
framework.RemoveDeployment(kubeClient, deployment.Namespace, deployment.Name)
})
gomega.Eventually(func() bool {
observedPolicy, err := karmadaClient.PolicyV1alpha1().PropagationPolicies(policy.Namespace).Get(context.TODO(), policy.Name, metav1.GetOptions{})
if err != nil {
return false
}
bindings, err := karmadaClient.WorkV1alpha2().ResourceBindings(testNamespace).List(context.TODO(), metav1.ListOptions{
LabelSelector: labels.SelectorFromSet(labels.Set{
policyv1alpha1.PropagationPolicyPermanentIDLabel: observedPolicy.Labels[policyv1alpha1.PropagationPolicyPermanentIDLabel],
}).String(),
})
if err != nil {
return false
}
return len(bindings.Items) != 0
}, pollTimeout, pollInterval).Should(gomega.Equal(true))
})
ginkgo.It("delete the propagationPolicy and check whether labels and annotations are deleted correctly", func() {
framework.RemovePropagationPolicy(karmadaClient, policy.Namespace, policy.Name)
framework.WaitDeploymentFitWith(kubeClient, deployment.Namespace, deployment.Name, func(dep *appsv1.Deployment) bool {
if dep.Labels != nil && dep.Labels[policyv1alpha1.PropagationPolicyPermanentIDLabel] != "" {
return false
}
if dep.Annotations != nil && dep.Annotations[policyv1alpha1.PropagationPolicyNamespaceAnnotation] != "" && dep.Annotations[policyv1alpha1.PropagationPolicyNameAnnotation] != "" {
return false
}
return true
})
resourceBindingName := names.GenerateBindingName(deployment.Kind, deployment.Name)
framework.WaitResourceBindingFitWith(karmadaClient, deployment.Namespace, resourceBindingName, func(resourceBinding *workv1alpha2.ResourceBinding) bool {
if resourceBinding.Labels != nil && resourceBinding.Labels[policyv1alpha1.PropagationPolicyPermanentIDLabel] != "" {
return false
}
if resourceBinding.Annotations != nil && resourceBinding.Annotations[policyv1alpha1.PropagationPolicyNamespaceAnnotation] != "" && resourceBinding.Annotations[policyv1alpha1.PropagationPolicyNameAnnotation] != "" {
return false
}
return true
})
})
})
ginkgo.Context("Unbind the old PropagationPolicy and create a new one", func() {
var policy01, policy02 *policyv1alpha1.PropagationPolicy
var configmap *corev1.ConfigMap
var member1, member2 string
ginkgo.BeforeEach(func() {
member1 = framework.ClusterNames()[0]
member2 = framework.ClusterNames()[1]
policyNamespace := testNamespace
policyName := configMapNamePrefix + rand.String(RandomStrLength)
configmap = testhelper.NewConfigMap(testNamespace, policyName, map[string]string{"a": "b"})
configmap.ObjectMeta.Labels = map[string]string{"a": "b"}
policy01 = testhelper.NewPropagationPolicy(policyNamespace, policyName+"01", []policyv1alpha1.ResourceSelector{
{
APIVersion: configmap.APIVersion,
Kind: configmap.Kind,
Name: configmap.Name,
}}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: []string{member1},
},
})
policy02 = testhelper.NewPropagationPolicy(policyNamespace, policyName+"02", []policyv1alpha1.ResourceSelector{
{
APIVersion: configmap.APIVersion,
Kind: configmap.Kind,
Name: configmap.Name,
}}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: []string{member2},
},
})
})
ginkgo.BeforeEach(func() {
framework.CreateConfigMap(kubeClient, configmap)
ginkgo.DeferCleanup(func() {
framework.RemoveConfigMap(kubeClient, configmap.Namespace, configmap.Name)
framework.WaitConfigMapDisappearOnClusters(framework.ClusterNames(), configmap.Namespace, configmap.Name)
})
})
ginkgo.It("modify the old propagationPolicy to unbind and create a new one", func() {
framework.CreatePropagationPolicy(karmadaClient, policy01)
framework.WaitConfigMapPresentOnClusterFitWith(member1, configmap.Namespace, configmap.Name,
func(*corev1.ConfigMap) bool { return true })
framework.UpdatePropagationPolicyWithSpec(karmadaClient, policy01.Namespace, policy01.Name, policyv1alpha1.PropagationSpec{
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: configmap.APIVersion,
Kind: configmap.Kind,
Name: configmap.Name + "fake",
},
},
Placement: policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: []string{member1},
},
},
})
framework.CreatePropagationPolicy(karmadaClient, policy02)
framework.WaitConfigMapDisappearOnCluster(member1, configmap.Namespace, configmap.Name)
framework.WaitConfigMapPresentOnClusterFitWith(member2, configmap.Namespace, configmap.Name,
func(*corev1.ConfigMap) bool { return true })
framework.RemovePropagationPolicy(karmadaClient, policy01.Namespace, policy01.Name)
framework.RemovePropagationPolicy(karmadaClient, policy02.Namespace, policy02.Name)
})
ginkgo.It("delete the old propagationPolicy to unbind and create a new one", func() {
framework.CreatePropagationPolicy(karmadaClient, policy01)
framework.WaitConfigMapPresentOnClusterFitWith(member1, configmap.Namespace, configmap.Name,
func(*corev1.ConfigMap) bool { return true })
framework.RemovePropagationPolicy(karmadaClient, policy01.Namespace, policy01.Name)
framework.CreatePropagationPolicy(karmadaClient, policy02)
framework.WaitConfigMapDisappearOnCluster(member1, configmap.Namespace, configmap.Name)
framework.WaitConfigMapPresentOnClusterFitWith(member2, configmap.Namespace, configmap.Name,
func(*corev1.ConfigMap) bool { return true })
framework.RemovePropagationPolicy(karmadaClient, policy02.Namespace, policy02.Name)
})
})
})
var _ = ginkgo.Describe("[Suspension] PropagationPolicy testing", func() {
var policy *policyv1alpha1.PropagationPolicy
var deployment *appsv1.Deployment
var targetMember string
ginkgo.BeforeEach(func() {
targetMember = framework.ClusterNames()[0]
policyNamespace := testNamespace
policyName := deploymentNamePrefix + rand.String(RandomStrLength)
deployment = testhelper.NewDeployment(testNamespace, policyName+"01")
policy = testhelper.NewPropagationPolicy(policyNamespace, policyName, []policyv1alpha1.ResourceSelector{
{
APIVersion: deployment.APIVersion,
Kind: deployment.Kind,
Name: deployment.Name,
}}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: []string{targetMember},
},
})
})
ginkgo.BeforeEach(func() {
framework.CreatePropagationPolicy(karmadaClient, policy)
framework.CreateDeployment(kubeClient, deployment)
framework.WaitDeploymentPresentOnClusterFitWith(targetMember, deployment.Namespace, deployment.Name,
func(*appsv1.Deployment) bool {
return true
})
ginkgo.DeferCleanup(func() {
framework.RemovePropagationPolicy(karmadaClient, policy.Namespace, policy.Name)
framework.RemoveDeployment(kubeClient, deployment.Namespace, deployment.Name)
})
})
ginkgo.It("suspend the PP dispatching", func() {
ginkgo.By("update the pp suspension dispatching to true", func() {
policy.Spec.Suspension = &policyv1alpha1.Suspension{
Dispatching: ptr.To(true),
}
framework.UpdatePropagationPolicyWithSpec(karmadaClient, policy.Namespace, policy.Name, policy.Spec)
})
ginkgo.By("check RB suspension spec", func() {
framework.WaitResourceBindingFitWith(karmadaClient, deployment.Namespace, names.GenerateBindingName(deployment.Kind, deployment.Name),
func(binding *workv1alpha2.ResourceBinding) bool {
return binding.Spec.Suspension != nil && ptr.Deref(binding.Spec.Suspension.Dispatching, false)
})
})
ginkgo.By("check Work suspension spec", func() {
workName := names.GenerateWorkName(deployment.Kind, deployment.Name, deployment.Namespace)
esName := names.GenerateExecutionSpaceName(targetMember)
gomega.Eventually(func() bool {
work, err := karmadaClient.WorkV1alpha1().Works(esName).Get(context.TODO(), workName, metav1.GetOptions{})
if err != nil {
return false
}
return work != nil && helper.IsWorkSuspendDispatching(work)
}, pollTimeout, pollInterval).Should(gomega.Equal(true))
})
ginkgo.By("check Work Dispatching status condition", func() {
workName := names.GenerateWorkName(deployment.Kind, deployment.Name, deployment.Namespace)
esName := names.GenerateExecutionSpaceName(targetMember)
gomega.Eventually(func() bool {
work, err := karmadaClient.WorkV1alpha1().Works(esName).Get(context.TODO(), workName, metav1.GetOptions{})
if err != nil {
return false
}
return work != nil && meta.IsStatusConditionPresentAndEqual(work.Status.Conditions, workv1alpha1.WorkDispatching, metav1.ConditionFalse)
}, pollTimeout, pollInterval).Should(gomega.Equal(true))
})
ginkgo.By("check dispatching event", func() {
workName := names.GenerateWorkName(deployment.Kind, deployment.Name, deployment.Namespace)
esName := names.GenerateExecutionSpaceName(targetMember)
framework.WaitEventFitWith(kubeClient, esName, workName,
func(event corev1.Event) bool {
return event.Reason == events.EventReasonWorkDispatching &&
event.Message == execution.WorkSuspendDispatchingConditionMessage
})
})
})
ginkgo.It("suspension resume", func() {
ginkgo.By("update deployment replicas", func() {
framework.UpdateDeploymentReplicas(kubeClient, deployment, updateDeploymentReplicas)
})
ginkgo.By("resume the propagationPolicy", func() {
policy.Spec.Suspension = &policyv1alpha1.Suspension{}
framework.UpdatePropagationPolicyWithSpec(karmadaClient, policy.Namespace, policy.Name, policy.Spec)
})
ginkgo.By("check deployment replicas", func() {
framework.WaitDeploymentPresentOnClusterFitWith(targetMember, deployment.Namespace, deployment.Name,
func(d *appsv1.Deployment) bool {
return *d.Spec.Replicas == updateDeploymentReplicas
})
})
})
})