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 7e4e51f
Showing 1 changed file with 60 additions and 1 deletion.
61 changes: 60 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,63 @@ 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
}
workloadEqual := equality.Semantic.DeepEqual(existingWorkloads, desiredWorkloads)

existing.Spec.Workload.Manifests = nil
objCopy := obj.DeepCopy()
objCopy.Spec.Workload.Manifests = nil
if workloadEqual && 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 7e4e51f

Please sign in to comment.