Skip to content

Commit

Permalink
Merge pull request #189 from fmount/conditions
Browse files Browse the repository at this point in the history
Re-init conditions each reconcile
  • Loading branch information
openshift-merge-bot[bot] authored Mar 29, 2024
2 parents 3be3eae + 86272f9 commit 0fa4390
Show file tree
Hide file tree
Showing 11 changed files with 213 additions and 109 deletions.
8 changes: 8 additions & 0 deletions api/bases/swift.openstack.org_swifts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,14 @@ spec:
- type
type: object
type: array
observedGeneration:
description: ObservedGeneration - the most recent generation observed
for this service. If the observed generation is less than the spec
generation, then the controller has not processed the latest changes
injected by the opentack-operator in the top-level CR (e.g. the
ContainerImage)
format: int64
type: integer
type: object
type: object
served: true
Expand Down
2 changes: 1 addition & 1 deletion api/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.20
require (
github.com/onsi/ginkgo/v2 v2.17.1
github.com/onsi/gomega v1.32.0
github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240314165949-fec16b14c33b
github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240326081751-56015b1ae3f6
k8s.io/api v0.28.8
k8s.io/apimachinery v0.28.8
k8s.io/client-go v0.28.8
Expand Down
4 changes: 2 additions & 2 deletions api/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,8 @@ github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8
github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk=
github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg=
github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240314165949-fec16b14c33b h1:5EzrrjcGziV69MsEgoBwPdsggY56M6jUxGBP9pp+hwo=
github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240314165949-fec16b14c33b/go.mod h1:DL+Ts0k+fzgZmx0XxWArIeAmdKuTkPa1I5DThdybfmE=
github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240326081751-56015b1ae3f6 h1:4Z7LjnjEF82XiusXJTI/4TqgwnJas3cdvg/qEgkrW8Q=
github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240326081751-56015b1ae3f6/go.mod h1:DL+Ts0k+fzgZmx0XxWArIeAmdKuTkPa1I5DThdybfmE=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
Expand Down
6 changes: 6 additions & 0 deletions api/v1beta1/swift_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,12 @@ type SwiftSpecBase struct {
type SwiftStatus struct {
// Conditions
Conditions condition.Conditions `json:"conditions,omitempty" optional:"true"`

// ObservedGeneration - the most recent generation observed for this
// service. If the observed generation is less than the spec generation,
// then the controller has not processed the latest changes injected by
// the opentack-operator in the top-level CR (e.g. the ContainerImage)
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
}

//+kubebuilder:object:root=true
Expand Down
8 changes: 8 additions & 0 deletions config/crd/bases/swift.openstack.org_swifts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,14 @@ spec:
- type
type: object
type: array
observedGeneration:
description: ObservedGeneration - the most recent generation observed
for this service. If the observed generation is less than the spec
generation, then the controller has not processed the latest changes
injected by the opentack-operator in the top-level CR (e.g. the
ContainerImage)
format: int64
type: integer
type: object
type: object
served: true
Expand Down
82 changes: 48 additions & 34 deletions controllers/swift_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,23 @@ func (r *SwiftReconciler) Reconcile(ctx context.Context, req ctrl.Request) (resu
return ctrl.Result{}, err
}

// Always patch the instance status when exiting this function so we can persist any changes.
// initialize status if Conditions is nil, but do not reset if it already
// exists
isNewInstance := instance.Status.Conditions == nil
if isNewInstance {
instance.Status.Conditions = condition.Conditions{}
}

// Save a copy of the condtions so that we can restore the LastTransitionTime
// when a condition's state doesn't change.
savedConditions := instance.Status.Conditions.DeepCopy()

// Always patch the instance status when exiting this function so we can
// persist any changes.
defer func() {
// update the Ready condition based on the sub conditions
if instance.Status.Conditions.AllSubConditionIsTrue() {
instance.Status.Conditions.MarkTrue(
condition.ReadyCondition, condition.ReadyMessage)
} else {
// something is not ready so reset the Ready condition
instance.Status.Conditions.MarkUnknown(
condition.ReadyCondition, condition.InitReason, condition.ReadyInitMessage)
// and recalculate it based on the state of the rest of the conditions
condition.RestoreLastTransitionTimes(
&instance.Status.Conditions, savedConditions)
if instance.Status.Conditions.IsUnknown(condition.ReadyCondition) {
instance.Status.Conditions.Set(
instance.Status.Conditions.Mirror(condition.ReadyCondition))
}
Expand All @@ -121,32 +127,31 @@ func (r *SwiftReconciler) Reconcile(ctx context.Context, req ctrl.Request) (resu
}
}()

// If we're not deleting this and the service object doesn't have our finalizer, add it.
if instance.DeletionTimestamp.IsZero() && controllerutil.AddFinalizer(instance, helper.GetFinalizer()) {
return ctrl.Result{}, nil
}

// initialize status

if instance.Status.Conditions == nil {
instance.Status.Conditions = condition.Conditions{}
// initialize conditions used later as Status=Unknown
cl := condition.CreateList(
condition.UnknownCondition(condition.ServiceConfigReadyCondition, condition.InitReason, condition.ServiceConfigReadyInitMessage),
condition.UnknownCondition(swiftv1.SwiftProxyReadyCondition, condition.InitReason, swiftv1.SwiftProxyReadyInitMessage),
condition.UnknownCondition(swiftv1.SwiftRingReadyCondition, condition.InitReason, swiftv1.SwiftRingReadyInitMessage),
condition.UnknownCondition(swiftv1.SwiftStorageReadyCondition, condition.InitReason, swiftv1.SwiftStorageReadyInitMessage),
// service account, role, rolebinding conditions
condition.UnknownCondition(condition.ServiceAccountReadyCondition, condition.InitReason, condition.ServiceAccountReadyInitMessage),
condition.UnknownCondition(condition.RoleReadyCondition, condition.InitReason, condition.RoleReadyInitMessage),
condition.UnknownCondition(condition.RoleBindingReadyCondition, condition.InitReason, condition.RoleBindingReadyInitMessage),
condition.UnknownCondition(condition.MemcachedReadyCondition, condition.InitReason, condition.MemcachedReadyInitMessage),
)

instance.Status.Conditions.Init(&cl)

// Register overall status immediately to have an early feedback e.g. in the cli
return ctrl.Result{}, err
// initialize conditions used later as Status=Unknown
cl := condition.CreateList(
// Mark ReadyCondition as Unknown from the beginning, because the
// Reconcile function is in progress. If this condition is not marked
// as True and is still in the "Unknown" state, we `Mirror(` the actual
// failure/in-progress operation
condition.UnknownCondition(condition.ReadyCondition, condition.InitReason, condition.ReadyInitMessage),
condition.UnknownCondition(condition.ServiceConfigReadyCondition, condition.InitReason, condition.ServiceConfigReadyInitMessage),
condition.UnknownCondition(swiftv1.SwiftProxyReadyCondition, condition.InitReason, swiftv1.SwiftProxyReadyInitMessage),
condition.UnknownCondition(swiftv1.SwiftRingReadyCondition, condition.InitReason, swiftv1.SwiftRingReadyInitMessage),
condition.UnknownCondition(swiftv1.SwiftStorageReadyCondition, condition.InitReason, swiftv1.SwiftStorageReadyInitMessage),
// service account, role, rolebinding conditions
condition.UnknownCondition(condition.ServiceAccountReadyCondition, condition.InitReason, condition.ServiceAccountReadyInitMessage),
condition.UnknownCondition(condition.RoleReadyCondition, condition.InitReason, condition.RoleReadyInitMessage),
condition.UnknownCondition(condition.RoleBindingReadyCondition, condition.InitReason, condition.RoleBindingReadyInitMessage),
condition.UnknownCondition(condition.MemcachedReadyCondition, condition.InitReason, condition.MemcachedReadyInitMessage),
)

instance.Status.Conditions.Init(&cl)

// If we're not deleting this and the service object doesn't have our finalizer, add it.
if instance.DeletionTimestamp.IsZero() && controllerutil.AddFinalizer(instance, helper.GetFinalizer()) || isNewInstance {
return ctrl.Result{}, nil
}

// Handle service delete
Expand Down Expand Up @@ -329,6 +334,15 @@ func (r *SwiftReconciler) reconcileNormal(ctx context.Context, instance *swiftv1
}

r.Log.Info(fmt.Sprintf("Reconciled Service '%s' successfully", instance.Name))

// Update the lastObserved generation before evaluating conditions
instance.Status.ObservedGeneration = instance.Generation
// We reached the end of the Reconcile, update the Ready condition based on
// the sub conditions
if instance.Status.Conditions.AllSubConditionIsTrue() {
instance.Status.Conditions.MarkTrue(
condition.ReadyCondition, condition.ReadyMessage)
}
return ctrl.Result{}, nil
}

Expand Down
86 changes: 58 additions & 28 deletions controllers/swiftproxy_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,17 +112,26 @@ func (r *SwiftProxyReconciler) Reconcile(ctx context.Context, req ctrl.Request)
return ctrl.Result{}, err
}

// Always patch the instance status when exiting this function so we can persist any changes.
//
// initialize status
//
// initialize status if Conditions is nil, but do not reset if it
// already exists
isNewInstance := instance.Status.Conditions == nil
if isNewInstance {
instance.Status.Conditions = condition.Conditions{}
}

// Save a copy of the condtions so that we can restore the LastTransitionTime
// when a condition's state doesn't change.
savedConditions := instance.Status.Conditions.DeepCopy()

// Always patch the instance status when exiting this function so we can
// persist any changes.
defer func() {
// update the Ready condition based on the sub conditions
if instance.Status.Conditions.AllSubConditionIsTrue() {
instance.Status.Conditions.MarkTrue(
condition.ReadyCondition, condition.ReadyMessage)
} else {
// something is not ready so reset the Ready condition
instance.Status.Conditions.MarkUnknown(
condition.ReadyCondition, condition.InitReason, condition.ReadyInitMessage)
// and recalculate it based on the state of the rest of the conditions
condition.RestoreLastTransitionTimes(
&instance.Status.Conditions, savedConditions)
if instance.Status.Conditions.IsUnknown(condition.ReadyCondition) {
instance.Status.Conditions.Set(
instance.Status.Conditions.Mirror(condition.ReadyCondition))
}
Expand All @@ -133,27 +142,31 @@ func (r *SwiftProxyReconciler) Reconcile(ctx context.Context, req ctrl.Request)
}
}()

cl := condition.CreateList(
// Mark ReadyCondition as Unknown from the beginning, because the
// Reconcile function is in progress. If this condition is not marked
// as True and is still in the "Unknown" state, we `Mirror(` the actual
// failure/in-progress operation
condition.UnknownCondition(condition.ReadyCondition, condition.InitReason, condition.ReadyInitMessage),
condition.UnknownCondition(condition.InputReadyCondition, condition.InitReason, condition.InputReadyInitMessage),
condition.UnknownCondition(condition.ExposeServiceReadyCondition, condition.InitReason, condition.ExposeServiceReadyInitMessage),
condition.UnknownCondition(condition.NetworkAttachmentsReadyCondition, condition.InitReason, condition.NetworkAttachmentsReadyInitMessage),
condition.UnknownCondition(swiftv1beta1.SwiftProxyReadyCondition, condition.InitReason, swiftv1beta1.SwiftProxyReadyInitMessage),
condition.UnknownCondition(condition.TLSInputReadyCondition, condition.InitReason, condition.InputReadyInitMessage),
condition.UnknownCondition(condition.ServiceConfigReadyCondition, condition.InitReason, condition.ServiceConfigReadyInitMessage),
// right now we have no dedicated KeystoneServiceReadyInitMessage and KeystoneEndpointReadyInitMessage
condition.UnknownCondition(condition.KeystoneServiceReadyCondition, condition.InitReason, ""),
condition.UnknownCondition(condition.KeystoneEndpointReadyCondition, condition.InitReason, ""),
)

instance.Status.Conditions.Init(&cl)

// If we're not deleting this and the service object doesn't have our finalizer, add it.
if instance.DeletionTimestamp.IsZero() && controllerutil.AddFinalizer(instance, helper.GetFinalizer()) {
if instance.DeletionTimestamp.IsZero() && controllerutil.AddFinalizer(instance, helper.GetFinalizer()) || isNewInstance {
return ctrl.Result{}, nil
}

if instance.Status.Conditions == nil {
instance.Status.Conditions = condition.Conditions{}
cl := condition.CreateList(
condition.UnknownCondition(condition.InputReadyCondition, condition.InitReason, condition.InputReadyInitMessage),
condition.UnknownCondition(condition.ExposeServiceReadyCondition, condition.InitReason, condition.ExposeServiceReadyInitMessage),
condition.UnknownCondition(condition.NetworkAttachmentsReadyCondition, condition.InitReason, condition.NetworkAttachmentsReadyInitMessage),
condition.UnknownCondition(swiftv1beta1.SwiftProxyReadyCondition, condition.InitReason, swiftv1beta1.SwiftProxyReadyInitMessage),
condition.UnknownCondition(condition.TLSInputReadyCondition, condition.InitReason, condition.InputReadyInitMessage),
condition.UnknownCondition(condition.ServiceConfigReadyCondition, condition.InitReason, condition.ServiceConfigReadyInitMessage),
// right now we have no dedicated KeystoneServiceReadyInitMessage and KeystoneEndpointReadyInitMessage
condition.UnknownCondition(condition.KeystoneServiceReadyCondition, condition.InitReason, ""),
condition.UnknownCondition(condition.KeystoneEndpointReadyCondition, condition.InitReason, ""),
)

instance.Status.Conditions.Init(&cl)

if isNewInstance {
if err := r.Status().Update(ctx, instance); err != nil {
return ctrl.Result{}, err
}
Expand Down Expand Up @@ -192,6 +205,12 @@ func (r *SwiftProxyReconciler) Reconcile(ctx context.Context, req ctrl.Request)
err.Error()))
return ctrlResult, err
} else if (ctrlResult != ctrl.Result{}) {
instance.Status.Conditions.Set(condition.FalseCondition(
condition.TLSInputReadyCondition,
condition.ErrorReason,
condition.SeverityWarning,
condition.TLSInputErrorMessage,
err.Error()))
return ctrlResult, nil
}

Expand All @@ -211,6 +230,12 @@ func (r *SwiftProxyReconciler) Reconcile(ctx context.Context, req ctrl.Request)
err.Error()))
return ctrlResult, err
} else if (ctrlResult != ctrl.Result{}) {
instance.Status.Conditions.Set(condition.FalseCondition(
condition.TLSInputReadyCondition,
condition.ErrorReason,
condition.SeverityWarning,
condition.TLSInputErrorMessage,
err.Error()))
return ctrlResult, nil
}
envVars[tls.TLSHashName] = env.SetValue(certsHash)
Expand Down Expand Up @@ -595,7 +620,12 @@ func (r *SwiftProxyReconciler) Reconcile(ctx context.Context, req ctrl.Request)
condition.SeverityInfo,
condition.DeploymentReadyRunningMessage))
}

// We reached the end of the Reconcile, update the Ready condition based on
// the sub conditions
if instance.Status.Conditions.AllSubConditionIsTrue() {
instance.Status.Conditions.MarkTrue(
condition.ReadyCondition, condition.ReadyMessage)
}
r.Log.Info(fmt.Sprintf("Reconciled SwiftProxy '%s' successfully", instance.Name))
return ctrl.Result{}, nil
}
Expand Down
58 changes: 38 additions & 20 deletions controllers/swiftring_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,26 @@ func (r *SwiftRingReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
return ctrl.Result{}, err
}

// Always patch the instance status when exiting this function so we can persist any changes.
//
// initialize status
//
// initialize status if Conditions is nil, but do not reset if it
// already exists
isNewInstance := instance.Status.Conditions == nil
if isNewInstance {
instance.Status.Conditions = condition.Conditions{}
}

// Save a copy of the condtions so that we can restore the LastTransitionTime
// when a condition's state doesn't change.
savedConditions := instance.Status.Conditions.DeepCopy()

// Always patch the instance status when exiting this function so we can
// persist any changes.
defer func() {
// update the Ready condition based on the sub conditions
if instance.Status.Conditions.AllSubConditionIsTrue() {
instance.Status.Conditions.MarkTrue(
condition.ReadyCondition, condition.ReadyMessage)
} else {
// something is not ready so reset the Ready condition
instance.Status.Conditions.MarkUnknown(
condition.ReadyCondition, condition.InitReason, condition.ReadyInitMessage)
// and recalculate it based on the state of the rest of the conditions
condition.RestoreLastTransitionTimes(
&instance.Status.Conditions, savedConditions)
if instance.Status.Conditions.IsUnknown(condition.ReadyCondition) {
instance.Status.Conditions.Set(
instance.Status.Conditions.Mirror(condition.ReadyCondition))
}
Expand All @@ -121,20 +130,23 @@ func (r *SwiftRingReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
}
}()

cl := condition.CreateList(
// Mark ReadyCondition as Unknown from the beginning, because the
// Reconcile function is in progress. If this condition is not marked
// as True and is still in the "Unknown" state, we `Mirror(` the actual
// failure/in-progress operation
condition.UnknownCondition(condition.ReadyCondition, condition.InitReason, condition.ReadyInitMessage),
condition.UnknownCondition(swiftv1beta1.SwiftRingReadyCondition, condition.InitReason, condition.ReadyInitMessage),
)

instance.Status.Conditions.Init(&cl)

// If we're not deleting this and the service object doesn't have our finalizer, add it.
if instance.DeletionTimestamp.IsZero() && controllerutil.AddFinalizer(instance, helper.GetFinalizer()) {
if instance.DeletionTimestamp.IsZero() && controllerutil.AddFinalizer(instance, helper.GetFinalizer()) || isNewInstance {
return ctrl.Result{}, nil
}

if instance.Status.Conditions == nil {
instance.Status.Conditions = condition.Conditions{}
cl := condition.CreateList(
condition.UnknownCondition(condition.ReadyCondition, condition.InitReason, condition.ReadyInitMessage),
condition.UnknownCondition(swiftv1beta1.SwiftRingReadyCondition, condition.InitReason, condition.ReadyInitMessage),
)

instance.Status.Conditions.Init(&cl)

if isNewInstance {
if err := r.Status().Update(ctx, instance); err != nil {
return ctrl.Result{}, err
}
Expand Down Expand Up @@ -240,6 +252,12 @@ func (r *SwiftRingReconciler) reconcileNormal(ctx context.Context, instance *swi
}
// Swift ring init job - end

// We reached the end of the Reconcile, update the Ready condition based on
// the sub conditions
if instance.Status.Conditions.AllSubConditionIsTrue() {
instance.Status.Conditions.MarkTrue(
condition.ReadyCondition, condition.ReadyMessage)
}
r.Log.Info(fmt.Sprintf("Reconciled SwiftRing '%s' successfully", instance.Name))
return ctrl.Result{}, nil
}
Expand Down
Loading

0 comments on commit 0fa4390

Please sign in to comment.