Skip to content

Commit e52d35e

Browse files
drivebyercndoit18
authored andcommitted
Wait cluster ready before creating user or database
Signed-off-by: drivebyer <[email protected]>
1 parent c403729 commit e52d35e

File tree

5 files changed

+59
-2
lines changed

5 files changed

+59
-2
lines changed

pkg/controller/mysqldatabase/db_controller.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"context"
2121
"fmt"
2222
"reflect"
23+
"time"
2324

2425
"github.com/go-test/deep"
2526
logf "github.com/presslabs/controller-util/log"
@@ -69,6 +70,7 @@ var _ reconcile.Reconciler = &ReconcileMySQLDatabase{}
6970

7071
// Reconcile reads that state of the cluster for a Wordpress object and makes changes based on the state read
7172
// and what is in the Wordpress.Spec
73+
// nolint: gocyclo
7274
func (r *ReconcileMySQLDatabase) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
7375
// Fetch the MysqlDatabase instance
7476
db := mysqldatabase.Wrap(&mysqlv1alpha1.MysqlDatabase{})
@@ -105,6 +107,23 @@ func (r *ReconcileMySQLDatabase) Reconcile(ctx context.Context, request reconcil
105107
return reconcile.Result{}, r.Update(ctx, db.Unwrap())
106108
}
107109

110+
cluster := mysqlcluster.New(&mysqlv1alpha1.MysqlCluster{})
111+
if err = r.Get(ctx, db.GetClusterKey(), cluster.Unwrap()); err != nil {
112+
return reconcile.Result{}, r.updateReadyCondition(ctx, oldDBStatus, db, err)
113+
}
114+
115+
if !cluster.IsClusterReady() {
116+
117+
log.Error(r.updateReadyCondition(ctx, oldDBStatus, db, fmt.Errorf("cluster is not ready")),
118+
"cluster is not ready when create database",
119+
"cluster", cluster.GetNamespacedName())
120+
121+
// The MysqlCluster and MysqlDatabase are separate Custom Resources (CRs). We typically apply both CRs at the same time.
122+
// If the MysqlCluster is not ready, the database creation will fail. The requeue time becomes exponential when an error is returned.
123+
// Therefore, we return a nil error here and specify the RequeueAfter to avoid the exponential requeue time.
124+
return reconcile.Result{RequeueAfter: 30 * time.Second}, nil
125+
}
126+
108127
// reconcile database in mysql
109128
err = r.createDatabase(ctx, db)
110129
if err != nil {

pkg/controller/mysqluser/mysqluser_controller.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,26 @@ func (r *ReconcileMySQLUser) Reconcile(ctx context.Context, request reconcile.Re
9797
return reconcile.Result{}, r.removeUser(ctx, user)
9898
}
9999

100+
cluster := mysqlcluster.New(&mysqlv1alpha1.MysqlCluster{})
101+
if err = r.Get(ctx, user.GetClusterKey(), cluster.Unwrap()); err != nil {
102+
return reconcile.Result{}, err
103+
}
104+
105+
if !cluster.IsClusterReady() {
106+
user.UpdateStatusCondition(
107+
mysqlv1alpha1.MySQLUserReady, corev1.ConditionFalse,
108+
mysqluser.ProvisionFailedReason, "cluster is not ready",
109+
)
110+
log.Error(r.updateStatusAndErr(ctx, user, oldStatus, fmt.Errorf("cluster is not ready")),
111+
"cluster is not ready when create user",
112+
"cluster", cluster.GetNamespacedName())
113+
114+
// The MysqlCluster and MysqlUser are separate Custom Resources (CRs). We typically apply both CRs at the same time.
115+
// If the MysqlCluster is not ready, the user creation will fail. The requeue time becomes exponential when an error is returned.
116+
// Therefore, we return a nil error here and specify the RequeueAfter to avoid the exponential requeue time.
117+
return reconcile.Result{RequeueAfter: 30 * time.Second}, nil
118+
}
119+
100120
// write the desired status into mysql cluster
101121
ruErr := r.reconcileUserInCluster(ctx, user)
102122
if err := r.updateStatusAndErr(ctx, user, oldStatus, ruErr); err != nil {

pkg/controller/mysqluser/mysqluser_controller_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ var _ = Describe("MySQL user controller", func() {
120120
BeforeEach(func() {
121121
// Create prerequisite resources
122122
cluster = factories.NewMySQLCluster(
123+
factories.WithClusterReadyCondition(),
123124
factories.CreateMySQLClusterSecret(c, &corev1.Secret{}),
124125
factories.CreateMySQLClusterInK8s(c),
125126
)
@@ -201,6 +202,7 @@ var _ = Describe("MySQL user controller", func() {
201202
BeforeEach(func() {
202203
// Create prerequisite resources
203204
cluster = factories.NewMySQLCluster(
205+
factories.WithClusterReadyCondition(),
204206
factories.CreateMySQLClusterSecret(c, &corev1.Secret{}),
205207
factories.CreateMySQLClusterInK8s(c),
206208
)
@@ -302,6 +304,7 @@ var _ = Describe("MySQL user controller", func() {
302304

303305
// Create prerequisite resources
304306
cluster = factories.NewMySQLCluster(
307+
factories.WithClusterReadyCondition(),
305308
factories.CreateMySQLClusterSecret(c, &corev1.Secret{}),
306309
factories.CreateMySQLClusterInK8s(c),
307310
)
@@ -394,7 +397,9 @@ var _ = Describe("MySQL user controller", func() {
394397
BeforeEach(func() {
395398
// Create prerequisite resources
396399
cluster = factories.NewMySQLCluster(
397-
factories.CreateMySQLClusterSecret(c, &corev1.Secret{}), factories.CreateMySQLClusterInK8s(c),
400+
factories.WithClusterReadyCondition(),
401+
factories.CreateMySQLClusterSecret(c, &corev1.Secret{}),
402+
factories.CreateMySQLClusterInK8s(c),
398403
)
399404

400405
// The mysql user creation fails
@@ -444,6 +449,7 @@ var _ = Describe("MySQL user controller", func() {
444449
BeforeEach(func() {
445450
// Create prerequisite resources
446451
cluster = factories.NewMySQLCluster(
452+
factories.WithClusterReadyCondition(),
447453
factories.CreateMySQLClusterSecret(c, &corev1.Secret{}),
448454
factories.CreateMySQLClusterInK8s(c),
449455
)

pkg/internal/mysqlcluster/mysqlcluster.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,18 @@ func (c *MysqlCluster) GetSidecarImage() string {
277277
return sidecarImage
278278
}
279279

280+
// IsClusterReady checks if the cluster is ready or not.
281+
func (c *MysqlCluster) IsClusterReady() bool {
282+
isReady := false
283+
for _, cond := range c.Status.Conditions {
284+
if cond.Type == api.ClusterConditionReady && cond.Status == core.ConditionTrue {
285+
isReady = true
286+
break
287+
}
288+
}
289+
return isReady
290+
}
291+
280292
// IsMysqlClusterKind for the given kind checks if CRD kind is for MysqlCluster CRD
281293
func IsMysqlClusterKind(kind string) bool {
282294
switch kind {

pkg/testutil/factories/mysql_database.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func WithMySQLCluster(ctx context.Context, cl client.Client, name string) MysqlD
4040
cluster := NewMySQLCluster(func(cluster *mysqlv1alpha1.MysqlCluster) error {
4141
cluster.Name = name
4242
return nil
43-
}, CreateMySQLClusterSecret(cl, &corev1.Secret{}), CreateMySQLClusterInK8s(cl))
43+
}, CreateMySQLClusterSecret(cl, &corev1.Secret{}), WithClusterReadyCondition(), CreateMySQLClusterInK8s(cl))
4444

4545
return func(db *mysqldatabase.Database) error {
4646
db.Spec.ClusterRef.Name = cluster.Name

0 commit comments

Comments
 (0)