From a7015d9f01e0e94332ee1a50cf33736dc59865b2 Mon Sep 17 00:00:00 2001 From: Alvaro Aleman Date: Sun, 21 Apr 2024 13:58:06 +0200 Subject: [PATCH] :sparkles: Add TransformStripManagedFields This change adds `TransformStripManagedFields` to the Cache, a transform func that strips off all managed fields for objects. There are no known issues when using this as a `DefaultTransform` unless there is explicit code to access objects `ManagedFields` and can lead to a significant reduction in memory usage. --- pkg/cache/cache.go | 16 ++++++++++++++++ pkg/cache/cache_test.go | 19 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go index e23045bf40..fa7b392b6e 100644 --- a/pkg/cache/cache.go +++ b/pkg/cache/cache.go @@ -201,6 +201,9 @@ type Options struct { // DefaultTransform will be used as transform for all object types // unless there is already one set in ByObject or DefaultNamespaces. + // + // A typical usecase for this is to use TransformStripManagedFields + // to reduce the caches memory usage. DefaultTransform toolscache.TransformFunc // DefaultWatchErrorHandler will be used to the WatchErrorHandler which is called @@ -344,6 +347,19 @@ func New(cfg *rest.Config, opts Options) (Cache, error) { return delegating, nil } +// TransformStripManagedFields strips the managed fields of an object before it is committed to the cache. +// If you are not explicitly accessing managedFields from your code, setting this as `DefaultTransform` +// on the cache can lead to a significant reduction in memory usage. +func TransformStripManagedFields() toolscache.TransformFunc { + return func(in any) (any, error) { + if obj, ok := in.(metav1.Object); ok { + obj.SetManagedFields(nil) + } + + return in, nil + } +} + func optionDefaultsToConfig(opts *Options) Config { return Config{ LabelSelector: opts.DefaultLabelSelector, diff --git a/pkg/cache/cache_test.go b/pkg/cache/cache_test.go index 2d88b43ef3..d6c1c4aae4 100644 --- a/pkg/cache/cache_test.go +++ b/pkg/cache/cache_test.go @@ -2421,6 +2421,25 @@ func CacheTest(createCacheFunc func(config *rest.Config, opts cache.Options) (ca }) } +var _ = Describe("TransformStripManagedFields", func() { + It("should strip managed fields from an object", func() { + obj := &corev1.Pod{ObjectMeta: metav1.ObjectMeta{ + ManagedFields: []metav1.ManagedFieldsEntry{{ + Manager: "foo", + }}, + }} + transformed, err := cache.TransformStripManagedFields()(obj) + Expect(err).NotTo(HaveOccurred()) + Expect(transformed).To(Equal(&corev1.Pod{ObjectMeta: metav1.ObjectMeta{}})) + }) + + It("should not trip over an unexpected object", func() { + transformed, err := cache.TransformStripManagedFields()("foo") + Expect(err).NotTo(HaveOccurred()) + Expect(transformed).To(Equal("foo")) + }) +}) + // ensureNamespace installs namespace of a given name if not exists. func ensureNamespace(namespace string, client client.Client) error { ns := corev1.Namespace{