Skip to content

Commit 4e7f0c9

Browse files
authored
Add UnsafeDisableCacheDeepCopy as list option to avoid deep copy during list (#1274)
Signed-off-by: Siyu Wang <[email protected]>
1 parent 5de246b commit 4e7f0c9

File tree

6 files changed

+321
-94
lines changed

6 files changed

+321
-94
lines changed

pkg/cache/cache.go

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@ type Options struct {
113113
// [1] https://pkg.go.dev/k8s.io/apimachinery/pkg/fields#Selector
114114
// [2] https://pkg.go.dev/k8s.io/apimachinery/pkg/fields#Set
115115
SelectorsByObject SelectorsByObject
116+
117+
// UnsafeDisableDeepCopyByObject indicates not to deep copy objects during get or
118+
// list objects per GVK at the specified object.
119+
// Be very careful with this, when enabled you must DeepCopy any object before mutating it,
120+
// otherwise you will mutate the object in the cache.
121+
UnsafeDisableDeepCopyByObject DisableDeepCopyByObject
116122
}
117123

118124
var defaultResyncTime = 10 * time.Hour
@@ -127,7 +133,11 @@ func New(config *rest.Config, opts Options) (Cache, error) {
127133
if err != nil {
128134
return nil, err
129135
}
130-
im := internal.NewInformersMap(config, opts.Scheme, opts.Mapper, *opts.Resync, opts.Namespace, selectorsByGVK)
136+
disableDeepCopyByGVK, err := convertToDisableDeepCopyByGVK(opts.UnsafeDisableDeepCopyByObject, opts.Scheme)
137+
if err != nil {
138+
return nil, err
139+
}
140+
im := internal.NewInformersMap(config, opts.Scheme, opts.Mapper, *opts.Resync, opts.Namespace, selectorsByGVK, disableDeepCopyByGVK)
131141
return &informerCache{InformersMap: im}, nil
132142
}
133143

@@ -136,6 +146,8 @@ func New(config *rest.Config, opts Options) (Cache, error) {
136146
// SelectorsByObject
137147
// WARNING: if SelectorsByObject is specified. filtered out resources are not
138148
// returned.
149+
// WARNING: if UnsafeDisableDeepCopy is enabled, you must DeepCopy any object
150+
// returned from cache get/list before mutating it.
139151
func BuilderWithOptions(options Options) NewCacheFunc {
140152
return func(config *rest.Config, opts Options) (Cache, error) {
141153
if opts.Scheme == nil {
@@ -151,6 +163,7 @@ func BuilderWithOptions(options Options) NewCacheFunc {
151163
opts.Namespace = options.Namespace
152164
}
153165
opts.SelectorsByObject = options.SelectorsByObject
166+
opts.UnsafeDisableDeepCopyByObject = options.UnsafeDisableDeepCopyByObject
154167
return New(config, opts)
155168
}
156169
}
@@ -189,3 +202,30 @@ func convertToSelectorsByGVK(selectorsByObject SelectorsByObject, scheme *runtim
189202
}
190203
return selectorsByGVK, nil
191204
}
205+
206+
// DisableDeepCopyByObject associate a client.Object's GVK to disable DeepCopy during get or list from cache.
207+
type DisableDeepCopyByObject map[client.Object]bool
208+
209+
var _ client.Object = &ObjectAll{}
210+
211+
// ObjectAll is the argument to represent all objects' types.
212+
type ObjectAll struct {
213+
client.Object
214+
}
215+
216+
func convertToDisableDeepCopyByGVK(disableDeepCopyByObject DisableDeepCopyByObject, scheme *runtime.Scheme) (internal.DisableDeepCopyByGVK, error) {
217+
disableDeepCopyByGVK := internal.DisableDeepCopyByGVK{}
218+
for obj, disable := range disableDeepCopyByObject {
219+
switch obj.(type) {
220+
case ObjectAll, *ObjectAll:
221+
disableDeepCopyByGVK[internal.GroupVersionKindAll] = disable
222+
default:
223+
gvk, err := apiutil.GVKForObject(obj, scheme)
224+
if err != nil {
225+
return nil, err
226+
}
227+
disableDeepCopyByGVK[gvk] = disable
228+
}
229+
}
230+
return disableDeepCopyByGVK, nil
231+
}

0 commit comments

Comments
 (0)