@@ -13,7 +13,10 @@ import (
13
13
kclient "k8s.io/kubernetes/pkg/client/unversioned"
14
14
adapter "k8s.io/kubernetes/pkg/client/unversioned/adapters/internalclientset"
15
15
"k8s.io/kubernetes/pkg/kubectl"
16
+ "k8s.io/kubernetes/pkg/labels"
16
17
"k8s.io/kubernetes/pkg/runtime"
18
+ "k8s.io/kubernetes/pkg/util/wait"
19
+ "k8s.io/kubernetes/pkg/watch"
17
20
18
21
"github.com/openshift/origin/pkg/client"
19
22
deployapi "github.com/openshift/origin/pkg/deploy/api"
@@ -36,6 +39,8 @@ type RecreateDeploymentStrategy struct {
36
39
until string
37
40
// rcClient is a client to access replication controllers
38
41
rcClient kcoreclient.ReplicationControllersGetter
42
+ // podClient is used to list and watch pods.
43
+ podClient kcoreclient.PodsGetter
39
44
// eventClient is a client to access events
40
45
eventClient kcoreclient.EventsGetter
41
46
// getUpdateAcceptor returns an UpdateAcceptor to verify the first replica
@@ -80,13 +85,15 @@ func NewRecreateDeploymentStrategy(oldClient kclient.Interface, tagClient client
80
85
events : events ,
81
86
until : until ,
82
87
rcClient : client .Core (),
88
+ podClient : client .Core (),
83
89
eventClient : client .Core (),
84
90
getUpdateAcceptor : func (timeout time.Duration , minReadySeconds int32 ) strat.UpdateAcceptor {
85
91
return stratsupport .NewAcceptAvailablePods (out , client .Core (), timeout , acceptorInterval , minReadySeconds )
86
92
},
87
93
scaler : scaler ,
88
94
decoder : decoder ,
89
95
hookExecutor : stratsupport .NewHookExecutor (client .Core (), tagClient , client .Core (), os .Stdout , decoder ),
96
+ // TODO: Should be config.Spec.Strategy.RecreateParams.TimeoutSeconds - (time.Now - deployerPodStartTime)
90
97
retryTimeout : 120 * time .Second ,
91
98
retryPeriod : 1 * time .Second ,
92
99
}
@@ -140,6 +147,8 @@ func (s *RecreateDeploymentStrategy) DeployWithAcceptor(from *kapi.ReplicationCo
140
147
if err != nil {
141
148
return fmt .Errorf ("couldn't scale %s to 0: %v" , from .Name , err )
142
149
}
150
+ // Wait for pods to terminate.
151
+ s .waitForTerminatedPods (from , time .Duration (* params .TimeoutSeconds )* time .Second )
143
152
}
144
153
145
154
if s .until == "0%" {
@@ -221,3 +230,40 @@ func (s *RecreateDeploymentStrategy) scaleAndWait(deployment *kapi.ReplicationCo
221
230
222
231
return s .rcClient .ReplicationControllers (deployment .Namespace ).Get (deployment .Name )
223
232
}
233
+
234
+ // waitForTerminatedPods waits until all pods for the provided replication controller are terminated.
235
+ func (s * RecreateDeploymentStrategy ) waitForTerminatedPods (from * kapi.ReplicationController , timeout time.Duration ) {
236
+ selector := labels .Set (from .Spec .Selector ).AsSelector ()
237
+ options := kapi.ListOptions {LabelSelector : selector }
238
+ podList , err := s .podClient .Pods (from .Namespace ).List (options )
239
+ if err != nil {
240
+ fmt .Fprintf (s .out , "--> Cannot list pods: %v\n New pods may be scaled up before old pods terminate\n " , err )
241
+ return
242
+ }
243
+ // If there are no pods left, we are done.
244
+ if len (podList .Items ) == 0 {
245
+ return
246
+ }
247
+ // Watch from the resource version of the list and wait for all pods to be deleted
248
+ // before proceeding with the Recreate strategy.
249
+ options .ResourceVersion = podList .ResourceVersion
250
+ w , err := s .podClient .Pods (from .Namespace ).Watch (options )
251
+ if err != nil {
252
+ fmt .Fprintf (s .out , "--> Watch could not be established: %v\n New pods may be scaled up before old pods terminate\n " , err )
253
+ return
254
+ }
255
+ defer w .Stop ()
256
+ // Observe as many deletions as the remaining pods and then return.
257
+ deletionsNeeded := len (podList .Items )
258
+ condition := func (event watch.Event ) (bool , error ) {
259
+ if event .Type == watch .Deleted {
260
+ deletionsNeeded --
261
+ }
262
+ return deletionsNeeded == 0 , nil
263
+ }
264
+ // TODO: Timeout should be timeout - (time.Now - deployerPodStartTime)
265
+ if _ , err = watch .Until (timeout , w , condition ); err != nil && err != wait .ErrWaitTimeout {
266
+ fmt .Fprintf (s .out , "--> Watch failed: %v\n New pods may be scaled up before old pods terminate\n " , err )
267
+ }
268
+ return
269
+ }
0 commit comments