mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Fix Retry-After in clients
This commit is contained in:
		@@ -57,6 +57,9 @@ type RESTClient struct {
 | 
				
			|||||||
	// serializers contain all serializers for undelying content type.
 | 
						// serializers contain all serializers for undelying content type.
 | 
				
			||||||
	serializers Serializers
 | 
						serializers Serializers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// creates BackoffManager that is passed to requests.
 | 
				
			||||||
 | 
						createBackoffMgr func() BackoffManager
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TODO extract this into a wrapper interface via the RESTClient interface in kubectl.
 | 
						// TODO extract this into a wrapper interface via the RESTClient interface in kubectl.
 | 
				
			||||||
	Throttle flowcontrol.RateLimiter
 | 
						Throttle flowcontrol.RateLimiter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -105,6 +108,7 @@ func NewRESTClient(baseURL *url.URL, versionedAPIPath string, config ContentConf
 | 
				
			|||||||
		versionedAPIPath: versionedAPIPath,
 | 
							versionedAPIPath: versionedAPIPath,
 | 
				
			||||||
		contentConfig:    config,
 | 
							contentConfig:    config,
 | 
				
			||||||
		serializers:      *serializers,
 | 
							serializers:      *serializers,
 | 
				
			||||||
 | 
							createBackoffMgr: readExpBackoffConfig,
 | 
				
			||||||
		Throttle:         throttle,
 | 
							Throttle:         throttle,
 | 
				
			||||||
		Client:           client,
 | 
							Client:           client,
 | 
				
			||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
@@ -181,7 +185,7 @@ func createSerializers(config ContentConfig) (*Serializers, error) {
 | 
				
			|||||||
// list, ok := resp.(*api.PodList)
 | 
					// list, ok := resp.(*api.PodList)
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
func (c *RESTClient) Verb(verb string) *Request {
 | 
					func (c *RESTClient) Verb(verb string) *Request {
 | 
				
			||||||
	backoff := readExpBackoffConfig()
 | 
						backoff := c.createBackoffMgr()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if c.Client == nil {
 | 
						if c.Client == nil {
 | 
				
			||||||
		return NewRequest(nil, verb, c.base, c.versionedAPIPath, c.contentConfig, c.serializers, backoff, c.Throttle)
 | 
							return NewRequest(nil, verb, c.base, c.versionedAPIPath, c.contentConfig, c.serializers, backoff, c.Throttle)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -838,6 +838,21 @@ func TestBackoffLifecycle(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type testBackoffManager struct {
 | 
				
			||||||
 | 
						sleeps []time.Duration
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (b *testBackoffManager) UpdateBackoff(actualUrl *url.URL, err error, responseCode int) {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (b *testBackoffManager) CalculateBackoff(actualUrl *url.URL) time.Duration {
 | 
				
			||||||
 | 
						return time.Duration(0)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (b *testBackoffManager) Sleep(d time.Duration) {
 | 
				
			||||||
 | 
						b.sleeps = append(b.sleeps, d)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestCheckRetryClosesBody(t *testing.T) {
 | 
					func TestCheckRetryClosesBody(t *testing.T) {
 | 
				
			||||||
	count := 0
 | 
						count := 0
 | 
				
			||||||
	ch := make(chan struct{})
 | 
						ch := make(chan struct{})
 | 
				
			||||||
@@ -849,12 +864,16 @@ func TestCheckRetryClosesBody(t *testing.T) {
 | 
				
			|||||||
			close(ch)
 | 
								close(ch)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		w.Header().Set("Retry-After", "0")
 | 
							w.Header().Set("Retry-After", "1")
 | 
				
			||||||
		w.WriteHeader(apierrors.StatusTooManyRequests)
 | 
							http.Error(w, "Too many requests, please try again later.", apierrors.StatusTooManyRequests)
 | 
				
			||||||
	}))
 | 
						}))
 | 
				
			||||||
	defer testServer.Close()
 | 
						defer testServer.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						backoffMgr := &testBackoffManager{}
 | 
				
			||||||
 | 
						expectedSleeps := []time.Duration{0, time.Second, 0, time.Second, 0, time.Second, 0, time.Second, 0}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	c := testRESTClient(t, testServer)
 | 
						c := testRESTClient(t, testServer)
 | 
				
			||||||
 | 
						c.createBackoffMgr = func() BackoffManager { return backoffMgr }
 | 
				
			||||||
	_, err := c.Verb("POST").
 | 
						_, err := c.Verb("POST").
 | 
				
			||||||
		Prefix("foo", "bar").
 | 
							Prefix("foo", "bar").
 | 
				
			||||||
		Suffix("baz").
 | 
							Suffix("baz").
 | 
				
			||||||
@@ -868,6 +887,9 @@ func TestCheckRetryClosesBody(t *testing.T) {
 | 
				
			|||||||
	if count != 5 {
 | 
						if count != 5 {
 | 
				
			||||||
		t.Errorf("unexpected retries: %d", count)
 | 
							t.Errorf("unexpected retries: %d", count)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if !reflect.DeepEqual(backoffMgr.sleeps, expectedSleeps) {
 | 
				
			||||||
 | 
							t.Errorf("unexpected sleeps, expected: %v, got: %v", expectedSleeps, backoffMgr.sleeps)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestCheckRetryHandles429And5xx(t *testing.T) {
 | 
					func TestCheckRetryHandles429And5xx(t *testing.T) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -52,11 +52,13 @@ type NoBackoff struct {
 | 
				
			|||||||
func (n *NoBackoff) UpdateBackoff(actualUrl *url.URL, err error, responseCode int) {
 | 
					func (n *NoBackoff) UpdateBackoff(actualUrl *url.URL, err error, responseCode int) {
 | 
				
			||||||
	// do nothing.
 | 
						// do nothing.
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (n *NoBackoff) CalculateBackoff(actualUrl *url.URL) time.Duration {
 | 
					func (n *NoBackoff) CalculateBackoff(actualUrl *url.URL) time.Duration {
 | 
				
			||||||
	return 0 * time.Second
 | 
						return 0 * time.Second
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (n *NoBackoff) Sleep(d time.Duration) {
 | 
					func (n *NoBackoff) Sleep(d time.Duration) {
 | 
				
			||||||
	return
 | 
						time.Sleep(d)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Disable makes the backoff trivial, i.e., sets it to zero.  This might be used
 | 
					// Disable makes the backoff trivial, i.e., sets it to zero.  This might be used
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user