Skip to content

Commit

Permalink
Add cross-version compatibility with client-go 1.27
Browse files Browse the repository at this point in the history
  • Loading branch information
howardjohn committed Mar 3, 2023
1 parent e2d8821 commit 13bba74
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 12 deletions.
33 changes: 27 additions & 6 deletions pkg/cache/multi_namespace_cache.go
Expand Up @@ -305,42 +305,63 @@ type multiNamespaceInformer struct {
namespaceToInformer map[string]Informer
}

type handlerRegistration struct {
handles map[string]toolscache.ResourceEventHandlerRegistration
}

type syncer interface {
HasSynced() bool
}

// HasSynced asserts that the handler has been called for the full initial state of the informer.
// This uses syncer to be compatible between client-go 1.27+ and older versions when the interface changed.
func (h handlerRegistration) HasSynced() bool {
for _, reg := range h.handles {
if s, ok := reg.(syncer); ok {
if !s.HasSynced() {
return false
}
}
}
return true
}

var _ Informer = &multiNamespaceInformer{}

// AddEventHandler adds the handler to each namespaced informer.
func (i *multiNamespaceInformer) AddEventHandler(handler toolscache.ResourceEventHandler) (toolscache.ResourceEventHandlerRegistration, error) {
handles := make(map[string]toolscache.ResourceEventHandlerRegistration, len(i.namespaceToInformer))
handles := handlerRegistration{handles: make(map[string]toolscache.ResourceEventHandlerRegistration, len(i.namespaceToInformer))}
for ns, informer := range i.namespaceToInformer {
registration, err := informer.AddEventHandler(handler)
if err != nil {
return nil, err
}
handles[ns] = registration
handles.handles[ns] = registration
}
return handles, nil
}

// AddEventHandlerWithResyncPeriod adds the handler with a resync period to each namespaced informer.
func (i *multiNamespaceInformer) AddEventHandlerWithResyncPeriod(handler toolscache.ResourceEventHandler, resyncPeriod time.Duration) (toolscache.ResourceEventHandlerRegistration, error) {
handles := make(map[string]toolscache.ResourceEventHandlerRegistration, len(i.namespaceToInformer))
handles := handlerRegistration{handles: make(map[string]toolscache.ResourceEventHandlerRegistration, len(i.namespaceToInformer))}
for ns, informer := range i.namespaceToInformer {
registration, err := informer.AddEventHandlerWithResyncPeriod(handler, resyncPeriod)
if err != nil {
return nil, err
}
handles[ns] = registration
handles.handles[ns] = registration
}
return handles, nil
}

// RemoveEventHandler removes a formerly added event handler given by its registration handle.
func (i *multiNamespaceInformer) RemoveEventHandler(h toolscache.ResourceEventHandlerRegistration) error {
handles, ok := h.(map[string]toolscache.ResourceEventHandlerRegistration)
handles, ok := h.(handlerRegistration)
if !ok {
return fmt.Errorf("it is not the registration returned by multiNamespaceInformer")
}
for ns, informer := range i.namespaceToInformer {
registration, ok := handles[ns]
registration, ok := handles.handles[ns]
if !ok {
continue
}
Expand Down
46 changes: 44 additions & 2 deletions pkg/controller/controllertest/util.go
Expand Up @@ -33,7 +33,49 @@ type FakeInformer struct {
// RunCount is incremented each time RunInformersAndControllers is called
RunCount int

handlers []cache.ResourceEventHandler
handlers []eventHandlerWrapper
}

type modernResourceEventHandler interface {
OnAdd(obj interface{}, isInInitialList bool)
OnUpdate(oldObj, newObj interface{})
OnDelete(obj interface{})
}

type legacyResourceEventHandler interface {
OnAdd(obj interface{})
OnUpdate(oldObj, newObj interface{})
OnDelete(obj interface{})
}

// eventHandlerWrapper wraps a ResourceEventHandler in a manner that is compatible with client-go 1.27+ and older.
// The interface was changed in these versions.
type eventHandlerWrapper struct {
handler any
}

func (e eventHandlerWrapper) OnAdd(obj interface{}) {
if m, ok := e.handler.(modernResourceEventHandler); ok {
m.OnAdd(obj, false)
return
}
e.handler.(legacyResourceEventHandler).OnAdd(obj)
}

func (e eventHandlerWrapper) OnUpdate(oldObj, newObj interface{}) {
if m, ok := e.handler.(modernResourceEventHandler); ok {
m.OnUpdate(oldObj, newObj)
return
}
e.handler.(legacyResourceEventHandler).OnUpdate(oldObj, newObj)
}

func (e eventHandlerWrapper) OnDelete(obj interface{}) {
if m, ok := e.handler.(modernResourceEventHandler); ok {
m.OnDelete(obj)
return
}
e.handler.(legacyResourceEventHandler).OnDelete(obj)
}

// AddIndexers does nothing. TODO(community): Implement this.
Expand All @@ -58,7 +100,7 @@ func (f *FakeInformer) HasSynced() bool {

// AddEventHandler implements the Informer interface. Adds an EventHandler to the fake Informers. TODO(community): Implement Registration.
func (f *FakeInformer) AddEventHandler(handler cache.ResourceEventHandler) (cache.ResourceEventHandlerRegistration, error) {
f.handlers = append(f.handlers, handler)
f.handlers = append(f.handlers, eventHandlerWrapper{handler})
return nil, nil
}

Expand Down
12 changes: 10 additions & 2 deletions pkg/internal/source/event_handler.go
Expand Up @@ -32,8 +32,6 @@ import (

var log = logf.RuntimeLog.WithName("source").WithName("EventHandler")

var _ cache.ResourceEventHandler = &EventHandler{}

// NewEventHandler creates a new EventHandler.
func NewEventHandler(ctx context.Context, queue workqueue.RateLimitingInterface, handler handler.EventHandler, predicates []predicate.Predicate) *EventHandler {
return &EventHandler{
Expand All @@ -55,6 +53,16 @@ type EventHandler struct {
predicates []predicate.Predicate
}

// HandlerFuncs converts EventHandler to a ResourceEventHandlerFuncs
// TODO: switch to ResourceEventHandlerDetailedFuncs with client-go 1.27
func (e *EventHandler) HandlerFuncs() cache.ResourceEventHandlerFuncs {
return cache.ResourceEventHandlerFuncs{
AddFunc: e.OnAdd,
UpdateFunc: e.OnUpdate,
DeleteFunc: e.OnDelete,
}
}

// OnAdd creates CreateEvent and calls Create on EventHandler.
func (e *EventHandler) OnAdd(obj interface{}) {
c := event.CreateEvent{}
Expand Down
2 changes: 1 addition & 1 deletion pkg/internal/source/kind.go
Expand Up @@ -79,7 +79,7 @@ func (ks *Kind) Start(ctx context.Context, handler handler.EventHandler, queue w
return
}

_, err := i.AddEventHandler(NewEventHandler(ctx, queue, handler, prct))
_, err := i.AddEventHandler(NewEventHandler(ctx, queue, handler, prct).HandlerFuncs())
if err != nil {
ks.started <- err
return
Expand Down
2 changes: 1 addition & 1 deletion pkg/source/source.go
Expand Up @@ -204,7 +204,7 @@ func (is *Informer) Start(ctx context.Context, handler handler.EventHandler, que
return fmt.Errorf("must specify Informer.Informer")
}

_, err := is.Informer.AddEventHandler(internal.NewEventHandler(ctx, queue, handler, prct))
_, err := is.Informer.AddEventHandler(internal.NewEventHandler(ctx, queue, handler, prct).HandlerFuncs())
if err != nil {
return err
}
Expand Down

0 comments on commit 13bba74

Please sign in to comment.