Skip to content

Commit

Permalink
Merge pull request #213 from fmount/conditions
Browse files Browse the repository at this point in the history
Re-init conditions each reconcile
  • Loading branch information
dprince authored Apr 3, 2024
2 parents 40cf3e6 + d8c4cc1 commit 75b048d
Show file tree
Hide file tree
Showing 9 changed files with 163 additions and 132 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ $(CONTROLLER_GEN): $(LOCALBIN)
.PHONY: envtest
envtest: $(ENVTEST) ## Download envtest-setup locally if necessary.
$(ENVTEST): $(LOCALBIN)
test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest
test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@c7e1dc9b

.PHONY: ginkgo
ginkgo: $(GINKGO) ## Download ginkgo locally if necessary.
Expand Down
8 changes: 8 additions & 0 deletions api/bases/mariadb.openstack.org_galeras.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,14 @@ spec:
type: string
description: Map of hashes to track input changes
type: object
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
safeToBootstrap:
description: Name of the node that can safely bootstrap a cluster
type: string
Expand Down
5 changes: 5 additions & 0 deletions api/v1beta1/galera_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ type GaleraStatus struct {
Hash map[string]string `json:"hash,omitempty"`
// Deployment 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/mariadb.openstack.org_galeras.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,14 @@ spec:
type: string
description: Map of hashes to track input changes
type: object
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
safeToBootstrap:
description: Name of the node that can safely bootstrap a cluster
type: string
Expand Down
78 changes: 43 additions & 35 deletions controllers/galera_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -356,17 +356,23 @@ func (r *GaleraReconciler) Reconcile(ctx context.Context, req ctrl.Request) (res
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 @@ -383,31 +389,26 @@ func (r *GaleraReconciler) Reconcile(ctx context.Context, req ctrl.Request) (res
if instance.Status.Attributes == nil {
instance.Status.Attributes = make(map[string]mariadbv1.GaleraAttributes)
}
if instance.Status.Conditions == nil {
instance.Status.Conditions = condition.Conditions{}
// initialize conditions used later as Status=Unknown
cl := condition.CreateList(
// DB Root password
condition.UnknownCondition(condition.InputReadyCondition, condition.InitReason, condition.InputReadyInitMessage),
// TLS cert secrets
condition.UnknownCondition(condition.TLSInputReadyCondition, condition.InitReason, condition.InputReadyInitMessage),
// endpoint for adoption redirect
condition.UnknownCondition(condition.ExposeServiceReadyCondition, condition.InitReason, condition.ExposeServiceReadyInitMessage),
// configmap generation
condition.UnknownCondition(condition.ServiceConfigReadyCondition, condition.InitReason, condition.ServiceConfigReadyInitMessage),
// cluster bootstrap
condition.UnknownCondition(condition.DeploymentReadyCondition, condition.InitReason, condition.DeploymentReadyInitMessage),
// service account, role, rolebinding
condition.UnknownCondition(condition.ServiceAccountReadyCondition, condition.InitReason, condition.ServiceAccountReadyInitMessage),
condition.UnknownCondition(condition.RoleReadyCondition, condition.InitReason, condition.RoleReadyInitMessage),
condition.UnknownCondition(condition.RoleBindingReadyCondition, condition.InitReason, condition.RoleBindingReadyInitMessage),
)

instance.Status.Conditions.Init(&cl)

// Register overall status immediately to have an early feedback e.g. in the cli
return ctrl.Result{}, nil
}
// initialize conditions used later as Status=Unknown
cl := condition.CreateList(
condition.UnknownCondition(condition.ReadyCondition, condition.InitReason, condition.ReadyInitMessage),
// DB Root password
condition.UnknownCondition(condition.InputReadyCondition, condition.InitReason, condition.InputReadyInitMessage),
// TLS cert secrets
condition.UnknownCondition(condition.TLSInputReadyCondition, condition.InitReason, condition.InputReadyInitMessage),
// endpoint for adoption redirect
condition.UnknownCondition(condition.ExposeServiceReadyCondition, condition.InitReason, condition.ExposeServiceReadyInitMessage),
// configmap generation
condition.UnknownCondition(condition.ServiceConfigReadyCondition, condition.InitReason, condition.ServiceConfigReadyInitMessage),
// cluster bootstrap
condition.UnknownCondition(condition.DeploymentReadyCondition, condition.InitReason, condition.DeploymentReadyInitMessage),
// service account, role, rolebinding
condition.UnknownCondition(condition.ServiceAccountReadyCondition, condition.InitReason, condition.ServiceAccountReadyInitMessage),
condition.UnknownCondition(condition.RoleReadyCondition, condition.InitReason, condition.RoleReadyInitMessage),
condition.UnknownCondition(condition.RoleBindingReadyCondition, condition.InitReason, condition.RoleBindingReadyInitMessage),
)

instance.Status.Conditions.Init(&cl)

//
// Service account, role, binding
Expand Down Expand Up @@ -697,6 +698,13 @@ func (r *GaleraReconciler) Reconcile(ctx context.Context, req ctrl.Request) (res
return ctrl.Result{RequeueAfter: time.Duration(3) * time.Second}, nil
}

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

Expand Down
57 changes: 31 additions & 26 deletions controllers/mariadbaccount_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,45 +82,44 @@ func (r *MariaDBAccountReconciler) Reconcile(ctx context.Context, req ctrl.Reque
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))
}

err := helper.PatchInstance(ctx, instance)
if err != nil {
_err = err
return
}
}()

if instance.Status.Conditions == nil {
instance.Status.Conditions = condition.Conditions{}

// initialize conditions used later as Status=Unknown
cl := condition.CreateList(
condition.UnknownCondition(databasev1beta1.MariaDBServerReadyCondition, condition.InitReason, databasev1beta1.MariaDBServerReadyInitMessage),
condition.UnknownCondition(databasev1beta1.MariaDBDatabaseReadyCondition, condition.InitReason, databasev1beta1.MariaDBDatabaseReadyInitMessage),
condition.UnknownCondition(databasev1beta1.MariaDBAccountReadyCondition, condition.InitReason, databasev1beta1.MariaDBAccountReadyInitMessage),
)
// initialize conditions used later as Status=Unknown
cl := condition.CreateList(
condition.UnknownCondition(condition.ReadyCondition, condition.InitReason, condition.ReadyInitMessage),
condition.UnknownCondition(databasev1beta1.MariaDBServerReadyCondition, condition.InitReason, databasev1beta1.MariaDBServerReadyInitMessage),
condition.UnknownCondition(databasev1beta1.MariaDBDatabaseReadyCondition, condition.InitReason, databasev1beta1.MariaDBDatabaseReadyInitMessage),
condition.UnknownCondition(databasev1beta1.MariaDBAccountReadyCondition, condition.InitReason, databasev1beta1.MariaDBAccountReadyInitMessage),
)

instance.Status.Conditions.Init(&cl)
instance.Status.Conditions.Init(&cl)

// Register overall status immediately to have an early feedback e.g. in the cli
return ctrl.Result{}, nil
}

if instance.DeletionTimestamp.IsZero() {
if instance.DeletionTimestamp.IsZero() || isNewInstance {
return r.reconcileCreate(ctx, req, log, helper, instance)
} else {
return r.reconcileDelete(ctx, req, log, helper, instance)
Expand Down Expand Up @@ -317,6 +316,12 @@ func (r *MariaDBAccountReconciler) reconcileCreate(
databasev1beta1.MariaDBAccountReadyMessage,
)

// 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
59 changes: 30 additions & 29 deletions controllers/mariadbdatabase_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,50 +72,45 @@ func (r *MariaDBDatabaseReconciler) Reconcile(ctx context.Context, req ctrl.Requ
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() {
if instance.Status.Conditions.AllSubConditionIsTrue() {
// update the Ready condition based on the sub conditions

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))
}

if instance.Status.Conditions.IsTrue(condition.ReadyCondition) {
// database creation finished... okay to set to completed
instance.Status.Completed = true
}

err := helper.PatchInstance(ctx, instance)

if err != nil {
_err = err
return
}

}()

if instance.Status.Conditions == nil {
instance.Status.Conditions = condition.Conditions{}

// initialize conditions used later as Status=Unknown
cl := condition.CreateList(
condition.UnknownCondition(databasev1beta1.MariaDBServerReadyCondition, condition.InitReason, databasev1beta1.MariaDBServerReadyInitMessage),
condition.UnknownCondition(databasev1beta1.MariaDBDatabaseReadyCondition, condition.InitReason, databasev1beta1.MariaDBDatabaseReadyInitMessage),
)

instance.Status.Conditions.Init(&cl)
// initialize conditions used later as Status=Unknown
cl := condition.CreateList(
condition.UnknownCondition(condition.ReadyCondition, condition.InitReason, condition.ReadyInitMessage),
condition.UnknownCondition(databasev1beta1.MariaDBServerReadyCondition, condition.InitReason, databasev1beta1.MariaDBServerReadyInitMessage),
condition.UnknownCondition(databasev1beta1.MariaDBDatabaseReadyCondition, condition.InitReason, databasev1beta1.MariaDBDatabaseReadyInitMessage),
)

// Register overall status immediately to have an early feedback e.g. in the cli
return ctrl.Result{}, nil
}
instance.Status.Conditions.Init(&cl)

// Fetch the Galera instance from which we'll pull the credentials
dbGalera, err := r.getDatabaseObject(ctx, instance)
Expand Down Expand Up @@ -149,7 +144,7 @@ func (r *MariaDBDatabaseReconciler) Reconcile(ctx context.Context, req ctrl.Requ
}

// here we know that Galera exists so add a finalizer to ourselves and to the db CR. Before this point there is no reason to have a finalizer on ourselves as nothing to cleanup.
if instance.DeletionTimestamp.IsZero() { // this condition can be removed if you wish as it is always true at this point otherwise we would returned earlier.
if instance.DeletionTimestamp.IsZero() || isNewInstance { // this condition can be removed if you wish as it is always true at this point otherwise we would returned earlier.
if controllerutil.AddFinalizer(dbGalera, fmt.Sprintf("%s-%s", helper.GetFinalizer(), instance.Name)) {
err := r.Update(ctx, dbGalera)
if err != nil {
Expand Down Expand Up @@ -234,6 +229,12 @@ func (r *MariaDBDatabaseReconciler) Reconcile(ctx context.Context, req ctrl.Requ
// DB instances supports TLS
instance.Status.TLSSupport = dbGalera.Spec.TLS.Enabled()

// 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
24 changes: 12 additions & 12 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ go 1.20

require (
github.com/go-logr/logr v1.4.1
github.com/onsi/ginkgo/v2 v2.15.0
github.com/onsi/ginkgo/v2 v2.16.0
github.com/onsi/gomega v1.31.1
github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240214144842-5dcac51e5b36
github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240402131709-f2ff3c9b230b
github.com/openstack-k8s-operators/mariadb-operator/api v0.3.0
golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3
k8s.io/api v0.28.3
k8s.io/apimachinery v0.28.3
k8s.io/client-go v0.28.3
k8s.io/api v0.28.8
k8s.io/apimachinery v0.28.8
k8s.io/client-go v0.28.8
k8s.io/kubectl v0.26.12
sigs.k8s.io/controller-runtime v0.16.4
sigs.k8s.io/controller-runtime v0.16.5
)

require (
Expand All @@ -30,7 +30,7 @@ require (
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
Expand All @@ -52,7 +52,7 @@ require (
github.com/prometheus/procfs v0.10.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.26.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/net v0.20.0 // indirect
golang.org/x/oauth2 v0.8.0 // indirect
golang.org/x/sys v0.16.0 // indirect
Expand All @@ -62,15 +62,15 @@ require (
golang.org/x/tools v0.17.0 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.31.0 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apiextensions-apiserver v0.28.3 // indirect
k8s.io/component-base v0.28.3 // indirect
k8s.io/apiextensions-apiserver v0.28.8 // indirect
k8s.io/component-base v0.28.8 // indirect
k8s.io/klog/v2 v2.110.1 // indirect
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
k8s.io/utils v0.0.0-20240102154912-e7106e64919e // indirect
k8s.io/utils v0.0.0-20240310230437-4693a0247e57 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
Expand Down
Loading

0 comments on commit 75b048d

Please sign in to comment.