Merge pull request #3879 from whitewindmills/detector-resource

fix bug: avoid updating directly cached resource template
This commit is contained in:
karmada-bot 2023-08-03 17:22:45 +08:00 committed by GitHub
commit e5277b6317
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 24 additions and 15 deletions

View File

@ -566,6 +566,9 @@ func (d *ResourceDetector) ApplyClusterPolicy(object *unstructured.Unstructured,
} }
// GetUnstructuredObject retrieves object by key and returned its unstructured. // GetUnstructuredObject retrieves object by key and returned its unstructured.
// Any updates to this resource template are not recommended as it may come from the informer cache.
// We should abide by the principle of making a deep copy first and then modifying it.
// See issue: https://github.com/karmada-io/karmada/issues/3878.
func (d *ResourceDetector) GetUnstructuredObject(objectKey keys.ClusterWideKey) (*unstructured.Unstructured, error) { func (d *ResourceDetector) GetUnstructuredObject(objectKey keys.ClusterWideKey) (*unstructured.Unstructured, error) {
objectGVR, err := restmapper.GetGroupVersionResource(d.RESTMapper, objectKey.GroupVersionKind()) objectGVR, err := restmapper.GetGroupVersionResource(d.RESTMapper, objectKey.GroupVersionKind())
if err != nil { if err != nil {
@ -1114,7 +1117,7 @@ func (d *ResourceDetector) HandleClusterPropagationPolicyCreationOrUpdate(policy
} }
// CleanupLabels removes labels from object referencing by objRef. // CleanupLabels removes labels from object referencing by objRef.
func (d *ResourceDetector) CleanupLabels(objRef workv1alpha2.ObjectReference, labels ...string) error { func (d *ResourceDetector) CleanupLabels(objRef workv1alpha2.ObjectReference, labelKeys ...string) error {
workload, err := helper.FetchResourceTemplate(d.DynamicClient, d.InformerManager, d.RESTMapper, objRef) workload, err := helper.FetchResourceTemplate(d.DynamicClient, d.InformerManager, d.RESTMapper, objRef)
if err != nil { if err != nil {
// do nothing if resource template not exist, it might has been removed. // do nothing if resource template not exist, it might has been removed.
@ -1125,11 +1128,8 @@ func (d *ResourceDetector) CleanupLabels(objRef workv1alpha2.ObjectReference, la
return err return err
} }
workloadLabels := workload.GetLabels() workload = workload.DeepCopy()
for _, l := range labels { util.RemoveLabels(workload, labelKeys...)
delete(workloadLabels, l)
}
workload.SetLabels(workloadLabels)
gvr, err := restmapper.GetGroupVersionResource(d.RESTMapper, workload.GroupVersionKind()) gvr, err := restmapper.GetGroupVersionResource(d.RESTMapper, workload.GroupVersionKind())
if err != nil { if err != nil {

View File

@ -272,9 +272,9 @@ func (d *ResourceDetector) removeResourceLabelsIfNotMatch(objectReference workv1
return false, nil return false, nil
} }
for _, labelKey := range labelKeys { object = object.DeepCopy()
util.RemoveLabel(object, labelKey) util.RemoveLabels(object, labelKeys...)
}
err = d.Client.Update(context.TODO(), object) err = d.Client.Update(context.TODO(), object)
if err != nil { if err != nil {
return false, err return false, err

View File

@ -207,6 +207,9 @@ func RemoveOrphanWorks(c client.Client, works []workv1alpha1.Work) error {
} }
// FetchResourceTemplate fetches the resource template to be propagated. // FetchResourceTemplate fetches the resource template to be propagated.
// Any updates to this resource template are not recommended as it may come from the informer cache.
// We should abide by the principle of making a deep copy first and then modifying it.
// See issue: https://github.com/karmada-io/karmada/issues/3878.
func FetchResourceTemplate( func FetchResourceTemplate(
dynamicClient dynamic.Interface, dynamicClient dynamic.Interface,
informerManager genericmanager.SingleClusterInformerManager, informerManager genericmanager.SingleClusterInformerManager,

View File

@ -57,11 +57,17 @@ func MergeLabel(obj *unstructured.Unstructured, labelKey string, labelValue stri
obj.SetLabels(labels) obj.SetLabels(labels)
} }
// RemoveLabel removes the label from the given object. // RemoveLabels removes the labels from the given object.
func RemoveLabel(obj *unstructured.Unstructured, labelKey string) { func RemoveLabels(obj *unstructured.Unstructured, labelKeys ...string) {
labels := obj.GetLabels() if len(labelKeys) == 0 {
delete(labels, labelKey) return
obj.SetLabels(labels) }
objLabels := obj.GetLabels()
for _, labelKey := range labelKeys {
delete(objLabels, labelKey)
}
obj.SetLabels(objLabels)
} }
// DedupeAndMergeLabels merges the new labels into exist labels. // DedupeAndMergeLabels merges the new labels into exist labels.

View File

@ -306,7 +306,7 @@ func TestRemoveLabel(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
RemoveLabel(tt.args.obj, tt.args.labelKey) RemoveLabels(tt.args.obj, tt.args.labelKey)
if !reflect.DeepEqual(tt.args.obj, tt.expected) { if !reflect.DeepEqual(tt.args.obj, tt.expected) {
t.Errorf("RemoveLabel() = %v, want %v", tt.args.obj, tt.expected) t.Errorf("RemoveLabel() = %v, want %v", tt.args.obj, tt.expected)
} }