From e6a8bb57e868eec5184881e1e3f4f9991f1232aa Mon Sep 17 00:00:00 2001 From: Tom Pantelis Date: Wed, 17 Apr 2024 08:25:22 -0400 Subject: [PATCH] Add reusable TrimManagedFields transform function Signed-off-by: Tom Pantelis --- pkg/resource/resource_test.go | 61 +++++++++++++++++++++++++++++++++++ pkg/resource/util.go | 11 +++++++ pkg/syncer/resource_syncer.go | 9 +----- 3 files changed, 73 insertions(+), 8 deletions(-) diff --git a/pkg/resource/resource_test.go b/pkg/resource/resource_test.go index 38c40831..fd869b2d 100644 --- a/pkg/resource/resource_test.go +++ b/pkg/resource/resource_test.go @@ -22,6 +22,10 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "github.com/submariner-io/admiral/pkg/resource" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/tools/cache" + "k8s.io/utils/ptr" ) var _ = Describe("EnsureValidName", func() { @@ -44,3 +48,60 @@ var _ = Describe("EnsureValidName", func() { }) }) }) + +var _ = Describe("TrimManagedFields", func() { + pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "pod", + Namespace: "ns", + Labels: map[string]string{"app": "test"}, + Annotations: map[string]string{"foo": "bar"}, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{ + { + Image: "image", + Name: "httpd", + }, + }, + }, + } + + When("the object has metadata", func() { + It("should succeed and trim the ManagedFields", func() { + podWithMF := pod.DeepCopy() + podWithMF.ManagedFields = []metav1.ManagedFieldsEntry{ + { + Manager: "kubectl", + Operation: metav1.ManagedFieldsOperationApply, + APIVersion: "v1", + Time: ptr.To(metav1.Now()), + FieldsType: "FieldsV1", + FieldsV1: ptr.To(metav1.FieldsV1{}), + }, + } + + retObj, err := resource.TrimManagedFields(podWithMF) + Expect(err).To(Succeed()) + Expect(podWithMF).To(Equal(pod)) + Expect(retObj).To(BeIdenticalTo(podWithMF)) + + _, err = resource.TrimManagedFields(podWithMF) + Expect(err).To(Succeed()) + Expect(podWithMF).To(Equal(pod)) + }) + }) + + When("the object does not have metadata", func() { + It("should succeed and return the object", func() { + obj := &cache.DeletedFinalStateUnknown{ + Key: "key", + Obj: pod, + } + + retObj, err := resource.TrimManagedFields(obj) + Expect(err).To(Succeed()) + Expect(retObj).To(Equal(obj)) + }) + }) +}) diff --git a/pkg/resource/util.go b/pkg/resource/util.go index 54054fcc..af861b91 100644 --- a/pkg/resource/util.go +++ b/pkg/resource/util.go @@ -125,3 +125,14 @@ func ToJSON(o any) string { out, _ := json.MarshalIndent(o, "", " ") return string(out) } + +// TrimManagedFields is a cache.TransformFunc that removes the ManagedFields metadata field if present. Note that if 'obj' does not +// implement metav1.Object then it is ignored and no error is returned. +func TrimManagedFields(obj interface{}) (interface{}, error) { + objMeta, err := meta.Accessor(obj) + if err == nil && len(objMeta.GetManagedFields()) > 0 { + objMeta.SetManagedFields(nil) + } + + return obj, nil +} diff --git a/pkg/syncer/resource_syncer.go b/pkg/syncer/resource_syncer.go index ae05325a..ad0f6990 100644 --- a/pkg/syncer/resource_syncer.go +++ b/pkg/syncer/resource_syncer.go @@ -256,14 +256,7 @@ func NewResourceSyncer(config *ResourceSyncerConfig) (Interface, error) { AddFunc: syncer.onCreate, UpdateFunc: syncer.onUpdate, DeleteFunc: syncer.onDelete, - }, func(obj interface{}) (interface{}, error) { - objMeta, err := meta.Accessor(obj) - if err == nil && len(objMeta.GetManagedFields()) > 0 { - objMeta.SetManagedFields(nil) - } - - return obj, nil - }) + }, resourceUtil.TrimManagedFields) return syncer, nil }