diff --git a/staging/src/k8s.io/apiserver/pkg/server/healthz/BUILD b/staging/src/k8s.io/apiserver/pkg/server/healthz/BUILD index 82a940b776205..a094fbf275a20 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/healthz/BUILD +++ b/staging/src/k8s.io/apiserver/pkg/server/healthz/BUILD @@ -11,6 +11,7 @@ go_test( srcs = ["healthz_test.go"], embed = [":go_default_library"], deps = [ + "//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", ], ) @@ -27,7 +28,6 @@ go_library( "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//staging/src/k8s.io/apiserver/pkg/server/httplog:go_default_library", - "//staging/src/k8s.io/client-go/informers:go_default_library", "//vendor/k8s.io/klog:go_default_library", ], ) diff --git a/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz.go b/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz.go index 0cacdf6a0725b..08633f368e61b 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz.go +++ b/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "net/http" + "reflect" "strings" "sync" "sync/atomic" @@ -28,7 +29,6 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/apiserver/pkg/server/httplog" - "k8s.io/client-go/informers" "k8s.io/klog" ) @@ -81,16 +81,20 @@ func (l *log) Check(_ *http.Request) error { return fmt.Errorf("logging blocked") } +type cacheSyncWaiter interface { + WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool +} + type informerSync struct { - sharedInformerFactory informers.SharedInformerFactory + cacheSyncWaiter cacheSyncWaiter } var _ HealthChecker = &informerSync{} -// NewInformerSyncHealthz returns a new HealthChecker that will pass only if all informers in the given sharedInformerFactory sync. -func NewInformerSyncHealthz(sharedInformerFactory informers.SharedInformerFactory) HealthChecker { +// NewInformerSyncHealthz returns a new HealthChecker that will pass only if all informers in the given cacheSyncWaiter sync. +func NewInformerSyncHealthz(cacheSyncWaiter cacheSyncWaiter) HealthChecker { return &informerSync{ - sharedInformerFactory: sharedInformerFactory, + cacheSyncWaiter: cacheSyncWaiter, } } @@ -103,8 +107,8 @@ func (i *informerSync) Check(_ *http.Request) error { // Close stopCh to force checking if informers are synced now. close(stopCh) - var informersByStarted map[bool][]string - for informerType, started := range i.sharedInformerFactory.WaitForCacheSync(stopCh) { + informersByStarted := make(map[bool][]string) + for informerType, started := range i.cacheSyncWaiter.WaitForCacheSync(stopCh) { informersByStarted[started] = append(informersByStarted[started], informerType.String()) } diff --git a/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz_test.go b/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz_test.go index aae39e0c87c76..800b7c179ce94 100644 --- a/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz_test.go +++ b/staging/src/k8s.io/apiserver/pkg/server/healthz/healthz_test.go @@ -25,6 +25,7 @@ import ( "reflect" "testing" + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/sets" ) @@ -240,3 +241,43 @@ func createGetRequestWithUrl(rawUrlString string) *http.Request { URL: url, } } + +func TestInformerSyncHealthChecker(t *testing.T) { + t.Run("test that check returns nil when all informers are started", func(t *testing.T) { + healthChecker := NewInformerSyncHealthz(cacheSyncWaiterStub{ + startedByInformerType: map[reflect.Type]bool{ + reflect.TypeOf(corev1.Pod{}): true, + }, + }) + + err := healthChecker.Check(nil) + if err != nil { + t.Errorf("Got %v, expected no error", err) + } + }) + + t.Run("test that check returns err when there is not started informer", func(t *testing.T) { + healthChecker := NewInformerSyncHealthz(cacheSyncWaiterStub{ + startedByInformerType: map[reflect.Type]bool{ + reflect.TypeOf(corev1.Pod{}): true, + reflect.TypeOf(corev1.Service{}): false, + reflect.TypeOf(corev1.Node{}): true, + }, + }) + + err := healthChecker.Check(nil) + if err == nil { + t.Errorf("expected error, got: %v", err) + } + }) +} + +type cacheSyncWaiterStub struct { + startedByInformerType map[reflect.Type]bool +} + +// WaitForCacheSync is a stub implementation of the corresponding func +// that simply returns the value passed during stub initialization. +func (s cacheSyncWaiterStub) WaitForCacheSync(_ <-chan struct{}) map[reflect.Type]bool { + return s.startedByInformerType +}