Skip to content

Commit

Permalink
fix deep equal check failure in CreateOrUpdateWork(), by change the w…
Browse files Browse the repository at this point in the history
…ay we check it.

Signed-off-by: zach593 <[email protected]>
  • Loading branch information
zach593 committed Dec 11, 2024
1 parent a6df137 commit d2e61d4
Showing 1 changed file with 61 additions and 1 deletion.
62 changes: 61 additions & 1 deletion pkg/util/helper/work.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
"fmt"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/equality"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/fields"
Expand Down Expand Up @@ -80,7 +82,7 @@ func CreateOrUpdateWork(ctx context.Context, client client.Client, workMeta meta
runtimeObject := work.DeepCopy()
var operationResult controllerutil.OperationResult
err = retry.RetryOnConflict(retry.DefaultRetry, func() (err error) {
operationResult, err = controllerutil.CreateOrUpdate(ctx, client, runtimeObject, func() error {
operationResult, err = createOrUpdateWork(ctx, client, runtimeObject, func() error {
if !runtimeObject.DeletionTimestamp.IsZero() {
return fmt.Errorf("work %s/%s is being deleted", runtimeObject.GetNamespace(), runtimeObject.GetName())
}
Expand Down Expand Up @@ -109,6 +111,64 @@ func CreateOrUpdateWork(ctx context.Context, client client.Client, workMeta meta
return nil
}

// createOrUpdateWork is a fork of sigs.k8s.io/controller-runtime/pkg/controller/controllerutil.CreateOrUpdate().
// We modified it to avoid performing deep-equality checks on workloads represented as byte slices.
func createOrUpdateWork(ctx context.Context, c client.Client, obj *workv1alpha1.Work, f controllerutil.MutateFn) (controllerutil.OperationResult, error) {
key := client.ObjectKeyFromObject(obj)
if err := c.Get(ctx, key, obj); err != nil {
if !apierrors.IsNotFound(err) {
return controllerutil.OperationResultNone, err
}
if err := mutate(f, key, obj); err != nil {
return controllerutil.OperationResultNone, err
}
if err := c.Create(ctx, obj); err != nil {
return controllerutil.OperationResultNone, err
}
return controllerutil.OperationResultCreated, nil
}

existing := obj.DeepCopy()
if err := mutate(f, key, obj); err != nil {
return controllerutil.OperationResultNone, err
}

existingWorkloads, err := unmarshalWorkManifests(existing)
if err != nil {
return controllerutil.OperationResultNone, err
}
desiredWorkloads, err := unmarshalWorkManifests(obj)
if err != nil {
return controllerutil.OperationResultNone, err
}
if equality.Semantic.DeepEqual(existingWorkloads, desiredWorkloads) {
return controllerutil.OperationResultNone, nil
}
existing.Spec.Workload.Manifests = nil
objCopy := obj.DeepCopy()
objCopy.Spec.Workload.Manifests = nil
if equality.Semantic.DeepEqual(existing, objCopy) {
return controllerutil.OperationResultNone, nil
}

if err := c.Update(ctx, obj); err != nil {
return controllerutil.OperationResultNone, err
}
return controllerutil.OperationResultUpdated, nil
}

func unmarshalWorkManifests(work *workv1alpha1.Work) ([]*unstructured.Unstructured, error) {
ret := make([]*unstructured.Unstructured, 0, len(work.Spec.Workload.Manifests))
for _, manifest := range work.Spec.Workload.Manifests {
obj := &unstructured.Unstructured{}
if err := obj.UnmarshalJSON(manifest.Raw); err != nil {
return nil, err
}
ret = append(ret, obj)
}
return ret, nil
}

// GetWorksByLabelsSet gets WorkList by matching labels.Set.
func GetWorksByLabelsSet(ctx context.Context, c client.Client, ls labels.Set) (*workv1alpha1.WorkList, error) {
workList := &workv1alpha1.WorkList{}
Expand Down

0 comments on commit d2e61d4

Please sign in to comment.