Implement priority of PropagationPolicy/ClusterPropagationPolicy

Signed-off-by: jwcesign <jiangwei115@huawei.com>
This commit is contained in:
jwcesign 2022-11-09 16:23:03 +08:00 committed by jwcesign
parent 3cbae40434
commit 4c6fc6e367
6 changed files with 989 additions and 22 deletions

View File

@ -1,6 +1,8 @@
package detector
import (
"math"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/klog/v2"
@ -9,15 +11,32 @@ import (
"github.com/karmada-io/karmada/pkg/util/fedinformer/keys"
)
func getHighestPriorityPropagationPolicies(policies []*policyv1alpha1.PropagationPolicy, resource *unstructured.Unstructured, objectKey keys.ClusterWideKey) *policyv1alpha1.PropagationPolicy {
func getHighestPriorityPropagationPolicy(policies []*policyv1alpha1.PropagationPolicy, resource *unstructured.Unstructured, objectKey keys.ClusterWideKey) *policyv1alpha1.PropagationPolicy {
matchedPolicyImplicitPriority := util.PriorityMisMatch
matchedPolicyExplicitPriority := int32(math.MinInt32)
var matchedPolicy *policyv1alpha1.PropagationPolicy
matchedPolicyPriority := util.PriorityMisMatch
for _, policy := range policies {
if p := util.ResourceMatchSelectorsPriority(resource, policy.Spec.ResourceSelectors...); p > matchedPolicyPriority {
implicitPriority := util.ResourceMatchSelectorsPriority(resource, policy.Spec.ResourceSelectors...)
if implicitPriority <= util.PriorityMisMatch {
continue
}
explicitPriority := policy.ExplicitPriority()
if matchedPolicyExplicitPriority < explicitPriority {
matchedPolicyImplicitPriority = implicitPriority
matchedPolicyExplicitPriority = explicitPriority
matchedPolicy = policy
matchedPolicyPriority = p
} else if p > util.PriorityMisMatch && p == matchedPolicyPriority {
matchedPolicy = getHigherPriorityPropagationPolicy(matchedPolicy, policy)
continue
}
if matchedPolicyExplicitPriority == explicitPriority {
if implicitPriority > matchedPolicyImplicitPriority {
matchedPolicyImplicitPriority = implicitPriority
matchedPolicy = policy
} else if implicitPriority == matchedPolicyImplicitPriority {
matchedPolicy = getHigherPriorityPropagationPolicy(matchedPolicy, policy)
}
}
}
@ -29,15 +48,32 @@ func getHighestPriorityPropagationPolicies(policies []*policyv1alpha1.Propagatio
return matchedPolicy
}
func getHighestPriorityClusterPropagationPolicies(policies []*policyv1alpha1.ClusterPropagationPolicy, resource *unstructured.Unstructured, objectKey keys.ClusterWideKey) *policyv1alpha1.ClusterPropagationPolicy {
func getHighestPriorityClusterPropagationPolicy(policies []*policyv1alpha1.ClusterPropagationPolicy, resource *unstructured.Unstructured, objectKey keys.ClusterWideKey) *policyv1alpha1.ClusterPropagationPolicy {
matchedClusterPolicyImplicitPriority := util.PriorityMisMatch
matchedClusterPolicyExplicitPriority := int32(math.MinInt32)
var matchedClusterPolicy *policyv1alpha1.ClusterPropagationPolicy
matchedClusterPolicyPriority := util.PriorityMisMatch
for _, policy := range policies {
if p := util.ResourceMatchSelectorsPriority(resource, policy.Spec.ResourceSelectors...); p > matchedClusterPolicyPriority {
implicitPriority := util.ResourceMatchSelectorsPriority(resource, policy.Spec.ResourceSelectors...)
if implicitPriority <= util.PriorityMisMatch {
continue
}
explicitPriority := policy.ExplicitPriority()
if matchedClusterPolicyExplicitPriority < explicitPriority {
matchedClusterPolicyImplicitPriority = implicitPriority
matchedClusterPolicyExplicitPriority = explicitPriority
matchedClusterPolicy = policy
matchedClusterPolicyPriority = p
} else if p > util.PriorityMisMatch && p == matchedClusterPolicyPriority {
matchedClusterPolicy = getHigherPriorityClusterPropagationPolicy(matchedClusterPolicy, policy)
continue
}
if matchedClusterPolicyExplicitPriority == explicitPriority {
if implicitPriority > matchedClusterPolicyImplicitPriority {
matchedClusterPolicyImplicitPriority = implicitPriority
matchedClusterPolicy = policy
} else if implicitPriority == matchedClusterPolicyImplicitPriority {
matchedClusterPolicy = getHigherPriorityClusterPropagationPolicy(matchedClusterPolicy, policy)
}
}
}

View File

@ -260,7 +260,7 @@ func Test_getHighestPriorityPropagationPolicies(t *testing.T) {
want: nil,
},
{
name: "different priority policy",
name: "different implicit priority policy",
args: args{
policies: []*policyv1alpha1.PropagationPolicy{
{
@ -321,7 +321,7 @@ func Test_getHighestPriorityPropagationPolicies(t *testing.T) {
},
},
{
name: "same priority policy",
name: "same implicit priority policy",
args: args{
policies: []*policyv1alpha1.PropagationPolicy{
{
@ -371,11 +371,314 @@ func Test_getHighestPriorityPropagationPolicies(t *testing.T) {
}}},
},
},
{
name: "one policy with implicit priority, one policy with explicit priority 1",
args: args{
policies: []*policyv1alpha1.PropagationPolicy{
{
ObjectMeta: metav1.ObjectMeta{Name: "a-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Name: "nginx",
Namespace: "test",
}}},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "b-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(1)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Name: "nginx",
Namespace: "test",
}}},
},
},
resource: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "nginx",
"namespace": "test",
"labels": map[string]interface{}{
"app": "nginx",
}}}},
objectKey: keys.ClusterWideKey{Kind: "Deployment", Namespace: "test", Name: "nginx"},
},
want: &policyv1alpha1.PropagationPolicy{
ObjectMeta: metav1.ObjectMeta{Name: "b-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(1)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Name: "nginx",
Namespace: "test",
}}},
},
},
{
name: "one policy with explicit priority 1(name match), one policy with explicit priority 2(label selector match)",
args: args{
policies: []*policyv1alpha1.PropagationPolicy{
{
ObjectMeta: metav1.ObjectMeta{Name: "a-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(1)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Name: "nginx",
Namespace: "test",
}}},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "b-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(2)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Namespace: "test",
LabelSelector: &metav1.LabelSelector{MatchLabels: map[string]string{"app": "nginx"}},
}}},
},
},
resource: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "nginx",
"namespace": "test",
"labels": map[string]interface{}{
"app": "nginx",
}}}},
objectKey: keys.ClusterWideKey{Kind: "Deployment", Namespace: "test", Name: "nginx"},
},
want: &policyv1alpha1.PropagationPolicy{
ObjectMeta: metav1.ObjectMeta{Name: "b-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(2)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Namespace: "test",
LabelSelector: &metav1.LabelSelector{MatchLabels: map[string]string{"app": "nginx"}},
}}},
},
},
{
name: "two policies with explicit priority 1(name match), select the one with lower alphabetical order",
args: args{
policies: []*policyv1alpha1.PropagationPolicy{
{
ObjectMeta: metav1.ObjectMeta{Name: "a-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(1)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Name: "nginx",
Namespace: "test",
}}},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "b-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(1)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Namespace: "test",
Name: "nginx",
}}},
},
},
resource: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "nginx",
"namespace": "test",
"labels": map[string]interface{}{
"app": "nginx",
}}}},
objectKey: keys.ClusterWideKey{Kind: "Deployment", Namespace: "test", Name: "nginx"},
},
want: &policyv1alpha1.PropagationPolicy{
ObjectMeta: metav1.ObjectMeta{Name: "a-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(1)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Namespace: "test",
Name: "nginx",
}}},
},
},
{
name: "one policy with explicit priority 1(name match), one policy with explicit priority 1(label selector match)",
args: args{
policies: []*policyv1alpha1.PropagationPolicy{
{
ObjectMeta: metav1.ObjectMeta{Name: "a-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(1)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Namespace: "test",
LabelSelector: &metav1.LabelSelector{MatchLabels: map[string]string{"app": "nginx"}},
}}},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "b-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(1)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Namespace: "test",
Name: "nginx",
}}},
},
},
resource: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "nginx",
"namespace": "test",
"labels": map[string]interface{}{
"app": "nginx",
}}}},
objectKey: keys.ClusterWideKey{Kind: "Deployment", Namespace: "test", Name: "nginx"},
},
want: &policyv1alpha1.PropagationPolicy{
ObjectMeta: metav1.ObjectMeta{Name: "b-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(1)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Namespace: "test",
Name: "nginx",
}}},
},
},
{
name: "one policy with explicit priority -1(name match), one policy with implicit priority(label selector match)",
args: args{
policies: []*policyv1alpha1.PropagationPolicy{
{
ObjectMeta: metav1.ObjectMeta{Name: "a-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Namespace: "test",
LabelSelector: &metav1.LabelSelector{MatchLabels: map[string]string{"app": "nginx"}},
}}},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "b-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(-1)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Namespace: "test",
Name: "nginx",
}}},
},
},
resource: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "nginx",
"namespace": "test",
"labels": map[string]interface{}{
"app": "nginx",
}}}},
objectKey: keys.ClusterWideKey{Kind: "Deployment", Namespace: "test", Name: "nginx"},
},
want: &policyv1alpha1.PropagationPolicy{
ObjectMeta: metav1.ObjectMeta{Name: "a-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Namespace: "test",
LabelSelector: &metav1.LabelSelector{MatchLabels: map[string]string{"app": "nginx"}},
}}},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := getHighestPriorityPropagationPolicies(tt.args.policies, tt.args.resource, tt.args.objectKey); !reflect.DeepEqual(got, tt.want) {
t.Errorf("getHighestPriorityPropagationPolicies() = %v, want %v", got, tt.want)
if got := getHighestPriorityPropagationPolicy(tt.args.policies, tt.args.resource, tt.args.objectKey); !reflect.DeepEqual(got, tt.want) {
t.Errorf("getHighestPriorityPropagationPolicy() = %v, want %v", got, tt.want)
}
})
}
@ -452,7 +755,7 @@ func Test_getHighestPriorityClusterPropagationPolicies(t *testing.T) {
want: nil,
},
{
name: "different priority policy",
name: "different implicit priority policy",
args: args{
policies: []*policyv1alpha1.ClusterPropagationPolicy{
{
@ -513,7 +816,7 @@ func Test_getHighestPriorityClusterPropagationPolicies(t *testing.T) {
},
},
{
name: "same priority policy",
name: "same implicit priority policy",
args: args{
policies: []*policyv1alpha1.ClusterPropagationPolicy{
{
@ -563,11 +866,314 @@ func Test_getHighestPriorityClusterPropagationPolicies(t *testing.T) {
}}},
},
},
{
name: "one policy with implicit priority, one policy with explicit priority 1",
args: args{
policies: []*policyv1alpha1.ClusterPropagationPolicy{
{
ObjectMeta: metav1.ObjectMeta{Name: "a-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Name: "nginx",
Namespace: "test",
}}},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "b-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(1)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Name: "nginx",
Namespace: "test",
}}},
},
},
resource: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "nginx",
"namespace": "test",
"labels": map[string]interface{}{
"app": "nginx",
}}}},
objectKey: keys.ClusterWideKey{Kind: "Deployment", Namespace: "test", Name: "nginx"},
},
want: &policyv1alpha1.ClusterPropagationPolicy{
ObjectMeta: metav1.ObjectMeta{Name: "b-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(1)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Name: "nginx",
Namespace: "test",
}}},
},
},
{
name: "one policy with explicit priority 1(name match), one policy with explicit priority 2(label selector match)",
args: args{
policies: []*policyv1alpha1.ClusterPropagationPolicy{
{
ObjectMeta: metav1.ObjectMeta{Name: "a-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(1)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Name: "nginx",
Namespace: "test",
}}},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "b-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(2)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Namespace: "test",
LabelSelector: &metav1.LabelSelector{MatchLabels: map[string]string{"app": "nginx"}},
}}},
},
},
resource: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "nginx",
"namespace": "test",
"labels": map[string]interface{}{
"app": "nginx",
}}}},
objectKey: keys.ClusterWideKey{Kind: "Deployment", Namespace: "test", Name: "nginx"},
},
want: &policyv1alpha1.ClusterPropagationPolicy{
ObjectMeta: metav1.ObjectMeta{Name: "b-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(2)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Namespace: "test",
LabelSelector: &metav1.LabelSelector{MatchLabels: map[string]string{"app": "nginx"}},
}}},
},
},
{
name: "two policies with explicit priority 1(name match), select the one with lower alphabetical order",
args: args{
policies: []*policyv1alpha1.ClusterPropagationPolicy{
{
ObjectMeta: metav1.ObjectMeta{Name: "a-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(1)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Name: "nginx",
Namespace: "test",
}}},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "b-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(1)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Namespace: "test",
Name: "nginx",
}}},
},
},
resource: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "nginx",
"namespace": "test",
"labels": map[string]interface{}{
"app": "nginx",
}}}},
objectKey: keys.ClusterWideKey{Kind: "Deployment", Namespace: "test", Name: "nginx"},
},
want: &policyv1alpha1.ClusterPropagationPolicy{
ObjectMeta: metav1.ObjectMeta{Name: "a-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(1)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Namespace: "test",
Name: "nginx",
}}},
},
},
{
name: "one policy with explicit priority 1(name match), one policy with explicit priority 1(label selector match)",
args: args{
policies: []*policyv1alpha1.ClusterPropagationPolicy{
{
ObjectMeta: metav1.ObjectMeta{Name: "a-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(1)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Namespace: "test",
LabelSelector: &metav1.LabelSelector{MatchLabels: map[string]string{"app": "nginx"}},
}}},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "b-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(1)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Namespace: "test",
Name: "nginx",
}}},
},
},
resource: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "nginx",
"namespace": "test",
"labels": map[string]interface{}{
"app": "nginx",
}}}},
objectKey: keys.ClusterWideKey{Kind: "Deployment", Namespace: "test", Name: "nginx"},
},
want: &policyv1alpha1.ClusterPropagationPolicy{
ObjectMeta: metav1.ObjectMeta{Name: "b-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(1)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Namespace: "test",
Name: "nginx",
}}},
},
},
{
name: "one policy with explicit priority -1(name match), one policy with implicit priority(label selector match)",
args: args{
policies: []*policyv1alpha1.ClusterPropagationPolicy{
{
ObjectMeta: metav1.ObjectMeta{Name: "a-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Namespace: "test",
LabelSelector: &metav1.LabelSelector{MatchLabels: map[string]string{"app": "nginx"}},
}}},
},
{
ObjectMeta: metav1.ObjectMeta{Name: "b-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
Priority: func() *int32 {
p := int32(-1)
return &p
}(),
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Namespace: "test",
Name: "nginx",
}}},
},
},
resource: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "nginx",
"namespace": "test",
"labels": map[string]interface{}{
"app": "nginx",
}}}},
objectKey: keys.ClusterWideKey{Kind: "Deployment", Namespace: "test", Name: "nginx"},
},
want: &policyv1alpha1.ClusterPropagationPolicy{
ObjectMeta: metav1.ObjectMeta{Name: "a-pp", Namespace: "test"},
Spec: policyv1alpha1.PropagationSpec{
ResourceSelectors: []policyv1alpha1.ResourceSelector{
{
APIVersion: "apps/v1",
Kind: "Deployment",
Namespace: "test",
LabelSelector: &metav1.LabelSelector{MatchLabels: map[string]string{"app": "nginx"}},
}}},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := getHighestPriorityClusterPropagationPolicies(tt.args.policies, tt.args.resource, tt.args.objectKey); !reflect.DeepEqual(got, tt.want) {
t.Errorf("getHighestPriorityClusterPropagationPolicies() = %v, want %v", got, tt.want)
if got := getHighestPriorityClusterPropagationPolicy(tt.args.policies, tt.args.resource, tt.args.objectKey); !reflect.DeepEqual(got, tt.want) {
t.Errorf("getHighestPriorityPropagationPolicies() = %v, want %v", got, tt.want)
}
})
}

View File

@ -337,7 +337,7 @@ func (d *ResourceDetector) LookForMatchedPolicy(object *unstructured.Unstructure
policyList = append(policyList, policy)
}
return getHighestPriorityPropagationPolicies(policyList, object, objectKey), nil
return getHighestPriorityPropagationPolicy(policyList, object, objectKey), nil
}
// LookForMatchedClusterPolicy tries to find a ClusterPropagationPolicy for object referenced by object key.
@ -363,7 +363,7 @@ func (d *ResourceDetector) LookForMatchedClusterPolicy(object *unstructured.Unst
policyList = append(policyList, policy)
}
return getHighestPriorityClusterPropagationPolicies(policyList, object, objectKey), nil
return getHighestPriorityClusterPropagationPolicy(policyList, object, objectKey), nil
}
// ApplyPolicy starts propagate the object referenced by object key according to PropagationPolicy.

View File

@ -7,6 +7,8 @@ import (
appsv1 "k8s.io/api/apps/v1"
rbacv1 "k8s.io/api/rbac/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/util/rand"
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
@ -318,3 +320,148 @@ var _ = ginkgo.Describe("[AdvancedClusterPropagation] propagation testing", func
})
})
})
// ExplicitPriority more than one CPP 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] propagation testing", func() {
ginkgo.Context("high explicit/low priority/implicit priority ClusterPropagationPolicy propagation testing", func() {
var higherPriorityLabelSelector, lowerPriorityMatchName, implicitPriorityMatchName string
var deploymentNamespace, deploymentName string
var deployment *appsv1.Deployment
var policyHigherPriorityLabelSelector, policyLowerPriorityMatchName, policyImplicitPriorityMatchName *policyv1alpha1.ClusterPropagationPolicy
var priorityLabelKey = "priority"
var priorityLabelValue = "priority"
ginkgo.BeforeEach(func() {
higherPriorityLabelSelector = deploymentNamePrefix + rand.String(RandomStrLength)
lowerPriorityMatchName = deploymentNamePrefix + rand.String(RandomStrLength)
implicitPriorityMatchName = deploymentNamePrefix + rand.String(RandomStrLength)
deploymentNamespace = testNamespace
deploymentName = deploymentNamePrefix + rand.String(RandomStrLength)
deployment = testhelper.NewDeployment(deploymentNamespace, deploymentName)
deployment.SetLabels(map[string]string{priorityLabelKey: priorityLabelValue})
policyHigherPriorityLabelSelector = testhelper.NewExplicitPriorityClusterPropagationPolicy(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)
policyLowerPriorityMatchName = testhelper.NewExplicitPriorityClusterPropagationPolicy(lowerPriorityMatchName, []policyv1alpha1.ResourceSelector{
{
APIVersion: deployment.APIVersion,
Kind: deployment.Kind,
Name: deployment.Name,
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: framework.ClusterNames(),
},
}, 1)
policyImplicitPriorityMatchName = testhelper.NewClusterPropagationPolicy(implicitPriorityMatchName, []policyv1alpha1.ResourceSelector{
{
APIVersion: deployment.APIVersion,
Kind: deployment.Kind,
Name: deployment.Name,
},
}, policyv1alpha1.Placement{
ClusterAffinity: &policyv1alpha1.ClusterAffinity{
ClusterNames: framework.ClusterNames(),
},
})
})
ginkgo.BeforeEach(func() {
framework.CreateClusterPropagationPolicy(karmadaClient, policyHigherPriorityLabelSelector)
framework.CreateClusterPropagationPolicy(karmadaClient, policyLowerPriorityMatchName)
framework.CreateClusterPropagationPolicy(karmadaClient, policyImplicitPriorityMatchName)
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.RemoveClusterPropagationPolicy(karmadaClient, policyHigherPriorityLabelSelector.Name)
framework.RemoveClusterPropagationPolicy(karmadaClient, policyLowerPriorityMatchName.Name)
})
})
ginkgo.It("high explicit/low priority/implicit priority ClusterPropagationPolicy testing", func() {
ginkgo.By("check whether the deployment uses the highest explicit priority ClusterPropagationPolicy", func() {
framework.WaitDeploymentPresentOnClustersFitWith(framework.ClusterNames(), deployment.Namespace, deployment.Name,
func(deployment *appsv1.Deployment) bool {
return deployment.GetLabels()[policyv1alpha1.ClusterPropagationPolicyLabel] == higherPriorityLabelSelector
})
})
})
})
ginkgo.Context("same explicit priority ClusterPropagationPolicy propagation testing", func() {
var explicitPriorityLabelSelector, explicitPriorityMatchName string
var deploymentNamespace, deploymentName string
var deployment *appsv1.Deployment
var policyExplicitPriorityLabelSelector, policyExplicitPriorityMatchName *policyv1alpha1.ClusterPropagationPolicy
var priorityLabelKey = "priority"
var priorityLabelValue = "priority"
ginkgo.BeforeEach(func() {
explicitPriorityLabelSelector = deploymentNamePrefix + rand.String(RandomStrLength)
explicitPriorityMatchName = deploymentNamePrefix + rand.String(RandomStrLength)
deploymentNamespace = testNamespace
deploymentName = deploymentNamePrefix + rand.String(RandomStrLength)
deployment = testhelper.NewDeployment(deploymentNamespace, deploymentName)
deployment.SetLabels(map[string]string{priorityLabelKey: priorityLabelValue})
policyExplicitPriorityLabelSelector = testhelper.NewExplicitPriorityClusterPropagationPolicy(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.NewExplicitPriorityClusterPropagationPolicy(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.CreateClusterPropagationPolicy(karmadaClient, policyExplicitPriorityLabelSelector)
framework.CreateClusterPropagationPolicy(karmadaClient, policyExplicitPriorityMatchName)
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.RemoveClusterPropagationPolicy(karmadaClient, policyExplicitPriorityLabelSelector.Name)
framework.RemoveClusterPropagationPolicy(karmadaClient, policyExplicitPriorityMatchName.Name)
})
})
ginkgo.It("same explicit priority ClusterPropagationPolicy propagation testing", func() {
ginkgo.By("check whether the deployment uses the ClusterPropagationPolicy with name matched", func() {
framework.WaitDeploymentPresentOnClustersFitWith(framework.ClusterNames(), deployment.Namespace, deployment.Name,
func(deployment *appsv1.Deployment) bool {
return deployment.GetLabels()[policyv1alpha1.ClusterPropagationPolicyLabel] == explicitPriorityMatchName
})
})
})
})
})

View File

@ -691,6 +691,153 @@ var _ = ginkgo.Describe("[ImplicitPriority] propagation testing", func() {
})
})
// 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] propagation 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
var priorityLabelKey = "priority"
var priorityLabelValue = "priority"
ginkgo.BeforeEach(func() {
policyNamespace = testNamespace
higherPriorityLabelSelector = deploymentNamePrefix + rand.String(RandomStrLength)
lowerPriorityMatchName = deploymentNamePrefix + rand.String(RandomStrLength)
implicitPriorityMatchName = deploymentNamePrefix + rand.String(RandomStrLength)
deploymentNamespace = testNamespace
deploymentName = deploymentNamePrefix + 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)
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 {
return deployment.GetLabels()[policyv1alpha1.PropagationPolicyNameLabel] == 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
var priorityLabelKey = "priority"
var priorityLabelValue = "priority"
ginkgo.BeforeEach(func() {
policyNamespace = testNamespace
explicitPriorityLabelSelector = deploymentNamePrefix + rand.String(RandomStrLength)
explicitPriorityMatchName = deploymentNamePrefix + rand.String(RandomStrLength)
deploymentNamespace = testNamespace
deploymentName = deploymentNamePrefix + 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)
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 {
return deployment.GetLabels()[policyv1alpha1.PropagationPolicyNameLabel] == explicitPriorityMatchName
})
})
})
})
})
// AdvancedPropagation focus on some advanced propagation testing.
var _ = ginkgo.Describe("[AdvancedPropagation] propagation testing", func() {
ginkgo.Context("Edit PropagationPolicy ResourceSelectors", func() {

View File

@ -22,6 +22,22 @@ func NewPropagationPolicy(ns, name string, rsSelectors []policyv1alpha1.Resource
}
}
// NewExplicitPriorityPropagationPolicy will build a PropagationPolicy object with explicit priority.
func NewExplicitPriorityPropagationPolicy(ns, name string, rsSelectors []policyv1alpha1.ResourceSelector,
placement policyv1alpha1.Placement, priority int32) *policyv1alpha1.PropagationPolicy {
return &policyv1alpha1.PropagationPolicy{
ObjectMeta: metav1.ObjectMeta{
Namespace: ns,
Name: name,
},
Spec: policyv1alpha1.PropagationSpec{
ResourceSelectors: rsSelectors,
Priority: &priority,
Placement: placement,
},
}
}
// NewClusterPropagationPolicy will build a ClusterPropagationPolicy object.
func NewClusterPropagationPolicy(policyName string, rsSelectors []policyv1alpha1.ResourceSelector, placement policyv1alpha1.Placement) *policyv1alpha1.ClusterPropagationPolicy {
return &policyv1alpha1.ClusterPropagationPolicy{
@ -35,6 +51,21 @@ func NewClusterPropagationPolicy(policyName string, rsSelectors []policyv1alpha1
}
}
// NewExplicitPriorityClusterPropagationPolicy will build a ClusterPropagationPolicy object with explicit priority.
func NewExplicitPriorityClusterPropagationPolicy(policyName string, rsSelectors []policyv1alpha1.ResourceSelector,
placement policyv1alpha1.Placement, priority int32) *policyv1alpha1.ClusterPropagationPolicy {
return &policyv1alpha1.ClusterPropagationPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: policyName,
},
Spec: policyv1alpha1.PropagationSpec{
ResourceSelectors: rsSelectors,
Priority: &priority,
Placement: placement,
},
}
}
// NewOverridePolicy will build a OverridePolicy object.
func NewOverridePolicy(namespace, policyName string, rsSelectors []policyv1alpha1.ResourceSelector, clusterAffinity policyv1alpha1.ClusterAffinity, overriders policyv1alpha1.Overriders) *policyv1alpha1.OverridePolicy {
return &policyv1alpha1.OverridePolicy{