mirror of
https://github.com/kubernetes/client-go.git
synced 2025-09-05 09:01:06 +00:00
client-go + apimachinery watch: context support
The Lister and Watcher interfaces only supported methods without context, but were typically implemented with client-go API calls which need a context. New interfaces get added using the same approach as in https://github.com/kubernetes/kubernetes/pull/129109. Kubernetes-commit: 6688adae142e37114d9dfa8d94cd1d8a91fbcc13
This commit is contained in:
committed by
Kubernetes Publisher
parent
362c5e8de9
commit
bad1caabde
2
tools/cache/controller_test.go
vendored
2
tools/cache/controller_test.go
vendored
@@ -363,7 +363,7 @@ func TestUpdate(t *testing.T) {
|
||||
// everything we've added has been deleted.
|
||||
watchCh := make(chan struct{})
|
||||
_, controller := NewInformer(
|
||||
&testLW{
|
||||
&ListWatch{
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
watch, err := source.Watch(options)
|
||||
close(watchCh)
|
||||
|
174
tools/cache/listwatch.go
vendored
174
tools/cache/listwatch.go
vendored
@@ -27,50 +27,160 @@ import (
|
||||
)
|
||||
|
||||
// Lister is any object that knows how to perform an initial list.
|
||||
//
|
||||
// Ideally, all implementations of Lister should also implement ListerWithContext.
|
||||
type Lister interface {
|
||||
// List should return a list type object; the Items field will be extracted, and the
|
||||
// ResourceVersion field will be used to start the watch in the right place.
|
||||
//
|
||||
// Deprecated: use ListerWithContext.ListWithContext instead.
|
||||
List(options metav1.ListOptions) (runtime.Object, error)
|
||||
}
|
||||
|
||||
// ListerWithContext is any object that knows how to perform an initial list.
|
||||
type ListerWithContext interface {
|
||||
// ListWithContext should return a list type object; the Items field will be extracted, and the
|
||||
// ResourceVersion field will be used to start the watch in the right place.
|
||||
ListWithContext(ctx context.Context, options metav1.ListOptions) (runtime.Object, error)
|
||||
}
|
||||
|
||||
func ToListerWithContext(l Lister) ListerWithContext {
|
||||
if l, ok := l.(ListerWithContext); ok {
|
||||
return l
|
||||
}
|
||||
return listerWrapper{
|
||||
parent: l,
|
||||
}
|
||||
}
|
||||
|
||||
type listerWrapper struct {
|
||||
parent Lister
|
||||
}
|
||||
|
||||
func (l listerWrapper) ListWithContext(ctx context.Context, options metav1.ListOptions) (runtime.Object, error) {
|
||||
return l.parent.List(options)
|
||||
}
|
||||
|
||||
// Watcher is any object that knows how to start a watch on a resource.
|
||||
//
|
||||
// Ideally, all implementations of Watcher should also implement WatcherWithContext.
|
||||
type Watcher interface {
|
||||
// Watch should begin a watch at the specified version.
|
||||
//
|
||||
// If Watch returns an error, it should handle its own cleanup, including
|
||||
// but not limited to calling Stop() on the watch, if one was constructed.
|
||||
// This allows the caller to ignore the watch, if the error is non-nil.
|
||||
//
|
||||
// Deprecated: use WatcherWithContext.WatchWithContext instead.
|
||||
Watch(options metav1.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// WatcherWithContext is any object that knows how to start a watch on a resource.
|
||||
type WatcherWithContext interface {
|
||||
// WatchWithContext should begin a watch at the specified version.
|
||||
//
|
||||
// If Watch returns an error, it should handle its own cleanup, including
|
||||
// but not limited to calling Stop() on the watch, if one was constructed.
|
||||
// This allows the caller to ignore the watch, if the error is non-nil.
|
||||
WatchWithContext(ctx context.Context, options metav1.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
func ToWatcherWithContext(w Watcher) WatcherWithContext {
|
||||
if w, ok := w.(WatcherWithContext); ok {
|
||||
return w
|
||||
}
|
||||
return watcherWrapper{
|
||||
parent: w,
|
||||
}
|
||||
}
|
||||
|
||||
type watcherWrapper struct {
|
||||
parent Watcher
|
||||
}
|
||||
|
||||
func (l watcherWrapper) WatchWithContext(ctx context.Context, options metav1.ListOptions) (watch.Interface, error) {
|
||||
return l.parent.Watch(options)
|
||||
}
|
||||
|
||||
// ListerWatcher is any object that knows how to perform an initial list and start a watch on a resource.
|
||||
//
|
||||
// Ideally, all implementations of ListerWatcher should also implement ListerWatcherWithContext.
|
||||
type ListerWatcher interface {
|
||||
Lister
|
||||
Watcher
|
||||
}
|
||||
|
||||
// ListerWatcherWithContext is any object that knows how to perform an initial list and start a watch on a resource.
|
||||
type ListerWatcherWithContext interface {
|
||||
ListerWithContext
|
||||
WatcherWithContext
|
||||
}
|
||||
|
||||
func ToListerWatcherWithContext(lw ListerWatcher) ListerWatcherWithContext {
|
||||
if lw, ok := lw.(ListerWatcherWithContext); ok {
|
||||
return lw
|
||||
}
|
||||
return listerWatcherWrapper{
|
||||
ListerWithContext: ToListerWithContext(lw),
|
||||
WatcherWithContext: ToWatcherWithContext(lw),
|
||||
}
|
||||
}
|
||||
|
||||
type listerWatcherWrapper struct {
|
||||
ListerWithContext
|
||||
WatcherWithContext
|
||||
}
|
||||
|
||||
// ListFunc knows how to list resources
|
||||
//
|
||||
// Deprecated: use ListWithContextFunc instead.
|
||||
type ListFunc func(options metav1.ListOptions) (runtime.Object, error)
|
||||
|
||||
// ListWithContextFunc knows how to list resources
|
||||
type ListWithContextFunc func(ctx context.Context, options metav1.ListOptions) (runtime.Object, error)
|
||||
|
||||
// WatchFunc knows how to watch resources
|
||||
//
|
||||
// Deprecated: use WatchFuncWithContext instead.
|
||||
type WatchFunc func(options metav1.ListOptions) (watch.Interface, error)
|
||||
|
||||
// ListWatch knows how to list and watch a set of apiserver resources. It satisfies the ListerWatcher interface.
|
||||
// WatchFuncWithContext knows how to watch resources
|
||||
type WatchFuncWithContext func(ctx context.Context, options metav1.ListOptions) (watch.Interface, error)
|
||||
|
||||
// ListWatch knows how to list and watch a set of apiserver resources.
|
||||
// It satisfies the ListerWatcher and ListerWatcherWithContext interfaces.
|
||||
// It is a convenience function for users of NewReflector, etc.
|
||||
// ListFunc and WatchFunc must not be nil
|
||||
// ListFunc or ListWithContextFunc must be set. Same for WatchFunc and WatchFuncWithContext.
|
||||
// ListWithContextFunc and WatchFuncWithContext are preferred if
|
||||
// a context is available, otherwise ListFunc and WatchFunc.
|
||||
//
|
||||
// NewFilteredListWatchFromClient sets all of the functions to ensure that callers
|
||||
// which only know about ListFunc and WatchFunc continue to work.
|
||||
type ListWatch struct {
|
||||
ListFunc ListFunc
|
||||
// Deprecated: use ListWithContext instead.
|
||||
ListFunc ListFunc
|
||||
// Deprecated: use WatchWithContext instead.
|
||||
WatchFunc WatchFunc
|
||||
|
||||
ListWithContextFunc ListWithContextFunc
|
||||
WatchFuncWithContext WatchFuncWithContext
|
||||
|
||||
// DisableChunking requests no chunking for this list watcher.
|
||||
DisableChunking bool
|
||||
}
|
||||
|
||||
var (
|
||||
_ ListerWatcher = &ListWatch{}
|
||||
_ ListerWatcherWithContext = &ListWatch{}
|
||||
)
|
||||
|
||||
// Getter interface knows how to access Get method from RESTClient.
|
||||
type Getter interface {
|
||||
Get() *restclient.Request
|
||||
}
|
||||
|
||||
// NewListWatchFromClient creates a new ListWatch from the specified client, resource, namespace and field selector.
|
||||
// For backward compatibility, all function fields are populated.
|
||||
func NewListWatchFromClient(c Getter, resource string, namespace string, fieldSelector fields.Selector) *ListWatch {
|
||||
optionsModifier := func(options *metav1.ListOptions) {
|
||||
options.FieldSelector = fieldSelector.String()
|
||||
@@ -81,6 +191,7 @@ func NewListWatchFromClient(c Getter, resource string, namespace string, fieldSe
|
||||
// NewFilteredListWatchFromClient creates a new ListWatch from the specified client, resource, namespace, and option modifier.
|
||||
// Option modifier is a function takes a ListOptions and modifies the consumed ListOptions. Provide customized modifier function
|
||||
// to apply modification to ListOptions with a field selector, a label selector, or any other desired options.
|
||||
// For backward compatibility, all function fields are populated.
|
||||
func NewFilteredListWatchFromClient(c Getter, resource string, namespace string, optionsModifier func(options *metav1.ListOptions)) *ListWatch {
|
||||
listFunc := func(options metav1.ListOptions) (runtime.Object, error) {
|
||||
optionsModifier(&options)
|
||||
@@ -88,7 +199,7 @@ func NewFilteredListWatchFromClient(c Getter, resource string, namespace string,
|
||||
Namespace(namespace).
|
||||
Resource(resource).
|
||||
VersionedParams(&options, metav1.ParameterCodec).
|
||||
Do(context.TODO()).
|
||||
Do(context.Background()).
|
||||
Get()
|
||||
}
|
||||
watchFunc := func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
@@ -98,19 +209,70 @@ func NewFilteredListWatchFromClient(c Getter, resource string, namespace string,
|
||||
Namespace(namespace).
|
||||
Resource(resource).
|
||||
VersionedParams(&options, metav1.ParameterCodec).
|
||||
Watch(context.TODO())
|
||||
Watch(context.Background())
|
||||
}
|
||||
listFuncWithContext := func(ctx context.Context, options metav1.ListOptions) (runtime.Object, error) {
|
||||
optionsModifier(&options)
|
||||
return c.Get().
|
||||
Namespace(namespace).
|
||||
Resource(resource).
|
||||
VersionedParams(&options, metav1.ParameterCodec).
|
||||
Do(ctx).
|
||||
Get()
|
||||
}
|
||||
watchFuncWithContext := func(ctx context.Context, options metav1.ListOptions) (watch.Interface, error) {
|
||||
options.Watch = true
|
||||
optionsModifier(&options)
|
||||
return c.Get().
|
||||
Namespace(namespace).
|
||||
Resource(resource).
|
||||
VersionedParams(&options, metav1.ParameterCodec).
|
||||
Watch(ctx)
|
||||
}
|
||||
return &ListWatch{
|
||||
ListFunc: listFunc,
|
||||
WatchFunc: watchFunc,
|
||||
ListWithContextFunc: listFuncWithContext,
|
||||
WatchFuncWithContext: watchFuncWithContext,
|
||||
}
|
||||
return &ListWatch{ListFunc: listFunc, WatchFunc: watchFunc}
|
||||
}
|
||||
|
||||
// List a set of apiserver resources
|
||||
//
|
||||
// Deprecated: use ListWatchWithContext.ListWithContext instead.
|
||||
func (lw *ListWatch) List(options metav1.ListOptions) (runtime.Object, error) {
|
||||
// ListWatch is used in Reflector, which already supports pagination.
|
||||
// Don't paginate here to avoid duplication.
|
||||
if lw.ListFunc != nil {
|
||||
return lw.ListFunc(options)
|
||||
}
|
||||
return lw.ListWithContextFunc(context.Background(), options)
|
||||
}
|
||||
|
||||
// List a set of apiserver resources
|
||||
func (lw *ListWatch) ListWithContext(ctx context.Context, options metav1.ListOptions) (runtime.Object, error) {
|
||||
// ListWatch is used in Reflector, which already supports pagination.
|
||||
// Don't paginate here to avoid duplication.
|
||||
if lw.ListWithContextFunc != nil {
|
||||
return lw.ListWithContextFunc(ctx, options)
|
||||
}
|
||||
return lw.ListFunc(options)
|
||||
}
|
||||
|
||||
// Watch a set of apiserver resources
|
||||
//
|
||||
// Deprecated: use ListWatchWithContext.WatchWithContext instead.
|
||||
func (lw *ListWatch) Watch(options metav1.ListOptions) (watch.Interface, error) {
|
||||
if lw.WatchFunc != nil {
|
||||
return lw.WatchFunc(options)
|
||||
}
|
||||
return lw.WatchFuncWithContext(context.Background(), options)
|
||||
}
|
||||
|
||||
// Watch a set of apiserver resources
|
||||
func (lw *ListWatch) WatchWithContext(ctx context.Context, options metav1.ListOptions) (watch.Interface, error) {
|
||||
if lw.WatchFuncWithContext != nil {
|
||||
return lw.WatchFuncWithContext(ctx, options)
|
||||
}
|
||||
return lw.WatchFunc(options)
|
||||
}
|
||||
|
4
tools/cache/mutation_detector_test.go
vendored
4
tools/cache/mutation_detector_test.go
vendored
@@ -20,7 +20,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
@@ -29,7 +29,7 @@ import (
|
||||
|
||||
func TestMutationDetector(t *testing.T) {
|
||||
fakeWatch := watch.NewFake()
|
||||
lw := &testLW{
|
||||
lw := &ListWatch{
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
return fakeWatch, nil
|
||||
},
|
||||
|
19
tools/cache/reflector.go
vendored
19
tools/cache/reflector.go
vendored
@@ -96,7 +96,7 @@ type Reflector struct {
|
||||
// The destination to sync up with the watch source
|
||||
store ReflectorStore
|
||||
// listerWatcher is used to perform lists and watches.
|
||||
listerWatcher ListerWatcher
|
||||
listerWatcher ListerWatcherWithContext
|
||||
// backoff manages backoff of ListWatch
|
||||
backoffManager wait.BackoffManager
|
||||
resyncPeriod time.Duration
|
||||
@@ -270,7 +270,7 @@ func NewReflectorWithOptions(lw ListerWatcher, expectedType interface{}, store R
|
||||
resyncPeriod: options.ResyncPeriod,
|
||||
minWatchTimeout: minWatchTimeout,
|
||||
typeDescription: options.TypeDescription,
|
||||
listerWatcher: lw,
|
||||
listerWatcher: ToListerWatcherWithContext(lw),
|
||||
store: store,
|
||||
// We used to make the call every 1sec (1 QPS), the goal here is to achieve ~98% traffic reduction when
|
||||
// API server is not healthy. With these parameters, backoff will stop at [30,60) sec interval which is
|
||||
@@ -512,7 +512,7 @@ func (r *Reflector) watch(ctx context.Context, w watch.Interface, resyncerrc cha
|
||||
AllowWatchBookmarks: true,
|
||||
}
|
||||
|
||||
w, err = r.listerWatcher.Watch(options)
|
||||
w, err = r.listerWatcher.WatchWithContext(ctx, options)
|
||||
if err != nil {
|
||||
if canRetry := isWatchErrorRetriable(err); canRetry {
|
||||
logger.V(4).Info("Watch failed - backing off", "reflector", r.name, "type", r.typeDescription, "err", err)
|
||||
@@ -583,7 +583,7 @@ func (r *Reflector) list(ctx context.Context) error {
|
||||
// Attempt to gather list in chunks, if supported by listerWatcher, if not, the first
|
||||
// list request will return the full response.
|
||||
pager := pager.New(pager.SimplePageFunc(func(opts metav1.ListOptions) (runtime.Object, error) {
|
||||
return r.listerWatcher.List(opts)
|
||||
return r.listerWatcher.ListWithContext(ctx, opts)
|
||||
}))
|
||||
switch {
|
||||
case r.WatchListPageSize != 0:
|
||||
@@ -739,7 +739,7 @@ func (r *Reflector) watchList(ctx context.Context) (watch.Interface, error) {
|
||||
}
|
||||
start := r.clock.Now()
|
||||
|
||||
w, err = r.listerWatcher.Watch(options)
|
||||
w, err = r.listerWatcher.WatchWithContext(ctx, options)
|
||||
if err != nil {
|
||||
if isErrorRetriableWithSideEffectsFn(err) {
|
||||
continue
|
||||
@@ -771,7 +771,7 @@ func (r *Reflector) watchList(ctx context.Context) (watch.Interface, error) {
|
||||
// we utilize the temporaryStore to ensure independence from the current store implementation.
|
||||
// as of today, the store is implemented as a queue and will be drained by the higher-level
|
||||
// component as soon as it finishes replacing the content.
|
||||
checkWatchListDataConsistencyIfRequested(ctx, r.name, resourceVersion, wrapListFuncWithContext(r.listerWatcher.List), temporaryStore.List)
|
||||
checkWatchListDataConsistencyIfRequested(ctx, r.name, resourceVersion, r.listerWatcher.ListWithContext, temporaryStore.List)
|
||||
|
||||
if err := r.store.Replace(temporaryStore.List(), resourceVersion); err != nil {
|
||||
return nil, fmt.Errorf("unable to sync watch-list result: %w", err)
|
||||
@@ -1057,13 +1057,6 @@ func isWatchErrorRetriable(err error) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// wrapListFuncWithContext simply wraps ListFunction into another function that accepts a context and ignores it.
|
||||
func wrapListFuncWithContext(listFn ListFunc) func(ctx context.Context, options metav1.ListOptions) (runtime.Object, error) {
|
||||
return func(_ context.Context, options metav1.ListOptions) (runtime.Object, error) {
|
||||
return listFn(options)
|
||||
}
|
||||
}
|
||||
|
||||
// initialEventsEndBookmarkTicker a ticker that produces a warning if the bookmark event
|
||||
// which marks the end of the watch stream, has not been received within the defined tick interval.
|
||||
//
|
||||
|
75
tools/cache/reflector_test.go
vendored
75
tools/cache/reflector_test.go
vendored
@@ -52,24 +52,12 @@ import (
|
||||
|
||||
var nevererrc chan error
|
||||
|
||||
type testLW struct {
|
||||
ListFunc func(options metav1.ListOptions) (runtime.Object, error)
|
||||
WatchFunc func(options metav1.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
func (t *testLW) List(options metav1.ListOptions) (runtime.Object, error) {
|
||||
return t.ListFunc(options)
|
||||
}
|
||||
func (t *testLW) Watch(options metav1.ListOptions) (watch.Interface, error) {
|
||||
return t.WatchFunc(options)
|
||||
}
|
||||
|
||||
func TestCloseWatchChannelOnError(t *testing.T) {
|
||||
_, ctx := ktesting.NewTestContext(t)
|
||||
r := NewReflector(&testLW{}, &v1.Pod{}, NewStore(MetaNamespaceKeyFunc), 0)
|
||||
r := NewReflector(&ListWatch{}, &v1.Pod{}, NewStore(MetaNamespaceKeyFunc), 0)
|
||||
pod := &v1.Pod{ObjectMeta: metav1.ObjectMeta{Name: "bar"}}
|
||||
fw := watch.NewFake()
|
||||
r.listerWatcher = &testLW{
|
||||
r.listerWatcher = &ListWatch{
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
return fw, nil
|
||||
},
|
||||
@@ -94,9 +82,9 @@ func TestRunUntil(t *testing.T) {
|
||||
_, ctx := ktesting.NewTestContext(t)
|
||||
ctx, cancel := context.WithCancelCause(ctx)
|
||||
store := NewStore(MetaNamespaceKeyFunc)
|
||||
r := NewReflector(&testLW{}, &v1.Pod{}, store, 0)
|
||||
r := NewReflector(&ListWatch{}, &v1.Pod{}, store, 0)
|
||||
fw := watch.NewFake()
|
||||
r.listerWatcher = &testLW{
|
||||
r.listerWatcher = &ListWatch{
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
return fw, nil
|
||||
},
|
||||
@@ -138,7 +126,7 @@ func TestRunUntil(t *testing.T) {
|
||||
|
||||
func TestReflectorResyncChan(t *testing.T) {
|
||||
s := NewStore(MetaNamespaceKeyFunc)
|
||||
g := NewReflector(&testLW{}, &v1.Pod{}, s, time.Millisecond)
|
||||
g := NewReflector(&ListWatch{}, &v1.Pod{}, s, time.Millisecond)
|
||||
a, _ := g.resyncChan()
|
||||
b := time.After(wait.ForeverTestTimeout)
|
||||
select {
|
||||
@@ -208,7 +196,7 @@ func TestReflectorWatchStoppedAfter(t *testing.T) {
|
||||
|
||||
func BenchmarkReflectorResyncChanMany(b *testing.B) {
|
||||
s := NewStore(MetaNamespaceKeyFunc)
|
||||
g := NewReflector(&testLW{}, &v1.Pod{}, s, 25*time.Millisecond)
|
||||
g := NewReflector(&ListWatch{}, &v1.Pod{}, s, 25*time.Millisecond)
|
||||
// The improvement to this (calling the timer's Stop() method) makes
|
||||
// this benchmark about 40% faster.
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -223,7 +211,7 @@ func BenchmarkReflectorResyncChanMany(b *testing.B) {
|
||||
// ResultChan is only called once and that Stop is called after ResultChan.
|
||||
func TestReflectorHandleWatchStoppedBefore(t *testing.T) {
|
||||
s := NewStore(MetaNamespaceKeyFunc)
|
||||
g := NewReflector(&testLW{}, &v1.Pod{}, s, 0)
|
||||
g := NewReflector(&ListWatch{}, &v1.Pod{}, s, 0)
|
||||
_, ctx := ktesting.NewTestContext(t)
|
||||
ctx, cancel := context.WithCancelCause(ctx)
|
||||
// Simulate the context being canceled before the watchHandler is called
|
||||
@@ -255,7 +243,7 @@ func TestReflectorHandleWatchStoppedBefore(t *testing.T) {
|
||||
// ResultChan is only called once and that Stop is called after ResultChan.
|
||||
func TestReflectorHandleWatchStoppedAfter(t *testing.T) {
|
||||
s := NewStore(MetaNamespaceKeyFunc)
|
||||
g := NewReflector(&testLW{}, &v1.Pod{}, s, 0)
|
||||
g := NewReflector(&ListWatch{}, &v1.Pod{}, s, 0)
|
||||
var calls []string
|
||||
_, ctx := ktesting.NewTestContext(t)
|
||||
ctx, cancel := context.WithCancelCause(ctx)
|
||||
@@ -291,7 +279,7 @@ func TestReflectorHandleWatchStoppedAfter(t *testing.T) {
|
||||
// stops when the result channel is closed before handleWatch was called.
|
||||
func TestReflectorHandleWatchResultChanClosedBefore(t *testing.T) {
|
||||
s := NewStore(MetaNamespaceKeyFunc)
|
||||
g := NewReflector(&testLW{}, &v1.Pod{}, s, 0)
|
||||
g := NewReflector(&ListWatch{}, &v1.Pod{}, s, 0)
|
||||
_, ctx := ktesting.NewTestContext(t)
|
||||
var calls []string
|
||||
resultCh := make(chan watch.Event)
|
||||
@@ -320,7 +308,7 @@ func TestReflectorHandleWatchResultChanClosedBefore(t *testing.T) {
|
||||
// stops when the result channel is closed after handleWatch has started watching.
|
||||
func TestReflectorHandleWatchResultChanClosedAfter(t *testing.T) {
|
||||
s := NewStore(MetaNamespaceKeyFunc)
|
||||
g := NewReflector(&testLW{}, &v1.Pod{}, s, 0)
|
||||
g := NewReflector(&ListWatch{}, &v1.Pod{}, s, 0)
|
||||
_, ctx := ktesting.NewTestContext(t)
|
||||
var calls []string
|
||||
resultCh := make(chan watch.Event)
|
||||
@@ -352,7 +340,7 @@ func TestReflectorHandleWatchResultChanClosedAfter(t *testing.T) {
|
||||
|
||||
func TestReflectorWatchHandler(t *testing.T) {
|
||||
s := NewStore(MetaNamespaceKeyFunc)
|
||||
g := NewReflector(&testLW{}, &v1.Pod{}, s, 0)
|
||||
g := NewReflector(&ListWatch{}, &v1.Pod{}, s, 0)
|
||||
// Wrap setLastSyncResourceVersion so we can tell the watchHandler to stop
|
||||
// watching after all the events have been consumed. This avoids race
|
||||
// conditions which can happen if the producer calls Stop(), instead of the
|
||||
@@ -416,7 +404,7 @@ func TestReflectorWatchHandler(t *testing.T) {
|
||||
|
||||
func TestReflectorStopWatch(t *testing.T) {
|
||||
s := NewStore(MetaNamespaceKeyFunc)
|
||||
g := NewReflector(&testLW{}, &v1.Pod{}, s, 0)
|
||||
g := NewReflector(&ListWatch{}, &v1.Pod{}, s, 0)
|
||||
fw := watch.NewFake()
|
||||
_, ctx := ktesting.NewTestContext(t)
|
||||
ctx, cancel := context.WithCancelCause(ctx)
|
||||
@@ -437,7 +425,7 @@ func TestReflectorListAndWatch(t *testing.T) {
|
||||
// to get called at the beginning of the watch with 1, and again with 3 when we
|
||||
// inject an error.
|
||||
expectedRVs := []string{"1", "3"}
|
||||
lw := &testLW{
|
||||
lw := &ListWatch{
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
rv := options.ResourceVersion
|
||||
fw := watch.NewFake()
|
||||
@@ -555,7 +543,7 @@ func TestReflectorListAndWatchWithErrors(t *testing.T) {
|
||||
watchRet, watchErr := item.events, item.watchErr
|
||||
_, ctx := ktesting.NewTestContext(t)
|
||||
ctx, cancel := context.WithCancelCause(ctx)
|
||||
lw := &testLW{
|
||||
lw := &ListWatch{
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
if watchErr != nil {
|
||||
return nil, watchErr
|
||||
@@ -634,7 +622,7 @@ func TestReflectorListAndWatchInitConnBackoff(t *testing.T) {
|
||||
time.Sleep(100 * time.Microsecond)
|
||||
}
|
||||
}()
|
||||
lw := &testLW{
|
||||
lw := &ListWatch{
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
if connFails > 0 {
|
||||
connFails--
|
||||
@@ -687,7 +675,7 @@ func TestBackoffOnTooManyRequests(t *testing.T) {
|
||||
clock := &clock.RealClock{}
|
||||
bm := &fakeBackoff{clock: clock}
|
||||
|
||||
lw := &testLW{
|
||||
lw := &ListWatch{
|
||||
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
||||
return &v1.PodList{ListMeta: metav1.ListMeta{ResourceVersion: "1"}}, nil
|
||||
},
|
||||
@@ -733,7 +721,7 @@ func TestNoRelistOnTooManyRequests(t *testing.T) {
|
||||
bm := &fakeBackoff{clock: clock}
|
||||
listCalls, watchCalls := 0, 0
|
||||
|
||||
lw := &testLW{
|
||||
lw := &ListWatch{
|
||||
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
||||
listCalls++
|
||||
return &v1.PodList{ListMeta: metav1.ListMeta{ResourceVersion: "1"}}, nil
|
||||
@@ -804,7 +792,7 @@ func TestRetryInternalError(t *testing.T) {
|
||||
|
||||
counter := 0
|
||||
|
||||
lw := &testLW{
|
||||
lw := &ListWatch{
|
||||
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
||||
return &v1.PodList{ListMeta: metav1.ListMeta{ResourceVersion: "1"}}, nil
|
||||
},
|
||||
@@ -860,7 +848,7 @@ func TestReflectorResync(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
lw := &testLW{
|
||||
lw := &ListWatch{
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
fw := watch.NewFake()
|
||||
return fw, nil
|
||||
@@ -885,7 +873,7 @@ func TestReflectorWatchListPageSize(t *testing.T) {
|
||||
ctx, cancel := context.WithCancelCause(ctx)
|
||||
s := NewStore(MetaNamespaceKeyFunc)
|
||||
|
||||
lw := &testLW{
|
||||
lw := &ListWatch{
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
// Stop once the reflector begins watching since we're only interested in the list.
|
||||
cancel(errors.New("done"))
|
||||
@@ -931,7 +919,7 @@ func TestReflectorNotPaginatingNotConsistentReads(t *testing.T) {
|
||||
ctx, cancel := context.WithCancelCause(ctx)
|
||||
s := NewStore(MetaNamespaceKeyFunc)
|
||||
|
||||
lw := &testLW{
|
||||
lw := &ListWatch{
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
// Stop once the reflector begins watching since we're only interested in the list.
|
||||
cancel(errors.New("done"))
|
||||
@@ -967,7 +955,7 @@ func TestReflectorPaginatingNonConsistentReadsIfWatchCacheDisabled(t *testing.T)
|
||||
var cancel func(error)
|
||||
s := NewStore(MetaNamespaceKeyFunc)
|
||||
|
||||
lw := &testLW{
|
||||
lw := &ListWatch{
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
// Stop once the reflector begins watching since we're only interested in the list.
|
||||
cancel(errors.New("done"))
|
||||
@@ -1024,7 +1012,7 @@ func TestReflectorResyncWithResourceVersion(t *testing.T) {
|
||||
s := NewStore(MetaNamespaceKeyFunc)
|
||||
listCallRVs := []string{}
|
||||
|
||||
lw := &testLW{
|
||||
lw := &ListWatch{
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
// Stop once the reflector begins watching since we're only interested in the list.
|
||||
cancel(errors.New("done"))
|
||||
@@ -1085,7 +1073,7 @@ func TestReflectorExpiredExactResourceVersion(t *testing.T) {
|
||||
s := NewStore(MetaNamespaceKeyFunc)
|
||||
listCallRVs := []string{}
|
||||
|
||||
lw := &testLW{
|
||||
lw := &ListWatch{
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
// Stop once the reflector begins watching since we're only interested in the list.
|
||||
cancel(errors.New("done"))
|
||||
@@ -1145,7 +1133,7 @@ func TestReflectorFullListIfExpired(t *testing.T) {
|
||||
s := NewStore(MetaNamespaceKeyFunc)
|
||||
listCallRVs := []string{}
|
||||
|
||||
lw := &testLW{
|
||||
lw := &ListWatch{
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
// Stop once the reflector begins watching since we're only interested in the list.
|
||||
cancel(errors.New("done"))
|
||||
@@ -1220,7 +1208,7 @@ func TestReflectorFullListIfTooLarge(t *testing.T) {
|
||||
listCallRVs := []string{}
|
||||
version := 30
|
||||
|
||||
lw := &testLW{
|
||||
lw := &ListWatch{
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
// Stop once the reflector begins watching since we're only interested in the list.
|
||||
cancel(errors.New("done"))
|
||||
@@ -1394,7 +1382,7 @@ func TestWatchTimeout(t *testing.T) {
|
||||
s := NewStore(MetaNamespaceKeyFunc)
|
||||
var gotTimeoutSeconds int64
|
||||
|
||||
lw := &testLW{
|
||||
lw := &ListWatch{
|
||||
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
|
||||
return &v1.PodList{ListMeta: metav1.ListMeta{ResourceVersion: "10"}}, nil
|
||||
},
|
||||
@@ -1450,7 +1438,7 @@ func TestReflectorResourceVersionUpdate(t *testing.T) {
|
||||
ctx, cancel := context.WithCancelCause(ctx)
|
||||
fw := watch.NewFake()
|
||||
|
||||
lw := &testLW{
|
||||
lw := &ListWatch{
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
return fw, nil
|
||||
},
|
||||
@@ -1866,7 +1854,7 @@ func TestReflectorReplacesStoreOnUnsafeDelete(t *testing.T) {
|
||||
}
|
||||
|
||||
var once sync.Once
|
||||
lw := &testLW{
|
||||
lw := &ListWatch{
|
||||
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
|
||||
fw := watch.NewFake()
|
||||
go func() {
|
||||
@@ -1892,6 +1880,7 @@ func TestReflectorReplacesStoreOnUnsafeDelete(t *testing.T) {
|
||||
doneCh, stopCh := make(chan struct{}), make(chan struct{})
|
||||
go func() {
|
||||
defer close(doneCh)
|
||||
//nolint:logcheck // Intentionally uses the old API.
|
||||
r.Run(stopCh)
|
||||
}()
|
||||
|
||||
@@ -2066,9 +2055,6 @@ func BenchmarkEachListItemWithAlloc(b *testing.B) {
|
||||
}
|
||||
|
||||
func BenchmarkReflectorList(b *testing.B) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), wait.ForeverTestTimeout)
|
||||
defer cancel()
|
||||
|
||||
store := NewStore(func(obj interface{}) (string, error) {
|
||||
o, err := meta.Accessor(obj)
|
||||
if err != nil {
|
||||
@@ -2102,6 +2088,7 @@ func BenchmarkReflectorList(b *testing.B) {
|
||||
|
||||
for _, tc := range tests {
|
||||
b.Run(tc.name, func(b *testing.B) {
|
||||
_, ctx := ktesting.NewTestContext(b)
|
||||
|
||||
sample := tc.sample()
|
||||
reflector := NewReflector(newPageTestLW(pageNum), &sample, store, 0)
|
||||
|
Reference in New Issue
Block a user