Merge pull request #115093 from xuzhenglun/too-large-resource-version-1.16

Fix bug in reflector not detecting "Too large resource version" error before 1.17.0

Kubernetes-commit: d3f881f7508ec3bd8aa83712038bdcf5f4703396
This commit is contained in:
Kubernetes Publisher 2023-01-18 03:12:46 -08:00
commit e6998df99e
2 changed files with 17 additions and 3 deletions

View File

@ -23,6 +23,7 @@ import (
"io" "io"
"math/rand" "math/rand"
"reflect" "reflect"
"strings"
"sync" "sync"
"time" "time"
@ -693,5 +694,11 @@ func isTooLargeResourceVersionError(err error) bool {
return true return true
} }
} }
// Matches the message returned by api server before 1.17.0
if strings.Contains(apierr.Status().Message, "Too large resource version") {
return true
}
return false return false
} }

View File

@ -919,6 +919,7 @@ func TestReflectorFullListIfTooLarge(t *testing.T) {
stopCh := make(chan struct{}) stopCh := make(chan struct{})
s := NewStore(MetaNamespaceKeyFunc) s := NewStore(MetaNamespaceKeyFunc)
listCallRVs := []string{} listCallRVs := []string{}
version := 30
lw := &testLW{ lw := &testLW{
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
@ -929,6 +930,7 @@ func TestReflectorFullListIfTooLarge(t *testing.T) {
}, },
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
listCallRVs = append(listCallRVs, options.ResourceVersion) listCallRVs = append(listCallRVs, options.ResourceVersion)
resourceVersion := strconv.Itoa(version)
switch options.ResourceVersion { switch options.ResourceVersion {
// initial list // initial list
@ -944,9 +946,14 @@ func TestReflectorFullListIfTooLarge(t *testing.T) {
err := apierrors.NewTimeoutError("too large resource version", 1) err := apierrors.NewTimeoutError("too large resource version", 1)
err.ErrStatus.Details.Causes = []metav1.StatusCause{{Message: "Too large resource version"}} err.ErrStatus.Details.Causes = []metav1.StatusCause{{Message: "Too large resource version"}}
return nil, err return nil, err
// relist after the initial list (covers the error format used in api server before 1.17.0)
case "40":
err := apierrors.NewTimeoutError("Too large resource version", 1)
return nil, err
// relist from etcd after "too large" error // relist from etcd after "too large" error
case "": case "":
return &v1.PodList{ListMeta: metav1.ListMeta{ResourceVersion: "30"}}, nil version += 10
return &v1.PodList{ListMeta: metav1.ListMeta{ResourceVersion: resourceVersion}}, nil
default: default:
return nil, fmt.Errorf("unexpected List call: %s", options.ResourceVersion) return nil, fmt.Errorf("unexpected List call: %s", options.ResourceVersion)
} }
@ -965,7 +972,7 @@ func TestReflectorFullListIfTooLarge(t *testing.T) {
// may be synced to a different version and they will never converge. // may be synced to a different version and they will never converge.
// TODO: We should use etcd progress-notify feature to avoid this behavior but until this is // TODO: We should use etcd progress-notify feature to avoid this behavior but until this is
// done we simply try to relist from now to avoid continuous errors on relists. // done we simply try to relist from now to avoid continuous errors on relists.
for i := 1; i <= 2; i++ { for i := 1; i <= 3; i++ {
// relist twice to cover the two variants of TooLargeResourceVersion api errors // relist twice to cover the two variants of TooLargeResourceVersion api errors
stopCh = make(chan struct{}) stopCh = make(chan struct{})
if err := r.ListAndWatch(stopCh); err != nil { if err := r.ListAndWatch(stopCh); err != nil {
@ -973,7 +980,7 @@ func TestReflectorFullListIfTooLarge(t *testing.T) {
} }
} }
expectedRVs := []string{"0", "20", "", "30", ""} expectedRVs := []string{"0", "20", "", "30", "", "40", ""}
if !reflect.DeepEqual(listCallRVs, expectedRVs) { if !reflect.DeepEqual(listCallRVs, expectedRVs) {
t.Errorf("Expected series of list calls with resource version of %#v but got: %#v", expectedRVs, listCallRVs) t.Errorf("Expected series of list calls with resource version of %#v but got: %#v", expectedRVs, listCallRVs)
} }