Skip to content

Commit 8a10e74

Browse files
committed
Update the ReadyCondition for GlanceAPI and mirror to the top level CR
This patch updates the Ready condition by removing it from the defer function and put it at the end of the reconcile loop. In addition, before marking the GlanceAPI Deployment Ready, it checks that the number of replicas is equals to the ReadyCount. If the deployment is still in progress, of this condition is not met, it's mirrored to the top-level CR that shows at which point the Deployment is blocked. Signed-off-by: Francesco Pantano <[email protected]>
1 parent 817980d commit 8a10e74

File tree

4 files changed

+49
-26
lines changed

4 files changed

+49
-26
lines changed

api/v1beta1/glance_types.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,11 @@ func init() {
206206
SchemeBuilder.Register(&Glance{}, &GlanceList{})
207207
}
208208

209-
// IsReady - returns true if Glance is reconciled successfully
209+
// IsReady - returns true if the underlying GlanceAPI is reconciled successfully
210+
// and set the ReadyCondition to True: it is mirrored to the top-level CR, so
211+
// the purpose of this function is to let the openstack-operator to gather the
212+
// Status of the entire Glance Deployment (intended as a single entity) from a
213+
// single place
210214
func (instance Glance) IsReady() bool {
211215
return instance.Status.Conditions.IsTrue(condition.ReadyCondition)
212216
}

controllers/glance_controller.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -699,8 +699,14 @@ func (r *GlanceReconciler) reconcileNormal(ctx context.Context, instance *glance
699699
return ctrlResult, err
700700
}
701701
instance.Status.Conditions.MarkTrue(condition.CronJobReadyCondition, condition.CronJobReadyMessage)
702-
703702
// create CronJob - end
703+
704+
// We reached the end of the Reconcile, update the Ready condition based on
705+
// the sub conditions
706+
if instance.Status.Conditions.AllSubConditionIsTrue() {
707+
instance.Status.Conditions.MarkTrue(
708+
condition.ReadyCondition, condition.ReadyMessage)
709+
}
704710
return ctrl.Result{}, nil
705711
}
706712

@@ -873,6 +879,10 @@ func (r *GlanceReconciler) apiDeploymentCreateOrUpdate(
873879
apiSpec.GlanceAPITemplate.StorageRequest = instance.Spec.StorageRequest
874880
apiSpec.GlanceAPITemplate.StorageClass = instance.Spec.StorageClass
875881
apiSpec.MemcachedInstance = memcached.Name
882+
// Make sure to inject the ContainerImage passed by the OpenStackVersions
883+
// resource to all the underlying instances and rollout a new StatefulSet
884+
// if it has been changed
885+
apiSpec.GlanceAPITemplate.ContainerImage = instance.Spec.ContainerImage
876886

877887
// We select which glanceAPI should register the keystoneEndpoint by using
878888
// an API selector defined in the main glance CR; if it matches with the

controllers/glanceapi_controller.go

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -134,18 +134,8 @@ func (r *GlanceAPIReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
134134

135135
// Always patch the instance status when exiting this function so we can persist any changes.
136136
defer func() {
137-
// update the Ready condition based on the sub conditions
138-
if instance.Status.Conditions.AllSubConditionIsTrue() {
139-
instance.Status.Conditions.MarkTrue(
140-
condition.ReadyCondition, condition.ReadyMessage)
141-
} else {
142-
// something is not ready so reset the Ready condition
143-
instance.Status.Conditions.MarkUnknown(
144-
condition.ReadyCondition, condition.InitReason, condition.ReadyInitMessage)
145-
// and recalculate it based on the state of the rest of the conditions
146-
instance.Status.Conditions.Set(
147-
instance.Status.Conditions.Mirror(condition.ReadyCondition))
148-
}
137+
// Always mirror the Condition from the sub level CRs
138+
instance.Status.Conditions.Set(instance.Status.Conditions.Mirror(condition.ReadyCondition))
149139
condition.RestoreLastTransitionTimes(&instance.Status.Conditions, savedConditions)
150140
err := helper.PatchInstance(ctx, instance)
151141
if err != nil {
@@ -835,8 +825,10 @@ func (r *GlanceAPIReconciler) reconcileNormal(ctx context.Context, instance *gla
835825

836826
return ctrl.Result{}, err
837827
}
838-
839-
if instance.Status.ReadyCount > 0 || *instance.Spec.Replicas == 0 {
828+
// Mark the Deployment as Ready only if the number of Replicas is equals
829+
// to the Deployed instances (ReadyCount), but mark it as True is Replicas
830+
// is zero
831+
if instance.Status.ReadyCount == *instance.Spec.Replicas || *instance.Spec.Replicas == 0 {
840832
instance.Status.Conditions.MarkTrue(condition.DeploymentReadyCondition, condition.DeploymentReadyMessage)
841833
} else {
842834
instance.Status.Conditions.Set(condition.FalseCondition(
@@ -889,8 +881,14 @@ func (r *GlanceAPIReconciler) reconcileNormal(ctx context.Context, instance *gla
889881
condition.CronJobReadyCondition,
890882
condition.CronJobReadyMessage,
891883
)
892-
893884
// create ImageCache cronJobs - end
885+
886+
// We reached the end of the Reconcile, update the Ready condition based on
887+
// the sub conditions
888+
if instance.Status.Conditions.AllSubConditionIsTrue() {
889+
instance.Status.Conditions.MarkTrue(
890+
condition.ReadyCondition, condition.ReadyMessage)
891+
}
894892
r.Log.Info(fmt.Sprintf("Reconciled Service '%s' successfully", instance.Name))
895893
return ctrl.Result{}, nil
896894
}

docs/dev/design-decisions.md

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -426,20 +426,31 @@ Conditions represent a critical aspect for reconciliation because they allow:
426426
3. identify the status of the underlying GlanceAPIs and report their healhy to
427427
the upper level CR
428428

429-
The document [docs/conditions]() describes the meaning of the k8s-operators
430-
shared conditions.
431-
Conditions are re-evaluated when a new Reconciliation loop starts, and if one of
432-
them is different from what has been previously registered, an update is performed,
429+
The document
430+
[docs/conditions](https://github.com/openstack-k8s-operators/docs/blob/main/conditions.md)
431+
describes the meaning of the k8s-operators shared `Conditions`.
432+
Conditions are re-evaluated when a new `Reconcile` loop starts, and if one of
433+
them is different from what was previously registered, an update is performed,
433434
and it allows to give immediate feedback to the user.
434435
Conditions are initially marked as `Unknown`, while the general `ReadyCondition`
435-
is marked as `False` because we assume that the Deployment is in progress but
436+
is marked as `False` because we assume that the `Deployment` is in progress but
436437
not `Ready` at the same time, until the entire set of conditions are evaluated.
437-
Conditions can be seen as a checklist or steps within the reconciliation loop,
438-
and while the loop proceed to the end, each of them is evaluated.
439-
If a particular component with an associated condition is not Ready, an `error`
438+
`Conditions` can be seen as a checklist or steps within the reconcile loop, and
439+
while the loop proceed to the end, each of them is evaluated.
440+
If a particular component with an associated condition is not `Ready`, an `error`
440441
is returned from the operator, and its failing condition is marked as `False`
441442
with an appropriate error message.
442443
If the end of the loop is reached, it means we passed through all the steps and
443-
the Conditions are marked to `True`: it is possible, at this point, to mark the
444+
the `Conditions` are marked to `True`: it is possible, at this point, to mark the
444445
overall `ReadyCondition` to `Status=True` as well and `Mirror` the result to the
445446
top-level CR.
447+
`Conditions` are always Mirrored using the defer function, so that we always
448+
have an information to the `ReadyCondition` that reflects the point where the
449+
loop is exiting/failing.
450+
The general `IsReady` function is used as a wrapper for the `ReadyCondition`
451+
boolean, and it can be used to get the status of the `instance`. In general
452+
in the glance-operator we make the following assumptions:
453+
- A Glance/GlanceAPI is considered `Ready` if all the subconditions are verified
454+
- A Deployment (intended as the `StatefulSet` that represents the GlanceAPIs) is
455+
considered `Ready` if the number of `Replicas` specified in the `Glance` CR
456+
spec is **equal** to the number of available instances (`ReadyCount`).

0 commit comments

Comments
 (0)