Skip to content

Commit 9e8c408

Browse files
Merge pull request #345 from zzzeek/OSPRH-14916-pr4
mariadbaccount system accounts (PR 4 of 6)
2 parents 231c653 + e72f0dc commit 9e8c408

13 files changed

Lines changed: 385 additions & 52 deletions

api/bases/mariadb.openstack.org_mariadbaccounts.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ spec:
4848
spec:
4949
description: MariaDBAccountSpec defines the desired state of MariaDBAccount
5050
properties:
51+
accountType:
52+
default: User
53+
enum:
54+
- User
55+
- System
56+
type: string
5157
requireTLS:
5258
default: false
5359
description: Account must use TLS to connect to the database

api/v1beta1/mariadbaccount_types.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,19 @@ type MariaDBAccountSpec struct {
4848
// Account must use TLS to connect to the database
4949
// +kubebuilder:default=false
5050
RequireTLS bool `json:"requireTLS"`
51+
52+
// +kubebuilder:validation:Enum=User;System
53+
// +kubebuilder:default=User
54+
AccountType AccountType `json:"accountType,omitempty"`
5155
}
5256

57+
type AccountType string
58+
59+
const (
60+
User AccountType = "User"
61+
System AccountType = "System"
62+
)
63+
5364
// MariaDBAccountStatus defines the observed state of MariaDBAccount
5465
type MariaDBAccountStatus struct {
5566
// Deployment Conditions
@@ -85,3 +96,11 @@ type MariaDBAccountList struct {
8596
func init() {
8697
SchemeBuilder.Register(&MariaDBAccount{}, &MariaDBAccountList{})
8798
}
99+
100+
func (mariadbAccount MariaDBAccount) IsSystemAccount() bool {
101+
return mariadbAccount.Spec.AccountType == System
102+
}
103+
104+
func (mariadbAccount MariaDBAccount) IsUserAccount() bool {
105+
return mariadbAccount.Spec.AccountType == "" || mariadbAccount.Spec.AccountType == User
106+
}

config/crd/bases/mariadb.openstack.org_mariadbaccounts.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ spec:
4848
spec:
4949
description: MariaDBAccountSpec defines the desired state of MariaDBAccount
5050
properties:
51+
accountType:
52+
default: User
53+
enum:
54+
- User
55+
- System
56+
type: string
5157
requireTLS:
5258
default: false
5359
description: Account must use TLS to connect to the database

controllers/galera_controller.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,9 +1058,8 @@ func (r *GaleraReconciler) SetupWithManager(mgr ctrl.Manager) error {
10581058
Complete(r)
10591059
}
10601060

1061-
// GetDatabaseObject - returns either a Galera or MariaDB object (and an associated client.Object interface).
1061+
// GetDatabaseObject - returns a Galera object.
10621062
// used by both MariaDBDatabaseReconciler and MariaDBAccountReconciler
1063-
// this will later return only Galera objects, so as a lookup it's part of the galera controller
10641063
func GetDatabaseObject(ctx context.Context, clientObj client.Client, name string, namespace string) (*mariadbv1.Galera, error) {
10651064
dbGalera := &mariadbv1.Galera{
10661065
ObjectMeta: metav1.ObjectMeta{

controllers/mariadbaccount_controller.go

Lines changed: 102 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
util "github.com/openstack-k8s-operators/lib-common/modules/common/util"
3131
databasev1beta1 "github.com/openstack-k8s-operators/mariadb-operator/api/v1beta1"
3232
mariadb "github.com/openstack-k8s-operators/mariadb-operator/pkg/mariadb"
33+
batchv1 "k8s.io/api/batch/v1"
3334
k8s_errors "k8s.io/apimachinery/pkg/api/errors"
3435
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3536
"k8s.io/apimachinery/pkg/runtime"
@@ -113,12 +114,18 @@ func (r *MariaDBAccountReconciler) Reconcile(ctx context.Context, req ctrl.Reque
113114
}()
114115

115116
// initialize conditions used later as Status=Unknown
116-
cl := condition.CreateList(
117-
condition.UnknownCondition(condition.ReadyCondition, condition.InitReason, condition.ReadyInitMessage),
118-
condition.UnknownCondition(databasev1beta1.MariaDBServerReadyCondition, condition.InitReason, databasev1beta1.MariaDBServerReadyInitMessage),
119-
condition.UnknownCondition(databasev1beta1.MariaDBDatabaseReadyCondition, condition.InitReason, databasev1beta1.MariaDBDatabaseReadyInitMessage),
120-
condition.UnknownCondition(databasev1beta1.MariaDBAccountReadyCondition, condition.InitReason, databasev1beta1.MariaDBAccountReadyInitMessage),
121-
)
117+
cl := condition.Conditions{
118+
*condition.UnknownCondition(condition.ReadyCondition, condition.InitReason, condition.ReadyInitMessage),
119+
*condition.UnknownCondition(databasev1beta1.MariaDBServerReadyCondition, condition.InitReason, databasev1beta1.MariaDBServerReadyInitMessage),
120+
}
121+
if instance.IsUserAccount() {
122+
// user accounts also need the database ready condition
123+
// the element is being inserted into the list in a specific location
124+
// to preseve expectations of tests suites that are hardcoded to
125+
// expect a specific ordering of Conditions in YAML displays
126+
cl = append(cl, *condition.UnknownCondition(databasev1beta1.MariaDBDatabaseReadyCondition, condition.InitReason, databasev1beta1.MariaDBDatabaseReadyInitMessage))
127+
}
128+
cl = append(cl, *condition.UnknownCondition(databasev1beta1.MariaDBAccountReadyCondition, condition.InitReason, databasev1beta1.MariaDBAccountReadyInitMessage))
122129
instance.Status.Conditions.Init(&cl)
123130

124131
if instance.DeletionTimestamp.IsZero() || isNewInstance { //revive:disable:indent-error-flow
@@ -134,23 +141,30 @@ func (r *MariaDBAccountReconciler) reconcileCreate(
134141
ctx context.Context, log logr.Logger,
135142
helper *helper.Helper, instance *databasev1beta1.MariaDBAccount) (result ctrl.Result, _err error) {
136143

137-
// get a handle to the current, active MariaDBDatabase.
138-
// if not ready yet, requeue.
139-
mariadbDatabase, result, err := r.getMariaDBDatabaseForCreate(ctx, log, instance)
140-
if mariadbDatabase == nil {
141-
return result, err
144+
var mariadbDatabase *databasev1beta1.MariaDBDatabase
145+
var err error
146+
147+
if instance.IsUserAccount() {
148+
// for User account, get a handle to the current, active MariaDBDatabase.
149+
// if not ready yet, requeue.
150+
mariadbDatabase, result, err = r.getMariaDBDatabaseForCreate(ctx, log, instance)
151+
if mariadbDatabase == nil {
152+
return result, err
153+
}
142154
}
143155

144156
if controllerutil.AddFinalizer(instance, helper.GetFinalizer()) {
145157
// we need to persist this right away
146158
return ctrl.Result{}, nil
147159
}
148160

149-
// MariaDBdatabase exists and we are a create case. ensure finalizers set up
150-
if controllerutil.AddFinalizer(mariadbDatabase, fmt.Sprintf("%s-%s", helper.GetFinalizer(), instance.Name)) {
151-
err = r.Update(ctx, mariadbDatabase)
152-
if err != nil {
153-
return ctrl.Result{}, err
161+
if instance.IsUserAccount() {
162+
// MariaDBdatabase exists and we are a create case. ensure finalizers set up
163+
if controllerutil.AddFinalizer(mariadbDatabase, fmt.Sprintf("%s-%s", helper.GetFinalizer(), instance.Name)) {
164+
err = r.Update(ctx, mariadbDatabase)
165+
if err != nil {
166+
return ctrl.Result{}, err
167+
}
154168
}
155169
}
156170

@@ -174,13 +188,25 @@ func (r *MariaDBAccountReconciler) reconcileCreate(
174188
return result, err
175189
}
176190

177-
log.Info(fmt.Sprintf("Running account create '%s' MariaDBDatabase '%s'",
178-
instance.Name, mariadbDatabase.Spec.Name))
179-
jobDef, err := mariadb.CreateDbAccountJob(
180-
dbGalera, instance, mariadbDatabase.Spec.Name, dbHostname,
181-
dbContainerImage, serviceAccountName, dbGalera.Spec.NodeSelector)
182-
if err != nil {
183-
return ctrl.Result{}, err
191+
var jobDef *batchv1.Job
192+
193+
if instance.IsUserAccount() {
194+
log.Info(fmt.Sprintf("Running account create '%s' MariaDBDatabase '%s'",
195+
instance.Name, mariadbDatabase.Spec.Name))
196+
jobDef, err = mariadb.CreateDbAccountJob(
197+
dbGalera, instance, mariadbDatabase.Spec.Name, dbHostname,
198+
dbContainerImage, serviceAccountName, dbGalera.Spec.NodeSelector)
199+
if err != nil {
200+
return ctrl.Result{}, err
201+
}
202+
} else {
203+
log.Info(fmt.Sprintf("Running system account create '%s'", instance.Name))
204+
jobDef, err = mariadb.CreateDbAccountJob(
205+
dbGalera, instance, "", dbHostname,
206+
dbContainerImage, serviceAccountName, dbGalera.Spec.NodeSelector)
207+
if err != nil {
208+
return ctrl.Result{}, err
209+
}
184210
}
185211

186212
accountCreateHash := instance.Status.Hash[databasev1beta1.AccountCreateHash]
@@ -228,9 +254,14 @@ func (r *MariaDBAccountReconciler) reconcileDelete(
228254
ctx context.Context, log logr.Logger,
229255
helper *helper.Helper, instance *databasev1beta1.MariaDBAccount) (result ctrl.Result, _err error) {
230256

231-
mariadbDatabase, result, err := r.getMariaDBDatabaseForDelete(ctx, log, helper, instance)
232-
if mariadbDatabase == nil {
233-
return result, err
257+
var mariadbDatabase *databasev1beta1.MariaDBDatabase
258+
var err error
259+
260+
if instance.IsUserAccount() {
261+
mariadbDatabase, result, err = r.getMariaDBDatabaseForDelete(ctx, log, helper, instance)
262+
if mariadbDatabase == nil {
263+
return result, err
264+
}
234265
}
235266

236267
// dont do actual DROP USER until finalizers from downstream controllers
@@ -259,10 +290,12 @@ func (r *MariaDBAccountReconciler) reconcileDelete(
259290
databasev1beta1.MariaDBAccountReadyForDeleteMessage,
260291
)
261292

262-
instance.Status.Conditions.MarkTrue(
263-
databasev1beta1.MariaDBDatabaseReadyCondition,
264-
databasev1beta1.MariaDBDatabaseReadyMessage,
265-
)
293+
if instance.IsUserAccount() {
294+
instance.Status.Conditions.MarkTrue(
295+
databasev1beta1.MariaDBDatabaseReadyCondition,
296+
databasev1beta1.MariaDBDatabaseReadyMessage,
297+
)
298+
}
266299

267300
// now proceed to do actual work. acquire the Galera instance
268301
// which will lead us to the hostname and container image to target
@@ -278,20 +311,21 @@ func (r *MariaDBAccountReconciler) reconcileDelete(
278311
// scheme allows multiple MariaDBAccounts to claim the same MariaDBDatabase
279312
// as a dependency) and allows a delete of the MariaDBDatabase to proceed
280313
// assuming no other finalizers
281-
if controllerutil.RemoveFinalizer(mariadbDatabase, fmt.Sprintf("%s-%s", helper.GetFinalizer(), instance.Name)) {
282-
err = r.Update(ctx, mariadbDatabase)
314+
if instance.IsUserAccount() {
315+
if controllerutil.RemoveFinalizer(mariadbDatabase, fmt.Sprintf("%s-%s", helper.GetFinalizer(), instance.Name)) {
316+
err = r.Update(ctx, mariadbDatabase)
283317

284-
if err != nil && !k8s_errors.IsNotFound(err) {
285-
return ctrl.Result{}, err
318+
if err != nil && !k8s_errors.IsNotFound(err) {
319+
return ctrl.Result{}, err
320+
}
286321
}
287-
288322
}
289323

290324
// remove finalizer "openstack.org/mariadbaccount" from both the
291325
// MariaDBAccount as well as the Secret which is referenced from the
292326
// MariaDBAccount, allowing both to be deleted assuming no other
293327
// finalizers
294-
err = r.removeAccountAndSecretFinalizer(ctx, helper, instance)
328+
err := r.removeAccountAndSecretFinalizer(ctx, helper, instance)
295329
return ctrl.Result{}, err
296330
} else if dbGalera == nil {
297331
return result, err
@@ -300,13 +334,24 @@ func (r *MariaDBAccountReconciler) reconcileDelete(
300334
dbContainerImage := dbGalera.Spec.ContainerImage
301335
serviceAccountName := dbGalera.RbacResourceName()
302336

303-
log.Info(fmt.Sprintf("Running account delete '%s' MariaDBDatabase '%s'", instance.Name, mariadbDatabase.Spec.Name))
337+
var jobDef *batchv1.Job
304338

305-
jobDef, err := mariadb.DeleteDbAccountJob(dbGalera, instance, mariadbDatabase.Spec.Name, dbHostname, dbContainerImage, serviceAccountName, dbGalera.Spec.NodeSelector)
306-
if err != nil {
307-
return ctrl.Result{}, err
308-
}
339+
if instance.IsUserAccount() {
340+
341+
log.Info(fmt.Sprintf("Running account delete '%s' MariaDBDatabase '%s'", instance.Name, mariadbDatabase.Spec.Name))
342+
343+
jobDef, err = mariadb.DeleteDbAccountJob(dbGalera, instance, mariadbDatabase.Spec.Name, dbHostname, dbContainerImage, serviceAccountName, dbGalera.Spec.NodeSelector)
344+
if err != nil {
345+
return ctrl.Result{}, err
346+
}
347+
} else {
348+
log.Info(fmt.Sprintf("Running system account delete '%s'", instance.Name))
309349

350+
jobDef, err = mariadb.DeleteDbAccountJob(dbGalera, instance, "", dbHostname, dbContainerImage, serviceAccountName, dbGalera.Spec.NodeSelector)
351+
if err != nil {
352+
return ctrl.Result{}, err
353+
}
354+
}
310355
accountDeleteHash := instance.Status.Hash[databasev1beta1.AccountDeleteHash]
311356
accountDeleteJob := job.NewJob(
312357
jobDef,
@@ -335,18 +380,19 @@ func (r *MariaDBAccountReconciler) reconcileDelete(
335380
// scheme allows multiple MariaDBAccounts to claim the same MariaDBDatabase
336381
// as a dependency) and allows a delete of the MariaDBDatabase to proceed
337382
// assuming no other finalizers
338-
if controllerutil.RemoveFinalizer(mariadbDatabase, fmt.Sprintf("%s-%s", helper.GetFinalizer(), instance.Name)) {
339-
err = r.Update(ctx, mariadbDatabase)
340-
if err != nil {
341-
return ctrl.Result{}, err
383+
if instance.IsUserAccount() {
384+
if controllerutil.RemoveFinalizer(mariadbDatabase, fmt.Sprintf("%s-%s", helper.GetFinalizer(), instance.Name)) {
385+
err = r.Update(ctx, mariadbDatabase)
386+
if err != nil {
387+
return ctrl.Result{}, err
388+
}
342389
}
343390
}
344391

345392
// remove finalizer "openstack.org/mariadbaccount" from
346393
// both the MariaDBAccount as well as the Secret which is referenced
347394
// from the MariaDBAccount, allowing both to be deleted
348395
err = r.removeAccountAndSecretFinalizer(ctx, helper, instance)
349-
350396
return ctrl.Result{}, err
351397
}
352398

@@ -526,9 +572,17 @@ func (r *MariaDBAccountReconciler) getGaleraForCreateOrDelete(
526572
helper *helper.Helper, instance *databasev1beta1.MariaDBAccount,
527573
mariadbDatabase *databasev1beta1.MariaDBDatabase) (*databasev1beta1.Galera, string, ctrl.Result, error) {
528574

529-
dbName := mariadbDatabase.Labels["dbName"]
575+
var dbGalera *databasev1beta1.Galera
576+
var err error
577+
var dbName string
530578

531-
dbGalera, err := GetDatabaseObject(ctx, r.Client, dbName, instance.Namespace)
579+
if instance.IsUserAccount() {
580+
dbName = mariadbDatabase.Labels["dbName"]
581+
} else {
582+
// note mariadbDatabase is passed as nil in this case
583+
dbName = instance.Labels["dbName"]
584+
}
585+
dbGalera, err = GetDatabaseObject(ctx, r.Client, dbName, instance.Namespace)
532586

533587
if err != nil {
534588
log.Error(err, "Error retrieving Galera instance")

templates/account.sh

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ MYSQL_REMOTE_HOST={{.DatabaseHostname}} source /var/lib/operator-scripts/mysql_r
44

55
export DatabasePassword=${DatabasePassword:?"Please specify a DatabasePassword variable."}
66

7-
mysql -h {{.DatabaseHostname}} -u {{.DatabaseAdminUsername}} -P 3306 -e "GRANT ALL PRIVILEGES ON {{.DatabaseName}}.* TO '{{.UserName}}'@'localhost' IDENTIFIED BY '$DatabasePassword'{{.RequireTLS}};GRANT ALL PRIVILEGES ON {{.DatabaseName}}.* TO '{{.UserName}}'@'%' IDENTIFIED BY '$DatabasePassword'{{.RequireTLS}};"
8-
7+
if [ -n "{{.DatabaseName}}" ]; then
8+
mysql -h {{.DatabaseHostname}} -u {{.DatabaseAdminUsername}} -P 3306 -e "GRANT ALL PRIVILEGES ON {{.DatabaseName}}.* TO '{{.UserName}}'@'localhost' IDENTIFIED BY '$DatabasePassword'{{.RequireTLS}};GRANT ALL PRIVILEGES ON {{.DatabaseName}}.* TO '{{.UserName}}'@'%' IDENTIFIED BY '$DatabasePassword'{{.RequireTLS}};"
9+
else
10+
mysql -h {{.DatabaseHostname}} -u {{.DatabaseAdminUsername}} -P 3306 -e "GRANT ALL PRIVILEGES ON *.* TO '{{.UserName}}'@'localhost' IDENTIFIED BY '$DatabasePassword'{{.RequireTLS}};GRANT ALL PRIVILEGES ON *.* TO '{{.UserName}}'@'%' IDENTIFIED BY '$DatabasePassword'{{.RequireTLS}};"
11+
fi
912

1013
# search for the account. not using SHOW CREATE USER to avoid displaying
1114
# password hash
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
apiVersion: mariadb.openstack.org/v1beta1
3+
kind: MariaDBAccount
4+
metadata:
5+
labels:
6+
dbName: openstack
7+
name: chainsawdb-some-system-db-account
8+
status:
9+
conditions:
10+
- message: Setup complete
11+
reason: Ready
12+
status: "True"
13+
type: Ready
14+
- message: MariaDBAccount creation complete
15+
reason: Ready
16+
status: "True"
17+
type: MariaDBAccountReady
18+
- message: MariaDB / Galera server ready
19+
reason: Ready
20+
status: "True"
21+
type: MariaDBServerReady
22+
---
23+
apiVersion: v1
24+
data:
25+
DatabasePassword: ZGJzZWNyZXQx
26+
kind: Secret
27+
metadata:
28+
name: some-system-db-secret
29+
# ensure finalizer was added
30+
finalizers:
31+
- openstack.org/mariadbaccount
32+
type: Opaque
33+
---
34+
apiVersion: batch/v1
35+
kind: Job
36+
metadata:
37+
name: systemuser-account-create
38+
spec:
39+
template:
40+
spec: {}
41+
status:
42+
succeeded: 1
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
apiVersion: v1
2+
data:
3+
DatabasePassword: ZGJzZWNyZXQx
4+
kind: Secret
5+
metadata:
6+
name: some-system-db-secret
7+
type: Opaque
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
apiVersion: mariadb.openstack.org/v1beta1
2+
kind: MariaDBAccount
3+
metadata:
4+
labels:
5+
dbName: openstack
6+
name: chainsawdb-some-system-db-account
7+
spec:
8+
userName: systemuser
9+
secret: some-system-db-secret
10+
accountType: System

0 commit comments

Comments
 (0)