Skip to content

✨ Add EnableWatchBookmarks option to cache informers #3017

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 1 commit into from
Nov 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 37 additions & 1 deletion pkg/cache/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,18 @@ type Options struct {
// DefaultNamespaces.
DefaultUnsafeDisableDeepCopy *bool

// DefaultEnableWatchBookmarks requests watch events with type "BOOKMARK".
// Servers that do not implement bookmarks may ignore this flag and
// bookmarks are sent at the server's discretion. Clients should not
// assume bookmarks are returned at any specific interval, nor may they
// assume the server will send any BOOKMARK event during a session.
//
// This will be used for all object types, unless it is set in ByObject or
// DefaultNamespaces.
//
// Defaults to true.
DefaultEnableWatchBookmarks *bool

// ByObject restricts the cache's ListWatch to the desired fields per GVK at the specified object.
// If unset, this will fall through to the Default* settings.
ByObject map[client.Object]ByObject
Expand Down Expand Up @@ -273,6 +285,15 @@ type ByObject struct {
// Be very careful with this, when enabled you must DeepCopy any object before mutating it,
// otherwise you will mutate the object in the cache.
UnsafeDisableDeepCopy *bool

// EnableWatchBookmarks requests watch events with type "BOOKMARK".
// Servers that do not implement bookmarks may ignore this flag and
// bookmarks are sent at the server's discretion. Clients should not
// assume bookmarks are returned at any specific interval, nor may they
// assume the server will send any BOOKMARK event during a session.
//
// Defaults to true.
EnableWatchBookmarks *bool
}

// Config describes all potential options for a given watch.
Expand All @@ -299,6 +320,15 @@ type Config struct {
// UnsafeDisableDeepCopy specifies if List and Get requests against the
// cache should not DeepCopy. A nil value allows to default this.
UnsafeDisableDeepCopy *bool

// EnableWatchBookmarks requests watch events with type "BOOKMARK".
// Servers that do not implement bookmarks may ignore this flag and
// bookmarks are sent at the server's discretion. Clients should not
// assume bookmarks are returned at any specific interval, nor may they
// assume the server will send any BOOKMARK event during a session.
//
// Defaults to true.
EnableWatchBookmarks *bool
}

// NewCacheFunc - Function for creating a new cache from the options and a rest config.
Expand Down Expand Up @@ -368,6 +398,7 @@ func optionDefaultsToConfig(opts *Options) Config {
FieldSelector: opts.DefaultFieldSelector,
Transform: opts.DefaultTransform,
UnsafeDisableDeepCopy: opts.DefaultUnsafeDisableDeepCopy,
EnableWatchBookmarks: opts.DefaultEnableWatchBookmarks,
}
}

Expand All @@ -377,6 +408,7 @@ func byObjectToConfig(byObject ByObject) Config {
FieldSelector: byObject.Field,
Transform: byObject.Transform,
UnsafeDisableDeepCopy: byObject.UnsafeDisableDeepCopy,
EnableWatchBookmarks: byObject.EnableWatchBookmarks,
}
}

Expand All @@ -399,6 +431,7 @@ func newCache(restConfig *rest.Config, opts Options) newCacheFunc {
Transform: config.Transform,
WatchErrorHandler: opts.DefaultWatchErrorHandler,
UnsafeDisableDeepCopy: ptr.Deref(config.UnsafeDisableDeepCopy, false),
EnableWatchBookmarks: ptr.Deref(config.EnableWatchBookmarks, true),
NewInformer: opts.newInformer,
}),
readerFailOnMissingInformer: opts.ReaderFailOnMissingInformer,
Expand Down Expand Up @@ -483,6 +516,7 @@ func defaultOpts(config *rest.Config, opts Options) (Options, error) {
byObject.Field = defaultedConfig.FieldSelector
byObject.Transform = defaultedConfig.Transform
byObject.UnsafeDisableDeepCopy = defaultedConfig.UnsafeDisableDeepCopy
byObject.EnableWatchBookmarks = defaultedConfig.EnableWatchBookmarks
}

opts.ByObject[obj] = byObject
Expand Down Expand Up @@ -524,7 +558,9 @@ func defaultConfig(toDefault, defaultFrom Config) Config {
if toDefault.UnsafeDisableDeepCopy == nil {
toDefault.UnsafeDisableDeepCopy = defaultFrom.UnsafeDisableDeepCopy
}

if toDefault.EnableWatchBookmarks == nil {
toDefault.EnableWatchBookmarks = defaultFrom.EnableWatchBookmarks
}
return toDefault
}

Expand Down
24 changes: 24 additions & 0 deletions pkg/cache/defaulting_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,30 @@ func TestDefaultOpts(t *testing.T) {
return cmp.Diff(expected, o.ByObject[pod].UnsafeDisableDeepCopy)
},
},
{
name: "ByObject.EnableWatchBookmarks gets defaulted from DefaultEnableWatchBookmarks",
in: Options{
ByObject: map[client.Object]ByObject{pod: {}},
DefaultEnableWatchBookmarks: ptr.To(true),
},

verification: func(o Options) string {
expected := ptr.To(true)
return cmp.Diff(expected, o.ByObject[pod].EnableWatchBookmarks)
},
},
{
name: "ByObject.EnableWatchBookmarks doesn't get defaulted when set",
in: Options{
ByObject: map[client.Object]ByObject{pod: {EnableWatchBookmarks: ptr.To(false)}},
DefaultEnableWatchBookmarks: ptr.To(true),
},

verification: func(o Options) string {
expected := ptr.To(false)
return cmp.Diff(expected, o.ByObject[pod].EnableWatchBookmarks)
},
},
{
name: "DefaultNamespace label selector gets defaulted from DefaultLabelSelector",
in: Options{
Expand Down
16 changes: 15 additions & 1 deletion pkg/cache/internal/informers.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ type InformersOpts struct {
Selector Selector
Transform cache.TransformFunc
UnsafeDisableDeepCopy bool
EnableWatchBookmarks bool
WatchErrorHandler cache.WatchErrorHandler
}

Expand Down Expand Up @@ -78,6 +79,7 @@ func NewInformers(config *rest.Config, options *InformersOpts) *Informers {
selector: options.Selector,
transform: options.Transform,
unsafeDisableDeepCopy: options.UnsafeDisableDeepCopy,
enableWatchBookmarks: options.EnableWatchBookmarks,
newInformer: newInformer,
watchErrorHandler: options.WatchErrorHandler,
}
Expand Down Expand Up @@ -174,6 +176,7 @@ type Informers struct {
selector Selector
transform cache.TransformFunc
unsafeDisableDeepCopy bool
enableWatchBookmarks bool

// NewInformer allows overriding of the shared index informer constructor for testing.
newInformer func(cache.ListerWatcher, runtime.Object, time.Duration, cache.Indexers) cache.SharedIndexInformer
Expand Down Expand Up @@ -361,8 +364,10 @@ func (ip *Informers) addInformerToMap(gvk schema.GroupVersionKind, obj runtime.O
return listWatcher.ListFunc(opts)
},
WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {
ip.selector.ApplyToList(&opts)
opts.Watch = true // Watch needs to be set to true separately
opts.AllowWatchBookmarks = ip.enableWatchBookmarks

ip.selector.ApplyToList(&opts)
return listWatcher.WatchFunc(opts)
},
}, obj, calculateResyncPeriod(ip.resync), cache.Indexers{
Expand Down Expand Up @@ -444,6 +449,9 @@ func (ip *Informers) makeListWatcher(gvk schema.GroupVersionKind, obj runtime.Ob
},
// Setup the watch function
WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {
opts.Watch = true // Watch needs to be set to true separately
opts.AllowWatchBookmarks = ip.enableWatchBookmarks

if namespace != "" {
return resources.Namespace(namespace).Watch(ip.ctx, opts)
}
Expand Down Expand Up @@ -486,6 +494,9 @@ func (ip *Informers) makeListWatcher(gvk schema.GroupVersionKind, obj runtime.Ob
},
// Setup the watch function
WatchFunc: func(opts metav1.ListOptions) (watcher watch.Interface, err error) {
opts.Watch = true // Watch needs to be set to true separately
opts.AllowWatchBookmarks = ip.enableWatchBookmarks

if namespace != "" {
watcher, err = resources.Namespace(namespace).Watch(ip.ctx, opts)
} else {
Expand Down Expand Up @@ -527,6 +538,9 @@ func (ip *Informers) makeListWatcher(gvk schema.GroupVersionKind, obj runtime.Ob
},
// Setup the watch function
WatchFunc: func(opts metav1.ListOptions) (watch.Interface, error) {
opts.Watch = true // Watch needs to be set to true separately
opts.AllowWatchBookmarks = ip.enableWatchBookmarks

// Build the request.
req := client.Get().Resource(mapping.Resource.Resource).VersionedParams(&opts, ip.paramCodec)
if namespace != "" {
Expand Down