diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go index e23045bf40..bf13e03642 100644 --- a/pkg/cache/cache.go +++ b/pkg/cache/cache.go @@ -344,6 +344,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{