@@ -149,6 +149,10 @@ func (c *DeploymentController) handle(deployment *v1.ReplicationController, will
149
149
return actionableError (fmt .Sprintf ("couldn't create deployer pod for %q: %v" , deployutil .LabelForDeploymentV1 (deployment ), err ))
150
150
}
151
151
updatedAnnotations [deployapi .DeploymentPodAnnotation ] = deploymentPod .Name
152
+ updatedAnnotations [deployapi .DeployerPodCreatedAtAnnotation ] = deploymentPod .CreationTimestamp .String ()
153
+ if deploymentPod .Status .StartTime != nil {
154
+ updatedAnnotations [deployapi .DeployerPodStartedAtAnnotation ] = deploymentPod .Status .StartTime .String ()
155
+ }
152
156
nextStatus = deployapi .DeploymentStatusPending
153
157
glog .V (4 ).Infof ("Created deployer pod %q for %q" , deploymentPod .Name , deployutil .LabelForDeploymentV1 (deployment ))
154
158
@@ -176,6 +180,10 @@ func (c *DeploymentController) handle(deployment *v1.ReplicationController, will
176
180
} else {
177
181
// Update to pending or to the appropriate status relative to the existing validated deployer pod.
178
182
updatedAnnotations [deployapi .DeploymentPodAnnotation ] = deployer .Name
183
+ updatedAnnotations [deployapi .DeployerPodCreatedAtAnnotation ] = deployer .CreationTimestamp .String ()
184
+ if deployer .Status .StartTime != nil {
185
+ updatedAnnotations [deployapi .DeployerPodStartedAtAnnotation ] = deployer .Status .StartTime .String ()
186
+ }
179
187
nextStatus = nextStatusComp (nextStatus , deployapi .DeploymentStatusPending )
180
188
}
181
189
}
@@ -293,16 +301,35 @@ func (c *DeploymentController) nextStatus(pod *v1.Pod, deployment *v1.Replicatio
293
301
}
294
302
// Sync the internal replica annotation with the target so that we can
295
303
// distinguish deployer updates from other scaling events.
304
+ completedTimestamp := getPodTerminatedTimestamp (pod )
305
+ if completedTimestamp != nil {
306
+ updatedAnnotations [deployapi .DeployerPodCompletedAtAnnotation ] = completedTimestamp .String ()
307
+ }
296
308
updatedAnnotations [deployapi .DeploymentReplicasAnnotation ] = updatedAnnotations [deployapi .DesiredReplicasAnnotation ]
297
309
delete (updatedAnnotations , deployapi .DesiredReplicasAnnotation )
298
310
return deployapi .DeploymentStatusComplete
299
311
300
312
case v1 .PodFailed :
313
+ completedTimestamp := getPodTerminatedTimestamp (pod )
314
+ if completedTimestamp != nil {
315
+ updatedAnnotations [deployapi .DeployerPodCompletedAtAnnotation ] = completedTimestamp .String ()
316
+ }
301
317
return deployapi .DeploymentStatusFailed
302
318
}
303
319
return deployapi .DeploymentStatusNew
304
320
}
305
321
322
+ // getPodTerminatedTimestamp gets the first terminated container in a pod and
323
+ // return its termination timestamp.
324
+ func getPodTerminatedTimestamp (pod * v1.Pod ) * metav1.Time {
325
+ for _ , c := range pod .Status .ContainerStatuses {
326
+ if t := c .State .Terminated ; t != nil {
327
+ return & t .FinishedAt
328
+ }
329
+ }
330
+ return nil
331
+ }
332
+
306
333
func nextStatusComp (fromDeployer , fromPath deployapi.DeploymentStatus ) deployapi.DeploymentStatus {
307
334
if deployutil .CanTransitionPhase (fromPath , fromDeployer ) {
308
335
return fromDeployer
0 commit comments