Skip to content

Commit fe6bff4

Browse files
author
OpenShift Bot
authored
Merge pull request #11412 from kargakis/add-more-deployment-conditions
Merged by openshift-bot
2 parents 47fd7d6 + e343373 commit fe6bff4

File tree

3 files changed

+282
-33
lines changed

3 files changed

+282
-33
lines changed

pkg/deploy/controller/deploymentconfig/controller.go

+44-32
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ type DeploymentConfigController struct {
7777
// Handle implements the loop that processes deployment configs. Since this controller started
7878
// using caches, the provided config MUST be deep-copied beforehand (see work() in factory.go).
7979
func (c *DeploymentConfigController) Handle(config *deployapi.DeploymentConfig) error {
80+
glog.V(5).Infof("Reconciling %s/%s", config.Namespace, config.Name)
8081
// There's nothing to reconcile until the version is nonzero.
8182
if config.Status.LatestVersion == 0 {
8283
return c.updateStatus(config, []kapi.ReplicationController{})
@@ -182,9 +183,13 @@ func (c *DeploymentConfigController) Handle(config *deployapi.DeploymentConfig)
182183
return c.updateStatus(config, existingDeployments)
183184
}
184185
c.recorder.Eventf(config, kapi.EventTypeWarning, "DeploymentCreationFailed", "Couldn't deploy version %d: %s", config.Status.LatestVersion, err)
186+
// We don't care about this error since we need to report the create failure.
187+
cond := deployutil.NewDeploymentCondition(deployapi.DeploymentProgressing, kapi.ConditionFalse, deployutil.FailedRcCreateReason, err.Error())
188+
_ = c.updateStatus(config, existingDeployments, *cond)
185189
return fmt.Errorf("couldn't create deployment for deployment config %s: %v", deployutil.LabelForDeploymentConfig(config), err)
186190
}
187-
c.recorder.Eventf(config, kapi.EventTypeNormal, "DeploymentCreated", "Created new deployment %q for version %d", created.Name, config.Status.LatestVersion)
191+
msg := fmt.Sprintf("Created new replication controller %q for version %d", created.Name, config.Status.LatestVersion)
192+
c.recorder.Eventf(config, kapi.EventTypeNormal, "DeploymentCreated", msg)
188193

189194
// As we've just created a new deployment, we need to make sure to clean
190195
// up old deployments if we have reached our deployment history quota
@@ -193,7 +198,8 @@ func (c *DeploymentConfigController) Handle(config *deployapi.DeploymentConfig)
193198
c.recorder.Eventf(config, kapi.EventTypeWarning, "DeploymentCleanupFailed", "Couldn't clean up deployments: %v", err)
194199
}
195200

196-
return c.updateStatus(config, existingDeployments)
201+
cond := deployutil.NewDeploymentCondition(deployapi.DeploymentProgressing, kapi.ConditionTrue, deployutil.NewRcAvailableReason, msg)
202+
return c.updateStatus(config, existingDeployments, *cond)
197203
}
198204

199205
// reconcileDeployments reconciles existing deployment replica counts which
@@ -352,19 +358,15 @@ func (c *DeploymentConfigController) reconcileDeployments(existingDeployments []
352358
return c.updateStatus(config, updatedDeployments)
353359
}
354360

355-
func (c *DeploymentConfigController) updateStatus(config *deployapi.DeploymentConfig, deployments []kapi.ReplicationController) error {
356-
newStatus, err := c.calculateStatus(*config, deployments)
361+
// Update the status of the provided deployment config. Additional conditions will override any other condition in the
362+
// deployment config status.
363+
func (c *DeploymentConfigController) updateStatus(config *deployapi.DeploymentConfig, deployments []kapi.ReplicationController, additional ...deployapi.DeploymentCondition) error {
364+
newStatus, err := c.calculateStatus(*config, deployments, additional...)
357365
if err != nil {
358366
glog.V(2).Infof("Cannot calculate the status for %q: %v", deployutil.LabelForDeploymentConfig(config), err)
359367
return err
360368
}
361369

362-
latestExists, latestRC := deployutil.LatestDeploymentInfo(config, deployments)
363-
if !latestExists {
364-
latestRC = nil
365-
}
366-
updateConditions(config, &newStatus, latestRC)
367-
368370
// NOTE: We should update the status of the deployment config only if we need to, otherwise
369371
// we hotloop between updates.
370372
if reflect.DeepEqual(newStatus, config.Status) {
@@ -377,6 +379,7 @@ func (c *DeploymentConfigController) updateStatus(config *deployapi.DeploymentCo
377379
}
378380

379381
copied.Status = newStatus
382+
// TODO: Retry update conficts
380383
if _, err := c.dn.DeploymentConfigs(copied.Namespace).UpdateStatus(copied); err != nil {
381384
glog.V(2).Infof("Cannot update the status for %q: %v", deployutil.LabelForDeploymentConfig(copied), err)
382385
return err
@@ -385,8 +388,9 @@ func (c *DeploymentConfigController) updateStatus(config *deployapi.DeploymentCo
385388
return nil
386389
}
387390

388-
func (c *DeploymentConfigController) calculateStatus(config deployapi.DeploymentConfig, deployments []kapi.ReplicationController) (deployapi.DeploymentConfigStatus, error) {
391+
func (c *DeploymentConfigController) calculateStatus(config deployapi.DeploymentConfig, deployments []kapi.ReplicationController, additional ...deployapi.DeploymentCondition) (deployapi.DeploymentConfigStatus, error) {
389392
selector := labels.Set(config.Spec.Selector).AsSelector()
393+
// TODO: Replace with using rc.status.availableReplicas that comes with the next rebase.
390394
pods, err := c.podStore.Pods(config.Namespace).List(selector)
391395
if err != nil {
392396
return config.Status, err
@@ -396,59 +400,67 @@ func (c *DeploymentConfigController) calculateStatus(config deployapi.Deployment
396400
// UpdatedReplicas represents the replicas that use the deployment config template which means
397401
// we should inform about the replicas of the latest deployment and not the active.
398402
latestReplicas := int32(0)
399-
for _, deployment := range deployments {
400-
if deployment.Name == deployutil.LatestDeploymentNameForConfig(&config) {
401-
updatedDeployment := []kapi.ReplicationController{deployment}
402-
latestReplicas = deployutil.GetStatusReplicaCountForDeployments(updatedDeployment)
403-
break
404-
}
403+
latestExists, latestRC := deployutil.LatestDeploymentInfo(&config, deployments)
404+
if !latestExists {
405+
latestRC = nil
406+
} else {
407+
latestReplicas = deployutil.GetStatusReplicaCountForDeployments([]kapi.ReplicationController{*latestRC})
405408
}
406409

407410
total := deployutil.GetReplicaCountForDeployments(deployments)
408411

409-
return deployapi.DeploymentConfigStatus{
412+
status := deployapi.DeploymentConfigStatus{
410413
LatestVersion: config.Status.LatestVersion,
411414
Details: config.Status.Details,
412415
ObservedGeneration: config.Generation,
413416
Replicas: deployutil.GetStatusReplicaCountForDeployments(deployments),
414417
UpdatedReplicas: latestReplicas,
415418
AvailableReplicas: available,
416419
UnavailableReplicas: total - available,
417-
}, nil
420+
Conditions: config.Status.Conditions,
421+
}
422+
423+
isProgressing := deployutil.IsProgressing(config, status)
424+
updateConditions(config, &status, latestRC, isProgressing)
425+
for _, cond := range additional {
426+
deployutil.SetDeploymentCondition(&status, cond)
427+
}
428+
429+
return status, nil
418430
}
419431

420-
func updateConditions(config *deployapi.DeploymentConfig, newStatus *deployapi.DeploymentConfigStatus, latestRC *kapi.ReplicationController) {
432+
func updateConditions(config deployapi.DeploymentConfig, newStatus *deployapi.DeploymentConfigStatus, latestRC *kapi.ReplicationController, isProgressing bool) {
421433
// Availability condition.
422-
if newStatus.AvailableReplicas >= config.Spec.Replicas-deployutil.MaxUnavailable(*config) {
434+
if newStatus.AvailableReplicas >= config.Spec.Replicas-deployutil.MaxUnavailable(config) && newStatus.AvailableReplicas > 0 {
423435
minAvailability := deployutil.NewDeploymentCondition(deployapi.DeploymentAvailable, kapi.ConditionTrue, "", "Deployment config has minimum availability.")
424436
deployutil.SetDeploymentCondition(newStatus, *minAvailability)
425437
} else {
426438
noMinAvailability := deployutil.NewDeploymentCondition(deployapi.DeploymentAvailable, kapi.ConditionFalse, "", "Deployment config does not have minimum availability.")
427439
deployutil.SetDeploymentCondition(newStatus, *noMinAvailability)
428440
}
441+
429442
// Condition about progress.
430443
cond := deployutil.GetDeploymentCondition(*newStatus, deployapi.DeploymentProgressing)
431444
if latestRC != nil {
432445
switch deployutil.DeploymentStatusFor(latestRC) {
433-
case deployapi.DeploymentStatusNew, deployapi.DeploymentStatusPending:
434-
msg := fmt.Sprintf("Waiting on deployer pod for %q to be scheduled", latestRC.Name)
446+
case deployapi.DeploymentStatusPending:
447+
msg := fmt.Sprintf("Waiting on deployer pod for replication controller %q to be scheduled", latestRC.Name)
435448
condition := deployutil.NewDeploymentCondition(deployapi.DeploymentProgressing, kapi.ConditionUnknown, "", msg)
436449
deployutil.SetDeploymentCondition(newStatus, *condition)
437450
case deployapi.DeploymentStatusRunning:
438-
msg := fmt.Sprintf("Replication controller %q is progressing", latestRC.Name)
439-
condition := deployutil.NewDeploymentCondition(deployapi.DeploymentProgressing, kapi.ConditionTrue, deployutil.ReplicationControllerUpdatedReason, msg)
440-
deployutil.SetDeploymentCondition(newStatus, *condition)
441-
case deployapi.DeploymentStatusFailed:
442-
if cond != nil && cond.Reason == deployutil.TimedOutReason {
443-
break
451+
if isProgressing {
452+
deployutil.RemoveDeploymentCondition(newStatus, deployapi.DeploymentProgressing)
453+
msg := fmt.Sprintf("Replication controller %q is progressing", latestRC.Name)
454+
condition := deployutil.NewDeploymentCondition(deployapi.DeploymentProgressing, kapi.ConditionTrue, deployutil.ReplicationControllerUpdatedReason, msg)
455+
// TODO: Right now, we use lastTransitionTime for storing the last time we had any progress instead
456+
// of the last time the condition transitioned to a new status. We should probably change that.
457+
deployutil.SetDeploymentCondition(newStatus, *condition)
444458
}
459+
case deployapi.DeploymentStatusFailed:
445460
msg := fmt.Sprintf("Replication controller %q has failed progressing", latestRC.Name)
446461
condition := deployutil.NewDeploymentCondition(deployapi.DeploymentProgressing, kapi.ConditionFalse, deployutil.TimedOutReason, msg)
447462
deployutil.SetDeploymentCondition(newStatus, *condition)
448463
case deployapi.DeploymentStatusComplete:
449-
if cond != nil && cond.Reason == deployutil.NewRcAvailableReason {
450-
break
451-
}
452464
msg := fmt.Sprintf("Replication controller %q has completed progressing", latestRC.Name)
453465
condition := deployutil.NewDeploymentCondition(deployapi.DeploymentProgressing, kapi.ConditionTrue, deployutil.NewRcAvailableReason, msg)
454466
deployutil.SetDeploymentCondition(newStatus, *condition)

pkg/deploy/util/util.go

+15-1
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,13 @@ func GetDeploymentCondition(status deployapi.DeploymentConfigStatus, condType de
7070
return nil
7171
}
7272

73-
// SetDeploymentCondition updates the deployment to include the provided condition.
73+
// SetDeploymentCondition updates the deployment to include the provided condition. If the condition that
74+
// we are about to add already exists and has the same status and reason then we are not going to update.
7475
func SetDeploymentCondition(status *deployapi.DeploymentConfigStatus, condition deployapi.DeploymentCondition) {
76+
currentCond := GetDeploymentCondition(*status, condition.Type)
77+
if currentCond != nil && currentCond.Status == condition.Status && currentCond.Reason == condition.Reason {
78+
return
79+
}
7580
newConditions := filterOutCondition(status.Conditions, condition.Type)
7681
status.Conditions = append(newConditions, condition)
7782
}
@@ -474,6 +479,15 @@ func IsRollingConfig(config *deployapi.DeploymentConfig) bool {
474479
return config.Spec.Strategy.Type == deployapi.DeploymentStrategyTypeRolling
475480
}
476481

482+
// IsProgressing expects a state deployment config and its updated status in order to
483+
// determine if there is any progress.
484+
func IsProgressing(config deployapi.DeploymentConfig, newStatus deployapi.DeploymentConfigStatus) bool {
485+
oldStatusOldReplicas := config.Status.Replicas - config.Status.UpdatedReplicas
486+
newStatusOldReplicas := newStatus.Replicas - newStatus.UpdatedReplicas
487+
488+
return (newStatus.UpdatedReplicas > config.Status.UpdatedReplicas) || (newStatusOldReplicas < oldStatusOldReplicas)
489+
}
490+
477491
// MaxUnavailable returns the maximum unavailable pods a rolling deployment config can take.
478492
func MaxUnavailable(config deployapi.DeploymentConfig) int32 {
479493
if !IsRollingConfig(&config) {

0 commit comments

Comments
 (0)