mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Fix panic on /readyz
Signed-off-by: ialidzhikov <i.alidjikov@gmail.com>
This commit is contained in:
parent
ee72e02907
commit
1f06c88dd3
@ -11,6 +11,7 @@ go_test(
|
|||||||
srcs = ["healthz_test.go"],
|
srcs = ["healthz_test.go"],
|
||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/endpoints/metrics:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/endpoints/metrics:go_default_library",
|
||||||
"//staging/src/k8s.io/component-base/metrics/legacyregistry:go_default_library",
|
"//staging/src/k8s.io/component-base/metrics/legacyregistry:go_default_library",
|
||||||
@ -31,7 +32,6 @@ go_library(
|
|||||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/endpoints/metrics:go_default_library",
|
"//staging/src/k8s.io/apiserver/pkg/endpoints/metrics:go_default_library",
|
||||||
"//staging/src/k8s.io/apiserver/pkg/server/httplog: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/v2:go_default_library",
|
"//vendor/k8s.io/klog/v2:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@ -29,7 +30,6 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/apiserver/pkg/endpoints/metrics"
|
"k8s.io/apiserver/pkg/endpoints/metrics"
|
||||||
"k8s.io/apiserver/pkg/server/httplog"
|
"k8s.io/apiserver/pkg/server/httplog"
|
||||||
"k8s.io/client-go/informers"
|
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -82,16 +82,20 @@ func (l *log) Check(_ *http.Request) error {
|
|||||||
return fmt.Errorf("logging blocked")
|
return fmt.Errorf("logging blocked")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type cacheSyncWaiter interface {
|
||||||
|
WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
|
||||||
|
}
|
||||||
|
|
||||||
type informerSync struct {
|
type informerSync struct {
|
||||||
sharedInformerFactory informers.SharedInformerFactory
|
cacheSyncWaiter cacheSyncWaiter
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ HealthChecker = &informerSync{}
|
var _ HealthChecker = &informerSync{}
|
||||||
|
|
||||||
// NewInformerSyncHealthz returns a new HealthChecker that will pass only if all informers in the given sharedInformerFactory sync.
|
// NewInformerSyncHealthz returns a new HealthChecker that will pass only if all informers in the given cacheSyncWaiter sync.
|
||||||
func NewInformerSyncHealthz(sharedInformerFactory informers.SharedInformerFactory) HealthChecker {
|
func NewInformerSyncHealthz(cacheSyncWaiter cacheSyncWaiter) HealthChecker {
|
||||||
return &informerSync{
|
return &informerSync{
|
||||||
sharedInformerFactory: sharedInformerFactory,
|
cacheSyncWaiter: cacheSyncWaiter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,8 +108,8 @@ func (i *informerSync) Check(_ *http.Request) error {
|
|||||||
// Close stopCh to force checking if informers are synced now.
|
// Close stopCh to force checking if informers are synced now.
|
||||||
close(stopCh)
|
close(stopCh)
|
||||||
|
|
||||||
var informersByStarted map[bool][]string
|
informersByStarted := make(map[bool][]string)
|
||||||
for informerType, started := range i.sharedInformerFactory.WaitForCacheSync(stopCh) {
|
for informerType, started := range i.cacheSyncWaiter.WaitForCacheSync(stopCh) {
|
||||||
informersByStarted[started] = append(informersByStarted[started], informerType.String())
|
informersByStarted[started] = append(informersByStarted[started], informerType.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apiserver/pkg/endpoints/metrics"
|
"k8s.io/apiserver/pkg/endpoints/metrics"
|
||||||
"k8s.io/component-base/metrics/legacyregistry"
|
"k8s.io/component-base/metrics/legacyregistry"
|
||||||
@ -273,3 +274,43 @@ func createGetRequestWithUrl(rawUrlString string) *http.Request {
|
|||||||
URL: url,
|
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
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user