diff --git a/internal/controller/autoscaling_controller.go b/internal/controller/autoscaling_controller.go index 8ab628f32..e157ac8dc 100644 --- a/internal/controller/autoscaling_controller.go +++ b/internal/controller/autoscaling_controller.go @@ -335,10 +335,13 @@ func (r *AutoscalingReconciler) reconcileNormal( return rbacResult, nil } - if instance.Spec.Aodh.Auth.ApplicationCredentialSecret != "" || instance.Status.ApplicationCredentialSecret != "" { + // Early phase of the AC split pattern: only add finalizer to the new + // secret. Old secret finalizer removal is deferred until all + // sub-conditions are true (see late phase below). + if instance.Spec.Aodh.Auth.ApplicationCredentialSecret != "" { if err := keystonev1.ManageACSecretFinalizer(ctx, helper, instance.Namespace, instance.Spec.Aodh.Auth.ApplicationCredentialSecret, - instance.Status.ApplicationCredentialSecret, + "", autoscaling.ACConsumerFinalizer); err != nil { instance.Status.Conditions.Set(condition.FalseCondition( condition.ServiceConfigReadyCondition, @@ -349,7 +352,6 @@ func (r *AutoscalingReconciler) reconcileNormal( return ctrl.Result{}, err } } - instance.Status.ApplicationCredentialSecret = instance.Spec.Aodh.Auth.ApplicationCredentialSecret instance.Status.Conditions.MarkTrue(condition.ServiceConfigReadyCondition, condition.ServiceConfigReadyMessage) @@ -727,6 +729,22 @@ func (r *AutoscalingReconciler) reconcileNormal( return ctrlResult, err } + // Late phase of the AC split pattern: remove the old AC secret's + // finalizer and update status only after all sub-conditions are true. + isACRotation := instance.Status.ApplicationCredentialSecret != "" && + instance.Status.ApplicationCredentialSecret != instance.Spec.Aodh.Auth.ApplicationCredentialSecret + if isACRotation { + if instance.Status.Conditions.AllSubConditionIsTrue() { + if err := keystonev1.RemoveACSecretConsumerFinalizer(ctx, helper, instance.Namespace, + instance.Status.ApplicationCredentialSecret, autoscaling.ACConsumerFinalizer); err != nil { + return ctrl.Result{}, err + } + instance.Status.ApplicationCredentialSecret = instance.Spec.Aodh.Auth.ApplicationCredentialSecret + } + } else { + instance.Status.ApplicationCredentialSecret = instance.Spec.Aodh.Auth.ApplicationCredentialSecret + } + if instance.Status.Conditions.AllSubConditionIsTrue() { instance.Status.Conditions.MarkTrue( condition.ReadyCondition, condition.ReadyMessage) diff --git a/internal/controller/ceilometer_controller.go b/internal/controller/ceilometer_controller.go index 8b55c251b..e123d0ab0 100644 --- a/internal/controller/ceilometer_controller.go +++ b/internal/controller/ceilometer_controller.go @@ -762,10 +762,13 @@ func (r *CeilometerReconciler) reconcileCeilometer( instance.Status.Hash[common.InputHashName] = inputHash - if instance.Spec.Auth.ApplicationCredentialSecret != "" || instance.Status.ApplicationCredentialSecret != "" { + // Early phase of the AC split pattern: only add finalizer to the new + // secret. Old secret finalizer removal is deferred until all + // sub-conditions are true (see late phase below). + if instance.Spec.Auth.ApplicationCredentialSecret != "" { if err := keystonev1.ManageACSecretFinalizer(ctx, helper, instance.Namespace, instance.Spec.Auth.ApplicationCredentialSecret, - instance.Status.ApplicationCredentialSecret, + "", ceilometer.ACConsumerFinalizer); err != nil { instance.Status.Conditions.Set(condition.FalseCondition( condition.ServiceConfigReadyCondition, @@ -776,7 +779,6 @@ func (r *CeilometerReconciler) reconcileCeilometer( return ctrl.Result{}, err } } - instance.Status.ApplicationCredentialSecret = instance.Spec.Auth.ApplicationCredentialSecret instance.Status.Conditions.MarkTrue(condition.ServiceConfigReadyCondition, condition.ServiceConfigReadyMessage) @@ -853,6 +855,22 @@ func (r *CeilometerReconciler) reconcileCeilometer( if instance.Status.ReadyCount > 0 { instance.Status.Conditions.MarkTrue(condition.DeploymentReadyCondition, condition.DeploymentReadyMessage) } + // Late phase of the AC split pattern: remove the old AC secret's + // finalizer and update status only after all sub-conditions are true. + isACRotation := instance.Status.ApplicationCredentialSecret != "" && + instance.Status.ApplicationCredentialSecret != instance.Spec.Auth.ApplicationCredentialSecret + if isACRotation { + if instance.Status.Conditions.AllSubConditionIsTrue() { + if err := keystonev1.RemoveACSecretConsumerFinalizer(ctx, helper, instance.Namespace, + instance.Status.ApplicationCredentialSecret, ceilometer.ACConsumerFinalizer); err != nil { + return ctrl.Result{}, err + } + instance.Status.ApplicationCredentialSecret = instance.Spec.Auth.ApplicationCredentialSecret + } + } else { + instance.Status.ApplicationCredentialSecret = instance.Spec.Auth.ApplicationCredentialSecret + } + if instance.Status.Conditions.AllSubConditionIsTrue() { instance.Status.Conditions.MarkTrue( condition.ReadyCondition, condition.ReadyMessage) diff --git a/internal/controller/cloudkitty_controller.go b/internal/controller/cloudkitty_controller.go index 67ea20ccc..7557cf6a6 100644 --- a/internal/controller/cloudkitty_controller.go +++ b/internal/controller/cloudkitty_controller.go @@ -1037,10 +1037,13 @@ func (r *CloudKittyReconciler) reconcileNormal(ctx context.Context, instance *te return ctrl.Result{}, nil } - if instance.Spec.Auth.ApplicationCredentialSecret != "" || instance.Status.ApplicationCredentialSecret != "" { + // Early phase of the AC split pattern: only add finalizer to the new + // secret. Old secret finalizer removal is deferred until all + // sub-conditions are true (see late phase below). + if instance.Spec.Auth.ApplicationCredentialSecret != "" { if err := keystonev1.ManageACSecretFinalizer(ctx, helper, instance.Namespace, instance.Spec.Auth.ApplicationCredentialSecret, - instance.Status.ApplicationCredentialSecret, + "", cloudkitty.ACConsumerFinalizer); err != nil { instance.Status.Conditions.Set(condition.FalseCondition( condition.ServiceConfigReadyCondition, @@ -1051,7 +1054,6 @@ func (r *CloudKittyReconciler) reconcileNormal(ctx context.Context, instance *te return ctrl.Result{}, err } } - instance.Status.ApplicationCredentialSecret = instance.Spec.Auth.ApplicationCredentialSecret instance.Status.Conditions.MarkTrue(condition.ServiceConfigReadyCondition, condition.ServiceConfigReadyMessage) @@ -1171,6 +1173,22 @@ func (r *CloudKittyReconciler) reconcileNormal(ctx context.Context, instance *te return ctrl.Result{}, err } + // Late phase of the AC split pattern: remove the old AC secret's + // finalizer and update status only after all sub-conditions are true. + isACRotation := instance.Status.ApplicationCredentialSecret != "" && + instance.Status.ApplicationCredentialSecret != instance.Spec.Auth.ApplicationCredentialSecret + if isACRotation { + if instance.Status.Conditions.AllSubConditionIsTrue() { + if err := keystonev1.RemoveACSecretConsumerFinalizer(ctx, helper, instance.Namespace, + instance.Status.ApplicationCredentialSecret, cloudkitty.ACConsumerFinalizer); err != nil { + return ctrl.Result{}, err + } + instance.Status.ApplicationCredentialSecret = instance.Spec.Auth.ApplicationCredentialSecret + } + } else { + instance.Status.ApplicationCredentialSecret = instance.Spec.Auth.ApplicationCredentialSecret + } + Log.Info(fmt.Sprintf("Reconciled Service '%s' successfully", instance.Name)) // update the overall status condition if service is ready if instance.IsReady() {