From 2798ed1135df4ee9d48e91bf173990ccef430df8 Mon Sep 17 00:00:00 2001 From: Damien Ciabrini Date: Thu, 23 Nov 2023 12:40:07 +0100 Subject: [PATCH] Make database character encoding configurable When a MariaDBDatabase CR is reconciled, a database is created with a default character encoding and collation of latin1. Instead of falling back to the server's default encoding for database creation, expose the encoding in the MariaDBDatabase CRD and default to utf8, as it expected by various Openstack projects. --- ...ariadb.openstack.org_mariadbdatabases.yaml | 14 ++- api/v1beta1/mariadbdatabase_types.go | 11 +- ...ariadb.openstack.org_mariadbdatabases.yaml | 14 ++- kuttl-test.yaml | 2 +- pkg/mariadb/database.go | 18 ++- templates/database.sh | 2 +- .../tests/database_create/01-assert.yaml | 114 ++++++++++++++++++ .../database_create/01-deploy_galera.yaml | 9 ++ .../tests/database_create/02-assert.yaml | 14 +++ .../database_create/02-create-database.yaml | 21 ++++ .../tests/database_create/03-assert.yaml | 15 +++ .../tests/database_create/04-teardown.yaml | 12 ++ 12 files changed, 238 insertions(+), 8 deletions(-) create mode 100644 tests/kuttl/tests/database_create/01-assert.yaml create mode 100644 tests/kuttl/tests/database_create/01-deploy_galera.yaml create mode 100644 tests/kuttl/tests/database_create/02-assert.yaml create mode 100644 tests/kuttl/tests/database_create/02-create-database.yaml create mode 100644 tests/kuttl/tests/database_create/03-assert.yaml create mode 100644 tests/kuttl/tests/database_create/04-teardown.yaml diff --git a/api/bases/mariadb.openstack.org_mariadbdatabases.yaml b/api/bases/mariadb.openstack.org_mariadbdatabases.yaml index 0cbb6c86..b8d76956 100644 --- a/api/bases/mariadb.openstack.org_mariadbdatabases.yaml +++ b/api/bases/mariadb.openstack.org_mariadbdatabases.yaml @@ -35,11 +35,23 @@ spec: spec: description: MariaDBDatabaseSpec defines the desired state of MariaDBDatabase properties: + defaultCharacterSet: + default: utf8 + description: Default character set for this database + type: string + defaultCollation: + default: utf8_general_ci + description: Default collation for this database + type: string name: + description: Name of the database in MariaDB type: string secret: - description: Secret Name of secret which contains DatabasePassword + description: Name of secret which contains DatabasePassword type: string + required: + - defaultCharacterSet + - defaultCollation type: object status: description: MariaDBDatabaseStatus defines the observed state of MariaDBDatabase diff --git a/api/v1beta1/mariadbdatabase_types.go b/api/v1beta1/mariadbdatabase_types.go index 801d5022..700547c4 100644 --- a/api/v1beta1/mariadbdatabase_types.go +++ b/api/v1beta1/mariadbdatabase_types.go @@ -30,9 +30,16 @@ const ( // MariaDBDatabaseSpec defines the desired state of MariaDBDatabase type MariaDBDatabaseSpec struct { - // Secret Name of secret which contains DatabasePassword + // Name of secret which contains DatabasePassword Secret string `json:"secret,omitempty"` - Name string `json:"name,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"` + // +kubebuilder:default=utf8_general_ci + // Default collation for this database + DefaultCollation string `json:"defaultCollation"` } // MariaDBDatabaseStatus defines the observed state of MariaDBDatabase diff --git a/config/crd/bases/mariadb.openstack.org_mariadbdatabases.yaml b/config/crd/bases/mariadb.openstack.org_mariadbdatabases.yaml index 0cbb6c86..b8d76956 100644 --- a/config/crd/bases/mariadb.openstack.org_mariadbdatabases.yaml +++ b/config/crd/bases/mariadb.openstack.org_mariadbdatabases.yaml @@ -35,11 +35,23 @@ spec: spec: description: MariaDBDatabaseSpec defines the desired state of MariaDBDatabase properties: + defaultCharacterSet: + default: utf8 + description: Default character set for this database + type: string + defaultCollation: + default: utf8_general_ci + description: Default collation for this database + type: string name: + description: Name of the database in MariaDB type: string secret: - description: Secret Name of secret which contains DatabasePassword + description: Name of secret which contains DatabasePassword type: string + required: + - defaultCharacterSet + - defaultCollation type: object status: description: MariaDBDatabaseStatus defines the observed state of MariaDBDatabase diff --git a/kuttl-test.yaml b/kuttl-test.yaml index a20ba589..777c26f7 100644 --- a/kuttl-test.yaml +++ b/kuttl-test.yaml @@ -20,6 +20,6 @@ reportFormat: JSON reportName: kuttl-test-mariadb namespace: mariadb-kuttl-tests timeout: 180 -parallel: 2 +parallel: 1 suppress: - events # Remove spammy event logs diff --git a/pkg/mariadb/database.go b/pkg/mariadb/database.go index 44a37f12..59b45719 100644 --- a/pkg/mariadb/database.go +++ b/pkg/mariadb/database.go @@ -14,12 +14,20 @@ type dbCreateOptions struct { DatabaseName string DatabaseHostname string DatabaseAdminUsername string + DefaultCharacterSet string + DefaultCollation string } // DbDatabaseJob - func DbDatabaseJob(database *databasev1beta1.MariaDBDatabase, databaseHostName string, databaseSecret string, containerImage string, serviceAccountName string) (*batchv1.Job, error) { - opts := dbCreateOptions{database.Spec.Name, databaseHostName, "root"} + opts := dbCreateOptions{ + database.Spec.Name, + databaseHostName, + "root", + database.Spec.DefaultCharacterSet, + database.Spec.DefaultCollation, + } dbCmd, err := util.ExecuteTemplateFile("database.sh", &opts) if err != nil { return nil, err @@ -83,7 +91,13 @@ func DbDatabaseJob(database *databasev1beta1.MariaDBDatabase, databaseHostName s // DeleteDbDatabaseJob - func DeleteDbDatabaseJob(database *databasev1beta1.MariaDBDatabase, databaseHostName string, databaseSecret string, containerImage string, serviceAccountName string) (*batchv1.Job, error) { - opts := dbCreateOptions{database.Spec.Name, databaseHostName, "root"} + opts := dbCreateOptions{ + database.Spec.Name, + databaseHostName, + "root", + database.Spec.DefaultCharacterSet, + database.Spec.DefaultCollation, + } delCmd, err := util.ExecuteTemplateFile("delete_database.sh", &opts) if err != nil { return nil, err diff --git a/templates/database.sh b/templates/database.sh index 13782839..96484af9 100755 --- a/templates/database.sh +++ b/templates/database.sh @@ -1,4 +1,4 @@ #!/bin/bash export DatabasePassword=${DatabasePassword:?"Please specify a DatabasePassword variable."} -mysql -h {{.DatabaseHostname}} -u {{.DatabaseAdminUsername}} -P 3306 -e "CREATE DATABASE IF NOT EXISTS {{.DatabaseName}}; 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}}'; GRANT ALL PRIVILEGES ON {{.DatabaseName}}.* TO '{{.DatabaseName}}'@'localhost' IDENTIFIED BY '$DatabasePassword';GRANT ALL PRIVILEGES ON {{.DatabaseName}}.* TO '{{.DatabaseName}}'@'%' IDENTIFIED BY '$DatabasePassword';" diff --git a/tests/kuttl/tests/database_create/01-assert.yaml b/tests/kuttl/tests/database_create/01-assert.yaml new file mode 100644 index 00000000..3b721bbd --- /dev/null +++ b/tests/kuttl/tests/database_create/01-assert.yaml @@ -0,0 +1,114 @@ +# +# Check for: +# +# - 1 MariaDB CR +# - 1 Pod for MariaDB CR +# + +apiVersion: mariadb.openstack.org/v1beta1 +kind: Galera +metadata: + name: openstack +spec: + replicas: 1 + secret: osp-secret + storageRequest: 500M +status: + bootstrapped: true + conditions: + - message: Setup complete + reason: Ready + status: "True" + type: Ready + - message: Deployment completed + reason: Ready + status: "True" + type: DeploymentReady + - message: Exposing service completed + reason: Ready + status: "True" + type: ExposeServiceReady + - message: RoleBinding created + reason: Ready + status: "True" + type: RoleBindingReady + - message: Role created + reason: Ready + status: "True" + type: RoleReady + - message: ServiceAccount created + reason: Ready + status: "True" + type: ServiceAccountReady + - message: Service config create completed + reason: Ready + status: "True" + type: ServiceConfigReady +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: openstack-galera +spec: + replicas: 1 + selector: + matchLabels: + app: galera + cr: galera-openstack + galera/name: openstack + serviceName: openstack-galera + template: + metadata: + labels: + app: galera + cr: galera-openstack + galera/name: openstack + spec: + containers: + - command: + - /usr/bin/dumb-init + - -- + - /usr/local/bin/kolla_start + name: galera + ports: + - containerPort: 3306 + name: mysql + protocol: TCP + - containerPort: 4567 + name: galera + protocol: TCP + serviceAccount: galera-openstack + serviceAccountName: galera-openstack +status: + availableReplicas: 1 + readyReplicas: 1 + replicas: 1 +--- +apiVersion: v1 +kind: Pod +metadata: + name: openstack-galera-0 +--- +apiVersion: v1 +kind: Service +metadata: + name: openstack-galera +spec: + ports: + - name: mysql + port: 3306 + protocol: TCP + targetPort: 3306 + selector: + app: galera + cr: galera-openstack +--- +apiVersion: v1 +kind: Endpoints +metadata: + name: openstack-galera +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: openstack-config-data diff --git a/tests/kuttl/tests/database_create/01-deploy_galera.yaml b/tests/kuttl/tests/database_create/01-deploy_galera.yaml new file mode 100644 index 00000000..c025eca7 --- /dev/null +++ b/tests/kuttl/tests/database_create/01-deploy_galera.yaml @@ -0,0 +1,9 @@ +apiVersion: mariadb.openstack.org/v1beta1 +kind: Galera +metadata: + name: openstack +spec: + secret: osp-secret + storageClass: local-storage + storageRequest: 500M + replicas: 1 diff --git a/tests/kuttl/tests/database_create/02-assert.yaml b/tests/kuttl/tests/database_create/02-assert.yaml new file mode 100644 index 00000000..ed1dbe73 --- /dev/null +++ b/tests/kuttl/tests/database_create/02-assert.yaml @@ -0,0 +1,14 @@ +--- +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 diff --git a/tests/kuttl/tests/database_create/02-create-database.yaml b/tests/kuttl/tests/database_create/02-create-database.yaml new file mode 100644 index 00000000..adaf5cec --- /dev/null +++ b/tests/kuttl/tests/database_create/02-create-database.yaml @@ -0,0 +1,21 @@ +apiVersion: mariadb.openstack.org/v1beta1 +kind: MariaDBDatabase +metadata: + name: kuttldb-utf8 + labels: + dbName: openstack +spec: + secret: osp-secret + name: kuttldb_utf8 +--- +apiVersion: mariadb.openstack.org/v1beta1 +kind: MariaDBDatabase +metadata: + name: kuttldb-latin1 + labels: + dbName: openstack +spec: + secret: osp-secret + name: kuttldb_latin1 + defaultCharacterSet: latin1 + defaultCollation: latin1_general_ci diff --git a/tests/kuttl/tests/database_create/03-assert.yaml b/tests/kuttl/tests/database_create/03-assert.yaml new file mode 100644 index 00000000..8be4ac8d --- /dev/null +++ b/tests/kuttl/tests/database_create/03-assert.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +commands: + - script: | + oc rsh -n ${NAMESPACE} -c galera openstack-galera-0 /bin/sh -c 'mysql -uroot -p${DB_ROOT_PASSWORD} -Nse "select @@character_set_database;" kuttldb_latin1' | grep -o -w latin1 + oc rsh -n ${NAMESPACE} -c galera openstack-galera-0 /bin/sh -c 'mysql -uroot -p${DB_ROOT_PASSWORD} -Nse "select @@collation_database;" kuttldb_latin1' | grep -o -w latin1_general_ci + +--- +apiVersion: kuttl.dev/v1beta1 +kind: TestAssert +commands: + - script: | + oc rsh -n ${NAMESPACE} -c galera openstack-galera-0 /bin/sh -c 'mysql -uroot -p${DB_ROOT_PASSWORD} -Nse "select @@character_set_database;" kuttldb_utf8' | grep -o -w utf8 + oc rsh -n ${NAMESPACE} -c galera openstack-galera-0 /bin/sh -c 'mysql -uroot -p${DB_ROOT_PASSWORD} -Nse "select @@collation_database;" kuttldb_utf8' | grep -o -w utf8_general_ci diff --git a/tests/kuttl/tests/database_create/04-teardown.yaml b/tests/kuttl/tests/database_create/04-teardown.yaml new file mode 100644 index 00000000..5184bca7 --- /dev/null +++ b/tests/kuttl/tests/database_create/04-teardown.yaml @@ -0,0 +1,12 @@ +apiVersion: kuttl.dev/v1beta +kind: TestStep +delete: +- apiVersion: mariadb.openstack.org/v1beta1 + kind: Galera + name: openstack +- apiVersion: mariadb.openstack.org/v1beta1 + kind: MariaDBDatabase +commands: + - script: | + oc delete -n $NAMESPACE pvc mysql-db-openstack-galera-0 + for i in `oc get pv | awk '/'$NAMESPACE'\/mysql-db-openstack-galera/ {print $1}'`; do oc patch pv $i -p '{"spec":{"claimRef": null}}'; done