Skip to content

Commit

Permalink
link MariaDBAccount to the Database api
Browse files Browse the repository at this point in the history
This replaces the MariaDBDatabase.secret attribute
with the use of MariaDBAccount instead.

also applies an interim fix to allow the encoding/collation to be
present in the Database API, otherwise the database pod would fail.

Amends MariaDBAccount to return from delete if the owning Galera
resource is already deleted.
  • Loading branch information
zzzeek committed Jan 15, 2024
1 parent 282488b commit d5c1598
Show file tree
Hide file tree
Showing 12 changed files with 127 additions and 62 deletions.
6 changes: 0 additions & 6 deletions api/bases/mariadb.openstack.org_mariadbdatabases.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,6 @@ spec:
name:
description: Name of the database in MariaDB
type: string
secret:
description: Name of secret which contains DatabasePassword
type: string
required:
- defaultCharacterSet
- defaultCollation
type: object
status:
description: MariaDBDatabaseStatus defines the observed state of MariaDBDatabase
Expand Down
110 changes: 106 additions & 4 deletions api/v1beta1/mariadbdatabase_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ func (d *Database) GetDatabase() *MariaDBDatabase {
return d.database
}

// GetAccount - returns the account
func (d *Database) GetAccount() *MariaDBAccount {
return d.account
}

// CreateOrPatchDB - create or patch the service DB instance
// Deprecated. Use CreateOrPatchDBByName instead. If you want to use the
// default the DB service instance of the deployment then pass "openstack" as
Expand Down Expand Up @@ -162,6 +167,22 @@ func (d *Database) CreateOrPatchDBByName(
}
}

account := d.account
if account == nil {
account = &MariaDBAccount{
ObjectMeta: metav1.ObjectMeta{
Name: d.databaseUser,
Namespace: d.namespace,
Labels: map[string]string{
"mariaDBDatabaseName": d.name,
},
},
Spec: MariaDBAccountSpec{
UserName: d.databaseUser,
Secret: d.secret,
},
}
}
// set the database hostname on the db instance
err := d.setDatabaseHostname(ctx, h, name)
if err != nil {
Expand All @@ -174,8 +195,6 @@ func (d *Database) CreateOrPatchDBByName(
d.labels,
)

db.Spec.Secret = d.secret

err := controllerutil.SetControllerReference(h.GetBeforeObject(), db, h.GetScheme())
if err != nil {
return err
Expand All @@ -200,6 +219,36 @@ func (d *Database) CreateOrPatchDBByName(
return ctrl.Result{RequeueAfter: time.Second * 5}, nil
}

op_acc, err_acc := controllerutil.CreateOrPatch(ctx, h.GetClient(), account, func() error {
account.Labels = util.MergeStringMaps(
account.GetLabels(),
d.labels,
)

err := controllerutil.SetControllerReference(h.GetBeforeObject(), account, h.GetScheme())
if err != nil {
return err
}

// If the service object doesn't have our finalizer, add it.
controllerutil.AddFinalizer(account, h.GetFinalizer())

return nil
})

if err_acc != nil && !k8s_errors.IsNotFound(err_acc) {
return ctrl.Result{}, util.WrapErrorForObject(
fmt.Sprintf("Error create or update account object %s", account.Name),
account,
err_acc,
)
}

if op_acc != controllerutil.OperationResultNone {
util.LogForObject(h, fmt.Sprintf("Account object %s created or patched", account.Name), account)
return ctrl.Result{RequeueAfter: time.Second * 5}, nil
}

err = d.getDBWithName(
ctx,
h,
Expand All @@ -211,7 +260,9 @@ func (d *Database) CreateOrPatchDBByName(
return ctrl.Result{}, nil
}

// WaitForDBCreatedWithTimeout - wait until the MariaDBDatabase is initialized and reports Status.Completed == true
// WaitForDBCreatedWithTimeout - wait until the MariaDBDatabase and MariaDBAccounts are
// initialized and reports Status.Conditions.IsTrue(MariaDBDatabaseReadyCondition)
// and Status.Conditions.IsTrue(MariaDBAccountReadyCondition)
func (d *Database) WaitForDBCreatedWithTimeout(
ctx context.Context,
h *helper.Helper,
Expand All @@ -226,7 +277,7 @@ func (d *Database) WaitForDBCreatedWithTimeout(
return ctrl.Result{}, err
}

if !d.database.Status.Completed || k8s_errors.IsNotFound(err) {
if !d.database.Status.Conditions.IsTrue(MariaDBDatabaseReadyCondition) {
util.LogForObject(
h,
fmt.Sprintf("Waiting for service DB %s to be created", d.database.Name),
Expand All @@ -236,6 +287,26 @@ func (d *Database) WaitForDBCreatedWithTimeout(
return ctrl.Result{RequeueAfter: requeueAfter}, nil
}

if !d.account.Status.Conditions.IsTrue(MariaDBAccountReadyCondition) {
util.LogForObject(
h,
fmt.Sprintf("Waiting for service account %s to be created", d.account.Name),
d.account,
)

return ctrl.Result{RequeueAfter: requeueAfter}, nil
}

if k8s_errors.IsNotFound(err) {
util.LogForObject(
h,
fmt.Sprintf("DB or account objects not yet found %s", d.database.Name),
d.database,
)

return ctrl.Result{RequeueAfter: requeueAfter}, nil
}

return ctrl.Result{}, nil
}

Expand All @@ -262,13 +333,15 @@ func (d *Database) getDBWithName(
if namespace == "" {
namespace = h.GetBeforeObject().GetNamespace()
}

err := h.GetClient().Get(
ctx,
types.NamespacedName{
Name: name,
Namespace: namespace,
},
db)

if err != nil {
if k8s_errors.IsNotFound(err) {
return util.WrapErrorForObject(
Expand All @@ -287,6 +360,35 @@ func (d *Database) getDBWithName(

d.database = db

account := &MariaDBAccount{}
username := d.databaseUser

err = h.GetClient().Get(
ctx,
types.NamespacedName{
Name: username,
Namespace: namespace,
},
account)

if err != nil {
if k8s_errors.IsNotFound(err) {
return util.WrapErrorForObject(
fmt.Sprintf("Failed to get %s account %s ", username, namespace),
h.GetBeforeObject(),
err,
)
}

return util.WrapErrorForObject(
fmt.Sprintf("account error %s %s ", username, namespace),
h.GetBeforeObject(),
err,
)
}

d.account = account

return nil
}

Expand Down
7 changes: 3 additions & 4 deletions api/v1beta1/mariadbdatabase_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,14 @@ const (

// MariaDBDatabaseSpec defines the desired state of MariaDBDatabase
type MariaDBDatabaseSpec struct {
// Name of secret which contains DatabasePassword
Secret string `json:"secret,omitempty"`
// Name of the database in MariaDB
Name string `json:"name,omitempty"`
// +kubebuilder:default=utf8
// Default character set for this database
DefaultCharacterSet string `json:"defaultCharacterSet"`
DefaultCharacterSet string `json:"defaultCharacterSet,omitempty"`
// +kubebuilder:default=utf8_general_ci
// Default collation for this database
DefaultCollation string `json:"defaultCollation"`
DefaultCollation string `json:"defaultCollation,omitempty"`
}

// MariaDBDatabaseStatus defines the observed state of MariaDBDatabase
Expand Down Expand Up @@ -88,6 +86,7 @@ const (
// Database -
type Database struct {
database *MariaDBDatabase
account *MariaDBAccount
databaseHostname string
databaseName string
databaseUser string
Expand Down
5 changes: 5 additions & 0 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 0 additions & 6 deletions config/crd/bases/mariadb.openstack.org_mariadbdatabases.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,6 @@ spec:
name:
description: Name of the database in MariaDB
type: string
secret:
description: Name of secret which contains DatabasePassword
type: string
required:
- defaultCharacterSet
- defaultCollation
type: object
status:
description: MariaDBDatabaseStatus defines the observed state of MariaDBDatabase
Expand Down
19 changes: 11 additions & 8 deletions controllers/mariadbaccount_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -429,16 +429,19 @@ func (r *MariaDBAccountReconciler) reconcileDelete(

// remove local finalizer
controllerutil.RemoveFinalizer(instance, helper.GetFinalizer())
}

instance.Status.Conditions.Set(condition.FalseCondition(
databasev1beta1.MariaDBServerReadyCondition,
condition.ErrorReason,
condition.SeverityError,
"Error retrieving MariaDB/Galera instance %s",
err))
// galera DB does not exist, so return
return ctrl.Result{}, nil
} else {
instance.Status.Conditions.Set(condition.FalseCondition(
databasev1beta1.MariaDBServerReadyCondition,
condition.ErrorReason,
condition.SeverityError,
"Error retrieving MariaDB/Galera instance %s",
err))

return ctrl.Result{}, err
return ctrl.Result{}, err
}
}

var dbInstance, dbAdminSecret, dbContainerImage, serviceAccountName string
Expand Down
11 changes: 0 additions & 11 deletions pkg/mariadb/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,17 +66,6 @@ func DbDatabaseJob(database *databasev1beta1.MariaDBDatabase, databaseHostName s
},
},
},
{
Name: "DatabasePassword",
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: database.Spec.Secret,
},
Key: "DatabasePassword",
},
},
},
},
},
},
Expand Down
3 changes: 1 addition & 2 deletions templates/database.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#!/bin/bash
export DatabasePassword=${DatabasePassword:?"Please specify a DatabasePassword variable."}

mysql -h {{.DatabaseHostname}} -u {{.DatabaseAdminUsername}} -P 3306 -e "CREATE DATABASE IF NOT EXISTS {{.DatabaseName}}; ALTER DATABASE {{.DatabaseName}} CHARACTER SET '{{.DefaultCharacterSet}}' COLLATE '{{.DefaultCollation}}'; GRANT ALL PRIVILEGES ON {{.DatabaseName}}.* TO '{{.DatabaseName}}'@'localhost' IDENTIFIED BY '$DatabasePassword';GRANT ALL PRIVILEGES ON {{.DatabaseName}}.* TO '{{.DatabaseName}}'@'%' IDENTIFIED BY '$DatabasePassword';"
mysql -h {{.DatabaseHostname}} -u {{.DatabaseAdminUsername}} -P 3306 -e "CREATE DATABASE IF NOT EXISTS {{.DatabaseName}}; ALTER DATABASE {{.DatabaseName}} CHARACTER SET '{{.DefaultCharacterSet}}' COLLATE '{{.DefaultCollation}}';"
2 changes: 1 addition & 1 deletion templates/delete_database.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/bash

mysql -h {{.DatabaseHostname}} -u {{.DatabaseAdminUsername}} -P 3306 -e "DROP DATABASE IF EXISTS {{.DatabaseName}}; DROP USER IF EXISTS '{{.DatabaseName}}'@'localhost'; DROP USER IF EXISTS '{{.DatabaseName}}'@'%';"
mysql -h {{.DatabaseHostname}} -u {{.DatabaseAdminUsername}} -P 3306 -e "DROP DATABASE IF EXISTS {{.DatabaseName}};"
1 change: 0 additions & 1 deletion tests/kuttl/tests/account_create/02-create-database.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@ metadata:
labels:
dbName: openstack
spec:
secret: osp-secret
name: kuttldb_accounttest
17 changes: 0 additions & 17 deletions tests/kuttl/tests/database_create/02-assert.yaml
Original file line number Diff line number Diff line change
@@ -1,26 +1,10 @@
---
apiVersion: batch/v1
kind: Job
metadata:
name: kuttldb-utf8-db-create
status:
succeeded: 1
---
apiVersion: batch/v1
kind: Job
metadata:
name: kuttldb-latin1-db-create
status:
succeeded: 1
---
apiVersion: mariadb.openstack.org/v1beta1
kind: MariaDBDatabase
metadata:
name: kuttldb-utf8
labels:
dbName: openstack
spec:
secret: osp-secret
name: kuttldb_utf8
status:
conditions:
Expand All @@ -45,7 +29,6 @@ metadata:
labels:
dbName: openstack
spec:
secret: osp-secret
name: kuttldb_latin1
status:
conditions:
Expand Down
2 changes: 0 additions & 2 deletions tests/kuttl/tests/database_create/02-create-database.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ metadata:
labels:
dbName: openstack
spec:
secret: osp-secret
name: kuttldb_utf8
---
apiVersion: mariadb.openstack.org/v1beta1
Expand All @@ -15,7 +14,6 @@ metadata:
labels:
dbName: openstack
spec:
secret: osp-secret
name: kuttldb_latin1
defaultCharacterSet: latin1
defaultCollation: latin1_general_ci

0 comments on commit d5c1598

Please sign in to comment.