Merge pull request #93600 from ialidzhikov/fix/readyz-panic
Fix panic on /readyz Kubernetes-commit: ec560b9737537be8c688776461bc700e8ddedb9d
This commit is contained in:
commit
7b7ecfc9c5
|
|
@ -676,7 +676,7 @@
|
|||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/client-go",
|
||||
"Rev": "6ecbef177593"
|
||||
"Rev": "00dbcca6ee44"
|
||||
},
|
||||
{
|
||||
"ImportPath": "k8s.io/component-base",
|
||||
|
|
|
|||
4
go.mod
4
go.mod
|
|
@ -43,7 +43,7 @@ require (
|
|||
gopkg.in/yaml.v2 v2.2.8
|
||||
k8s.io/api v0.0.0-20200731065412-4859c9473977
|
||||
k8s.io/apimachinery v0.0.0-20200726131235-945d4ebf362b
|
||||
k8s.io/client-go v0.0.0-20200731171655-6ecbef177593
|
||||
k8s.io/client-go v0.0.0-20200802132507-00dbcca6ee44
|
||||
k8s.io/component-base v0.0.0-20200731172211-756196c2cad2
|
||||
k8s.io/klog/v2 v2.2.0
|
||||
k8s.io/kube-openapi v0.0.0-20200427153329-656914f816f9
|
||||
|
|
@ -56,6 +56,6 @@ require (
|
|||
replace (
|
||||
k8s.io/api => k8s.io/api v0.0.0-20200731065412-4859c9473977
|
||||
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20200726131235-945d4ebf362b
|
||||
k8s.io/client-go => k8s.io/client-go v0.0.0-20200731171655-6ecbef177593
|
||||
k8s.io/client-go => k8s.io/client-go v0.0.0-20200802132507-00dbcca6ee44
|
||||
k8s.io/component-base => k8s.io/component-base v0.0.0-20200731172211-756196c2cad2
|
||||
)
|
||||
|
|
|
|||
2
go.sum
2
go.sum
|
|
@ -509,7 +509,7 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
|
|||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
k8s.io/api v0.0.0-20200731065412-4859c9473977/go.mod h1:dWsX+vGcHv9rDhMoQlwkI/sGwaGI1AZERZK/rETJ3Ao=
|
||||
k8s.io/apimachinery v0.0.0-20200726131235-945d4ebf362b/go.mod h1:oE8UQU9DqIIc9PyIEYxTj/oJECzZLymCEU9dL0H4F+o=
|
||||
k8s.io/client-go v0.0.0-20200731171655-6ecbef177593/go.mod h1:ch2F5aVooSVNJ55V1uSp2dvmtscdaYZpIJhHtP9l3eY=
|
||||
k8s.io/client-go v0.0.0-20200802132507-00dbcca6ee44/go.mod h1:ch2F5aVooSVNJ55V1uSp2dvmtscdaYZpIJhHtP9l3eY=
|
||||
k8s.io/component-base v0.0.0-20200731172211-756196c2cad2/go.mod h1:GF/5EP2ReckoUAM2elxg5g/5o2ukJ3ydokI2WuF5bCs=
|
||||
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
|
@ -29,7 +30,6 @@ import (
|
|||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apiserver/pkg/endpoints/metrics"
|
||||
"k8s.io/apiserver/pkg/server/httplog"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
|
|
@ -82,16 +82,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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -104,8 +108,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())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apiserver/pkg/endpoints/metrics"
|
||||
"k8s.io/component-base/metrics/legacyregistry"
|
||||
|
|
@ -273,3 +274,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
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue