Skip to content

Commit aa65e13

Browse files
committed
Reorganize main reconcile flow
1 parent b3cb986 commit aa65e13

File tree

1 file changed

+121
-63
lines changed

1 file changed

+121
-63
lines changed

controllers/placementapi_controller.go

Lines changed: 121 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,11 @@ func (r *PlacementAPIReconciler) Reconcile(ctx context.Context, req ctrl.Request
248248
return ctrl.Result{}, err
249249
}
250250

251+
// initialize status fields
252+
if err = r.initStatus(ctx, h, instance); err != nil {
253+
return ctrl.Result{}, err
254+
}
255+
251256
// Always patch the instance status when exiting this function so we can persist any changes.
252257
defer func() {
253258
// update the Ready condition based on the sub conditions
@@ -270,52 +275,138 @@ func (r *PlacementAPIReconciler) Reconcile(ctx context.Context, req ctrl.Request
270275
}()
271276

272277
// If we're not deleting this and the service object doesn't have our finalizer, add it.
273-
if instance.DeletionTimestamp.IsZero() && controllerutil.AddFinalizer(instance, helper.GetFinalizer()) {
278+
if instance.DeletionTimestamp.IsZero() {
279+
return ctrl.Result{}, r.reconcileDelete(ctx, h, instance)
280+
}
281+
// We create a KeystoneEndpoint CR later and that will automatically get the
282+
// Nova finalizer. So we need a finalizer on the ourselves too so that
283+
// during NovaAPI CR delete we can have a chance to remove the finalizer from
284+
// the our KeystoneEndpoint so that is also deleted.
285+
updated := controllerutil.AddFinalizer(instance, h.GetFinalizer())
286+
if updated {
287+
Log.Info("Added finalizer to ourselves")
288+
// we intentionally return immediately to force the deferred function
289+
// to persist the Instance with the finalizer. We need to have our own
290+
// finalizer persisted before we try to create the KeystoneEndpoint with
291+
// our finalizer to avoid orphaning the KeystoneEndpoint.
274292
return ctrl.Result{}, nil
275293
}
276294

277295
//
278-
// initialize status
296+
// check for required OpenStack secret holding passwords for service/admin user and add hash to the vars map
279297
//
280-
if instance.Status.Conditions == nil {
281-
instance.Status.Conditions = condition.Conditions{}
282-
// initialize conditions used later as Status=Unknown
283-
cl := condition.CreateList(
284-
condition.UnknownCondition(condition.DBReadyCondition, condition.InitReason, condition.DBReadyInitMessage),
285-
condition.UnknownCondition(condition.DBSyncReadyCondition, condition.InitReason, condition.DBSyncReadyInitMessage),
286-
condition.UnknownCondition(condition.ExposeServiceReadyCondition, condition.InitReason, condition.ExposeServiceReadyInitMessage),
287-
condition.UnknownCondition(condition.InputReadyCondition, condition.InitReason, condition.InputReadyInitMessage),
288-
condition.UnknownCondition(condition.ServiceConfigReadyCondition, condition.InitReason, condition.ServiceConfigReadyInitMessage),
289-
condition.UnknownCondition(condition.DeploymentReadyCondition, condition.InitReason, condition.DeploymentReadyInitMessage),
290-
// right now we have no dedicated KeystoneServiceReadyInitMessage and KeystoneEndpointReadyInitMessage
291-
condition.UnknownCondition(condition.KeystoneServiceReadyCondition, condition.InitReason, ""),
292-
condition.UnknownCondition(condition.KeystoneEndpointReadyCondition, condition.InitReason, ""),
293-
condition.UnknownCondition(condition.NetworkAttachmentsReadyCondition, condition.InitReason, condition.NetworkAttachmentsReadyInitMessage),
294-
// service account, role, rolebinding conditions
295-
condition.UnknownCondition(condition.ServiceAccountReadyCondition, condition.InitReason, condition.ServiceAccountReadyInitMessage),
296-
condition.UnknownCondition(condition.RoleReadyCondition, condition.InitReason, condition.RoleReadyInitMessage),
297-
condition.UnknownCondition(condition.RoleBindingReadyCondition, condition.InitReason, condition.RoleBindingReadyInitMessage),
298-
)
298+
hash, result, ospSecret, err := ensureSecret(
299+
ctx,
300+
types.NamespacedName{Namespace: instance.Namespace, Name: instance.Spec.Secret},
301+
[]string{
302+
instance.Spec.PasswordSelectors.Service,
303+
instance.Spec.PasswordSelectors.Database,
304+
},
305+
helper.GetClient(),
306+
&instance.Status.Conditions)
307+
if (err != nil || result != ctrl.Result{}) {
308+
return result, err
309+
}
310+
configMapVars[ospSecret.Name] = env.SetValue(hash)
311+
// all our input checks out so report InputReady
312+
instance.Status.Conditions.MarkTrue(condition.InputReadyCondition, condition.InputReadyMessage)
299313

300-
instance.Status.Conditions.Init(&cl)
314+
// Handle non-deleted clusters
315+
return r.reconcileNormal(ctx, instance, helper)
316+
}
301317

302-
// Register overall status immediately to have an early feedback e.g. in the cli
303-
return ctrl.Result{}, nil
318+
func (r *PlacementAPIReconciler) initStatus(
319+
ctx context.Context, h *helper.Helper, instance *placementv1.PlacementAPI,
320+
) error {
321+
if err := r.initConditions(ctx, h, instance); err != nil {
322+
return err
304323
}
324+
325+
// NOTE(gibi): initialize the rest of the status fields here
326+
// so that the reconcile loop later can assume they are not nil.
305327
if instance.Status.Hash == nil {
306328
instance.Status.Hash = map[string]string{}
307329
}
308330
if instance.Status.NetworkAttachments == nil {
309331
instance.Status.NetworkAttachments = map[string][]string{}
310332
}
311333

312-
// Handle service delete
313-
if !instance.DeletionTimestamp.IsZero() {
314-
return r.reconcileDelete(ctx, instance, helper)
315-
}
334+
return nil
335+
}
316336

317-
// Handle non-deleted clusters
318-
return r.reconcileNormal(ctx, instance, helper)
337+
func (r *PlacementAPIReconciler) initConditions(
338+
ctx context.Context, h *helper.Helper, instance *placementv1.PlacementAPI,
339+
) error {
340+
if instance.Status.Conditions == nil {
341+
instance.Status.Conditions = condition.Conditions{}
342+
// initialize conditions used later as Status=Unknown
343+
cl := condition.CreateList(
344+
condition.UnknownCondition(
345+
condition.DBReadyCondition,
346+
condition.InitReason,
347+
condition.DBReadyInitMessage
348+
),
349+
condition.UnknownCondition(
350+
condition.DBSyncReadyCondition,
351+
condition.InitReason,
352+
condition.DBSyncReadyInitMessage
353+
),
354+
condition.UnknownCondition(
355+
condition.ExposeServiceReadyCondition,
356+
condition.InitReason,
357+
condition.ExposeServiceReadyInitMessage
358+
),
359+
condition.UnknownCondition(
360+
condition.InputReadyCondition,
361+
condition.InitReason,
362+
condition.InputReadyInitMessage
363+
),
364+
condition.UnknownCondition(
365+
condition.ServiceConfigReadyCondition,
366+
condition.InitReason,
367+
condition.ServiceConfigReadyInitMessage
368+
),
369+
condition.UnknownCondition(
370+
condition.DeploymentReadyCondition,
371+
condition.InitReason,
372+
condition.DeploymentReadyInitMessage
373+
),
374+
// right now we have no dedicated KeystoneServiceReadyInitMessage and KeystoneEndpointReadyInitMessage
375+
condition.UnknownCondition(
376+
condition.KeystoneServiceReadyCondition,
377+
condition.InitReason,
378+
"Service registration not started",
379+
),
380+
condition.UnknownCondition(
381+
condition.KeystoneEndpointReadyCondition,
382+
condition.InitReason,
383+
"KeystoneEndpoint not created",
384+
),
385+
condition.UnknownCondition(
386+
condition.NetworkAttachmentsReadyCondition,
387+
condition.InitReason,
388+
condition.NetworkAttachmentsReadyInitMessage
389+
),
390+
// service account, role, rolebinding conditions
391+
condition.UnknownCondition(
392+
condition.ServiceAccountReadyCondition,
393+
condition.InitReason,
394+
condition.ServiceAccountReadyInitMessage
395+
),
396+
condition.UnknownCondition(
397+
condition.RoleReadyCondition,
398+
condition.InitReason,
399+
condition.RoleReadyInitMessage
400+
),
401+
condition.UnknownCondition(
402+
condition.RoleBindingReadyCondition,
403+
condition.InitReason,
404+
condition.RoleBindingReadyInitMessage),
405+
)
406+
407+
instance.Status.Conditions.Init(&cl)
408+
}
409+
return nil
319410
}
320411

321412
// SetupWithManager sets up the controller with the Manager.
@@ -716,39 +807,6 @@ func (r *PlacementAPIReconciler) reconcileNormal(ctx context.Context, instance *
716807
// ConfigMap
717808
configMapVars := make(map[string]env.Setter)
718809

719-
//
720-
// check for required OpenStack secret holding passwords for service/admin user and add hash to the vars map
721-
//
722-
hash, result, ospSecret, err := ensureSecret(
723-
ctx,
724-
types.NamespacedName{Namespace: instance.Namespace, Name: instance.Spec.Secret},
725-
[]string{
726-
instance.Spec.PasswordSelectors.Service,
727-
instance.Spec.PasswordSelectors.Database,
728-
},
729-
helper.GetClient(),
730-
&instance.Status.Conditions)
731-
if err != nil {
732-
if k8s_errors.IsNotFound(err) {
733-
instance.Status.Conditions.Set(condition.FalseCondition(
734-
condition.InputReadyCondition,
735-
condition.RequestedReason,
736-
condition.SeverityInfo,
737-
condition.InputReadyWaitingMessage))
738-
return ctrl.Result{RequeueAfter: time.Second * 10}, fmt.Errorf("OpenStack secret %s not found", instance.Spec.Secret)
739-
}
740-
instance.Status.Conditions.Set(condition.FalseCondition(
741-
condition.InputReadyCondition,
742-
condition.ErrorReason,
743-
condition.SeverityWarning,
744-
condition.InputReadyErrorMessage,
745-
err.Error()))
746-
return result, err
747-
}
748-
configMapVars[ospSecret.Name] = env.SetValue(hash)
749-
instance.Status.Conditions.MarkTrue(condition.InputReadyCondition, condition.InputReadyMessage)
750-
// run check OpenStack secret - end
751-
752810
//
753811
// Create ConfigMaps and Secrets required as input for the Service and calculate an overall hash of hashes
754812
//

0 commit comments

Comments
 (0)