Skip to content

Commit f081ac4

Browse files
author
OpenShift Bot
authored
Merge pull request #13279 from mfojtik/retry-scale-in-deploy
Merged by openshift-bot
2 parents 475ae9a + f00d197 commit f081ac4

File tree

3 files changed

+93
-2
lines changed

3 files changed

+93
-2
lines changed

pkg/deploy/cmd/test/support.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ package test
33
import (
44
"fmt"
55

6+
"k8s.io/client-go/pkg/api/errors"
7+
"k8s.io/client-go/pkg/api/unversioned"
68
"k8s.io/kubernetes/pkg/kubectl"
79
)
810

@@ -23,3 +25,23 @@ func (t *FakeScaler) Scale(namespace, name string, newSize uint, preconditions *
2325
func (t *FakeScaler) ScaleSimple(namespace, name string, preconditions *kubectl.ScalePrecondition, newSize uint) (string, error) {
2426
return "", fmt.Errorf("unexpected call to ScaleSimple")
2527
}
28+
29+
type FakeLaggedScaler struct {
30+
Events []ScaleEvent
31+
RetryCount int
32+
}
33+
34+
func (t *FakeLaggedScaler) Scale(namespace, name string, newSize uint, preconditions *kubectl.ScalePrecondition, retry, wait *kubectl.RetryParams) error {
35+
if t.RetryCount != 2 {
36+
t.RetryCount += 1
37+
// This is faking a real error from the
38+
// "k8s.io/kubernetes/plugin/pkg/admission/namespace/lifecycle" package.
39+
return errors.NewForbidden(unversioned.GroupResource{Resource: "ReplicationController"}, name, fmt.Errorf("%s: not yet ready to handle request", name))
40+
}
41+
t.Events = append(t.Events, ScaleEvent{name, newSize})
42+
return nil
43+
}
44+
45+
func (t *FakeLaggedScaler) ScaleSimple(namespace, name string, preconditions *kubectl.ScalePrecondition, newSize uint) (string, error) {
46+
return "", nil
47+
}

pkg/deploy/strategy/recreate/recreate.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ import (
55
"io"
66
"io/ioutil"
77
"os"
8+
"strings"
89
"time"
910

11+
"k8s.io/client-go/pkg/api/errors"
1012
kapi "k8s.io/kubernetes/pkg/api"
1113
kclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
1214
kcoreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
@@ -231,11 +233,29 @@ func (s *RecreateDeploymentStrategy) DeployWithAcceptor(from *kapi.ReplicationCo
231233
return nil
232234
}
233235

234-
func (s *RecreateDeploymentStrategy) scaleAndWait(deployment *kapi.ReplicationController, replicas int, retry *kubectl.RetryParams, wait *kubectl.RetryParams) (*kapi.ReplicationController, error) {
236+
func (s *RecreateDeploymentStrategy) scaleAndWait(deployment *kapi.ReplicationController, replicas int, retry *kubectl.RetryParams, retryParams *kubectl.RetryParams) (*kapi.ReplicationController, error) {
235237
if int32(replicas) == deployment.Spec.Replicas && int32(replicas) == deployment.Status.Replicas {
236238
return deployment, nil
237239
}
238-
if err := s.scaler.Scale(deployment.Namespace, deployment.Name, uint(replicas), &kubectl.ScalePrecondition{Size: -1, ResourceVersion: ""}, retry, wait); err != nil {
240+
var scaleErr error
241+
err := wait.PollImmediate(1*time.Second, 30*time.Second, func() (bool, error) {
242+
scaleErr = s.scaler.Scale(deployment.Namespace, deployment.Name, uint(replicas), &kubectl.ScalePrecondition{Size: -1, ResourceVersion: ""}, retry, retryParams)
243+
if scaleErr == nil {
244+
return true, nil
245+
}
246+
// This error is returned when the lifecycle admission plugin cache is not fully
247+
// synchronized. In that case the scaling should be retried.
248+
//
249+
// FIXME: The error returned from admission should not be forbidden but come-back-later error.
250+
if errors.IsForbidden(scaleErr) && strings.Contains(scaleErr.Error(), "not yet ready to handle request") {
251+
return false, nil
252+
}
253+
return false, scaleErr
254+
})
255+
if err == wait.ErrWaitTimeout {
256+
return nil, fmt.Errorf("%v: %v", err, scaleErr)
257+
}
258+
if err != nil {
239259
return nil, err
240260
}
241261

pkg/deploy/strategy/recreate/recreate_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,55 @@ func TestRecreate_acceptorSuccess(t *testing.T) {
293293
}
294294
}
295295

296+
func TestRecreate_acceptorSuccessWithColdCaches(t *testing.T) {
297+
var deployment *kapi.ReplicationController
298+
scaler := &cmdtest.FakeLaggedScaler{}
299+
300+
strategy := &RecreateDeploymentStrategy{
301+
out: &bytes.Buffer{},
302+
errOut: &bytes.Buffer{},
303+
eventClient: fake.NewSimpleClientset().Core(),
304+
decoder: kapi.Codecs.UniversalDecoder(),
305+
retryPeriod: 1 * time.Millisecond,
306+
scaler: scaler,
307+
}
308+
309+
acceptorCalled := false
310+
acceptor := &testAcceptor{
311+
acceptFn: func(deployment *kapi.ReplicationController) error {
312+
acceptorCalled = true
313+
return nil
314+
},
315+
}
316+
317+
oldDeployment, _ := deployutil.MakeDeployment(deploytest.OkDeploymentConfig(1), kapi.Codecs.LegacyCodec(registered.GroupOrDie(kapi.GroupName).GroupVersions[0]))
318+
deployment, _ = deployutil.MakeDeployment(deploytest.OkDeploymentConfig(2), kapi.Codecs.LegacyCodec(registered.GroupOrDie(kapi.GroupName).GroupVersions[0]))
319+
strategy.rcClient = &fakeControllerClient{deployment: deployment}
320+
strategy.podClient = &fakePodClient{deployerName: deployutil.DeployerPodNameForDeployment(deployment.Name)}
321+
322+
err := strategy.DeployWithAcceptor(oldDeployment, deployment, 2, acceptor)
323+
if err != nil {
324+
t.Fatalf("unexpected deploy error: %#v", err)
325+
}
326+
327+
if !acceptorCalled {
328+
t.Fatalf("expected acceptor to be called")
329+
}
330+
331+
if e, a := 2, len(scaler.Events); e != a {
332+
t.Fatalf("expected %d scale calls, got %d", e, a)
333+
}
334+
if e, a := uint(1), scaler.Events[0].Size; e != a {
335+
t.Errorf("expected scale down to %d, got %d", e, a)
336+
}
337+
if e, a := uint(2), scaler.Events[1].Size; e != a {
338+
t.Errorf("expected scale up to %d, got %d", e, a)
339+
}
340+
if scaler.RetryCount != 2 {
341+
t.Errorf("expected retry when the caches are not initialized")
342+
}
343+
}
344+
296345
func TestRecreate_acceptorFail(t *testing.T) {
297346
var deployment *kapi.ReplicationController
298347
scaler := &cmdtest.FakeScaler{}

0 commit comments

Comments
 (0)