kubeadm: special case context errors in GetConfigMapWithShortRetry

If some code is about to go over the context deadline,
"x/time/rate/rate.go" would return and untyped error with the string
"would exceed context deadline". If some code already exceeded
the deadline the error would be of type DeadlineExceeded.
Ignore such context errors and only store API and connectivity errors.
This commit is contained in:
Lubomir I. Ivanov
2024-01-18 15:32:35 +02:00
parent 54a6e6a772
commit 26a79e4c0b
2 changed files with 59 additions and 1 deletions

View File

@@ -19,6 +19,7 @@ package apiclient
import (
"context"
"encoding/json"
"strings"
"time"
"github.com/pkg/errors"
@@ -346,7 +347,13 @@ func GetConfigMapWithShortRetry(client clientset.Interface, namespace, name stri
if err == nil {
return true, nil
}
lastError = err
// If some code is about to go over the context deadline, "x/time/rate/rate.go" would return
// and untyped error with the string "would exceed context deadline". If some code already exceeded
// the deadline the error would be of type DeadlineExceeded. Ignore such context errors and only store
// API and connectivity errors.
if !strings.Contains(err.Error(), "would exceed context deadline") && !errors.Is(err, context.DeadlineExceeded) {
lastError = err
}
return false, nil
})
if err == nil {

View File

@@ -237,3 +237,54 @@ func TestMutateConfigMapWithConflict(t *testing.T) {
t.Fatalf("ConfigMap mutation with conflict was invalid, has: %q", cm.Data["key"])
}
}
func TestGetConfigMapWithShortRetry(t *testing.T) {
testcases := []struct {
name string
reactorFunc func(core.Action) (bool, runtime.Object, error)
errorCheckFunc func(*testing.T, error)
}{
{
name: "context deadline exceeded error is handled",
reactorFunc: func(core.Action) (bool, runtime.Object, error) {
return true, nil, context.DeadlineExceeded
},
errorCheckFunc: func(t *testing.T, err error) {
if err != nil {
t.Errorf("unexpected error: %v", err)
}
},
},
{
name: "would exceed context deadline error is handled",
reactorFunc: func(core.Action) (bool, runtime.Object, error) {
return true, nil, errors.New("Wait returned an error: rate: Wait(n=1) would exceed context deadline")
},
errorCheckFunc: func(t *testing.T, err error) {
if err != nil {
t.Errorf("unexpected error: %v", err)
}
},
},
{
name: "API error is not handled",
reactorFunc: func(core.Action) (bool, runtime.Object, error) {
return true, nil, apierrors.NewNotFound(schema.GroupResource{}, "")
},
errorCheckFunc: func(t *testing.T, err error) {
if !apierrors.IsNotFound(err) {
t.Errorf("expected error: IsNotFound, got: %v", err)
}
},
},
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
client := fake.NewSimpleClientset()
client.PrependReactor("get", "configmaps", tc.reactorFunc)
_, err := GetConfigMapWithShortRetry(client, "foo", "bar")
tc.errorCheckFunc(t, err)
})
}
}