Skip to content

Commit 7fcb95e

Browse files
committed
use system MariaDBAccount for the galera server's root pw
This commit ties together the previous ones to create a new MariaDBAccount when a Galera instance is created, and then to use the password from that account/secret in the mariadb bootstrap/maintenance scripts. Galera gets bootstrapped with this secret, then the mariadbaccount controller, who is waiting for galera to be available to set up this new "root" account, wakes up when galera is running, and changes the root password to itself, establishing the initial job hash for the mariadbaccount.
1 parent a3a32f3 commit 7fcb95e

File tree

16 files changed

+328
-80
lines changed

16 files changed

+328
-80
lines changed

api/bases/mariadb.openstack.org_galeras.yaml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,18 @@ spec:
7878
maximum: 3
7979
minimum: 0
8080
type: integer
81+
rootDatabaseAccount:
82+
description: |-
83+
RootDatabaseAccount - name of MariaDBAccount which will be used to
84+
generate root account / password.
85+
this account is generated if not exists, and a name is chosen based
86+
on a naming convention if not present
87+
type: string
8188
secret:
82-
description: Name of the secret to look for password keys
89+
description: |-
90+
Name of the legacy secret to locate the initial galera root
91+
password
92+
this field will be removed once scripts can adjust to using root_auth.sh
8393
type: string
8494
storageClass:
8595
description: Storage class to host the mariadb databases
@@ -118,7 +128,6 @@ spec:
118128
required:
119129
- containerImage
120130
- replicas
121-
- secret
122131
- storageClass
123132
- storageRequest
124133
type: object
@@ -237,6 +246,9 @@ spec:
237246
the opentack-operator in the top-level CR (e.g. the ContainerImage)
238247
format: int64
239248
type: integer
249+
rootDatabaseSecret:
250+
description: name of the Secret that is being used for the root password
251+
type: string
240252
safeToBootstrap:
241253
description: Name of the node that can safely bootstrap a cluster
242254
type: string

api/v1beta1/conditions.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ const (
8484

8585
MariaDBAccountReadyInitMessage = "MariaDBAccount create / drop not started"
8686

87+
MariaDBSystemAccountReadyMessage = "MariaDBAccount System account '%s' creation complete"
88+
8789
MariaDBAccountReadyMessage = "MariaDBAccount creation complete"
8890

8991
MariaDBAccountNotReadyMessage = "MariaDBAccount is not present: %s"

api/v1beta1/galera_types.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@ limitations under the License.
1717
package v1beta1
1818

1919
import (
20+
topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1"
2021
condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition"
2122
"github.com/openstack-k8s-operators/lib-common/modules/common/tls"
2223
"github.com/openstack-k8s-operators/lib-common/modules/common/util"
23-
topologyv1 "github.com/openstack-k8s-operators/infra-operator/apis/topology/v1beta1"
24-
"k8s.io/apimachinery/pkg/util/validation/field"
2524
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25+
"k8s.io/apimachinery/pkg/util/validation/field"
2626
)
2727

2828
const (
@@ -50,9 +50,19 @@ type GaleraSpec struct {
5050

5151
// GaleraSpec defines the desired state of Galera
5252
type GaleraSpecCore struct {
53-
// Name of the secret to look for password keys
54-
// +kubebuilder:validation:Required
53+
// Name of the legacy secret to locate the initial galera root
54+
// password
55+
// this field will be removed once scripts can adjust to using root_auth.sh
56+
// +kubebuilder:validation:Optional
5557
Secret string `json:"secret"`
58+
59+
// RootDatabaseAccount - name of MariaDBAccount which will be used to
60+
// generate root account / password.
61+
// this account is generated if not exists, and a name is chosen based
62+
// on a naming convention if not present
63+
// +kubebuilder:validation:Optional
64+
RootDatabaseAccount string `json:"rootDatabaseAccount"`
65+
5666
// Storage class to host the mariadb databases
5767
// +kubebuilder:validation:Required
5868
StorageClass string `json:"storageClass"`
@@ -109,6 +119,9 @@ type GaleraAttributes struct {
109119
type GaleraStatus struct {
110120
// A map of database node attributes for each pod
111121
Attributes map[string]GaleraAttributes `json:"attributes,omitempty"`
122+
// name of the Secret that is being used for the root password
123+
// +kubebuilder:validation:Optional
124+
RootDatabaseSecret string `json:"rootDatabaseSecret"`
112125
// Name of the node that can safely bootstrap a cluster
113126
SafeToBootstrap string `json:"safeToBootstrap,omitempty"`
114127
// Is the galera cluster currently running

api/v1beta1/mariadbaccount_types.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,6 @@ const (
2828
// AccountDeleteHash hash
2929
AccountDeleteHash = "accountdelete"
3030

31-
// DbRootPassword selector for galera root account
32-
DbRootPasswordSelector = "DbRootPassword"
33-
3431
// DatabasePassword selector for MariaDBAccount->Secret
3532
DatabasePasswordSelector = "DatabasePassword"
3633
)

api/v1beta1/mariadbdatabase_funcs.go

Lines changed: 99 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,50 @@ func DeleteDatabaseAndAccountFinalizers(
541541
namespace string,
542542
) error {
543543

544+
err := DeleteAccountFinalizers(
545+
ctx,
546+
h,
547+
accountName,
548+
namespace,
549+
)
550+
if err != nil {
551+
return err
552+
}
553+
554+
// also do a delete for "unused" MariaDBAccounts, associated with
555+
// this MariaDBDatabase.
556+
err = DeleteUnusedMariaDBAccountFinalizers(
557+
ctx, h, name, accountName, namespace,
558+
)
559+
if err != nil && !k8s_errors.IsNotFound(err) {
560+
return err
561+
}
562+
563+
mariaDBDatabase, err := GetDatabase(ctx, h, name, namespace)
564+
if err != nil && !k8s_errors.IsNotFound(err) {
565+
return err
566+
} else if err == nil && controllerutil.RemoveFinalizer(mariaDBDatabase, h.GetFinalizer()) {
567+
err := h.GetClient().Update(ctx, mariaDBDatabase)
568+
if err != nil && !k8s_errors.IsNotFound(err) {
569+
return err
570+
}
571+
util.LogForObject(h, fmt.Sprintf("Removed finalizer %s from MariaDBDatabase %s", h.GetFinalizer(), mariaDBDatabase.Spec.Name), mariaDBDatabase)
572+
}
573+
574+
return nil
575+
}
576+
577+
// DeleteAccountFinalizers performs just the primary account + secret finalizer
578+
// removal part of DeleteDatabaseAndAccountFinalizers
579+
func DeleteAccountFinalizers(
580+
ctx context.Context,
581+
h *helper.Helper,
582+
accountName string,
583+
namespace string,
584+
) error {
585+
if accountName == "" {
586+
return fmt.Errorf("Account name is blank")
587+
}
544588
databaseAccount, err := GetAccount(ctx, h, accountName, namespace)
545589
if err != nil && !k8s_errors.IsNotFound(err) {
546590
return err
@@ -572,26 +616,6 @@ func DeleteDatabaseAndAccountFinalizers(
572616
}
573617
}
574618

575-
// also do a delete for "unused" MariaDBAccounts, associated with
576-
// this MariaDBDatabase.
577-
err = DeleteUnusedMariaDBAccountFinalizers(
578-
ctx, h, name, accountName, namespace,
579-
)
580-
if err != nil && !k8s_errors.IsNotFound(err) {
581-
return err
582-
}
583-
584-
mariaDBDatabase, err := GetDatabase(ctx, h, name, namespace)
585-
if err != nil && !k8s_errors.IsNotFound(err) {
586-
return err
587-
} else if err == nil && controllerutil.RemoveFinalizer(mariaDBDatabase, h.GetFinalizer()) {
588-
err := h.GetClient().Update(ctx, mariaDBDatabase)
589-
if err != nil && !k8s_errors.IsNotFound(err) {
590-
return err
591-
}
592-
util.LogForObject(h, fmt.Sprintf("Removed finalizer %s from MariaDBDatabase %s", h.GetFinalizer(), mariaDBDatabase.Spec.Name), mariaDBDatabase)
593-
}
594-
595619
return nil
596620
}
597621

@@ -811,6 +835,32 @@ func EnsureMariaDBAccount(ctx context.Context,
811835
userNamePrefix string,
812836
) (*MariaDBAccount, *corev1.Secret, error) {
813837

838+
return ensureMariaDBAccount(
839+
ctx, helper, accountName, namespace, requireTLS,
840+
userNamePrefix, "", "", map[string]string{})
841+
842+
}
843+
844+
// EnsureMariaDBSystemAccount ensures a MariaDBAccount has been created for a given
845+
// operator calling the function, and returns the MariaDBAccount and its
846+
// Secret for use in consumption into a configuration.
847+
// Unlike EnsureMariaDBAccount, the function accepts an exact username that
848+
// expected to remain constant, supporting in-place password changes for the
849+
// account.
850+
func EnsureMariaDBSystemAccount(ctx context.Context,
851+
helper *helper.Helper,
852+
accountName string, galeraInstanceName string, namespace string, requireTLS bool,
853+
exactUserName string, exactPassword string) (*MariaDBAccount, *corev1.Secret, error) {
854+
return ensureMariaDBAccount(
855+
ctx, helper, accountName, namespace, requireTLS,
856+
"", exactUserName, exactPassword, map[string]string{"dbName": galeraInstanceName})
857+
}
858+
859+
func ensureMariaDBAccount(ctx context.Context,
860+
helper *helper.Helper,
861+
accountName string, namespace string, requireTLS bool,
862+
userNamePrefix string, exactUserName string, exactPassword string, labels map[string]string,
863+
) (*MariaDBAccount, *corev1.Secret, error) {
814864
if accountName == "" {
815865
return nil, nil, fmt.Errorf("accountName is empty")
816866
}
@@ -822,9 +872,20 @@ func EnsureMariaDBAccount(ctx context.Context,
822872
return nil, nil, err
823873
}
824874

825-
username, err := generateUniqueUsername(userNamePrefix)
826-
if err != nil {
827-
return nil, nil, err
875+
var username string
876+
var accountType AccountType
877+
878+
if exactUserName == "" {
879+
accountType = "User"
880+
username, err = generateUniqueUsername(userNamePrefix)
881+
if err != nil {
882+
return nil, nil, err
883+
}
884+
} else if userNamePrefix != "" {
885+
return nil, nil, fmt.Errorf("userNamePrefix and exactUserName are mutually exclusive")
886+
} else {
887+
accountType = "System"
888+
username = exactUserName
828889
}
829890

830891
account = &MariaDBAccount{
@@ -837,9 +898,10 @@ func EnsureMariaDBAccount(ctx context.Context,
837898
// MariaDBAccount once this is filled in
838899
},
839900
Spec: MariaDBAccountSpec{
840-
UserName: username,
841-
Secret: fmt.Sprintf("%s-db-secret", accountName),
842-
RequireTLS: requireTLS,
901+
UserName: username,
902+
Secret: fmt.Sprintf("%s-db-secret", accountName),
903+
RequireTLS: requireTLS,
904+
AccountType: accountType,
843905
},
844906
}
845907

@@ -849,6 +911,7 @@ func EnsureMariaDBAccount(ctx context.Context,
849911
if account.Spec.Secret == "" {
850912
account.Spec.Secret = fmt.Sprintf("%s-db-secret", accountName)
851913
}
914+
852915
}
853916

854917
dbSecret, _, err := secret.GetSecret(ctx, helper, account.Spec.Secret, namespace)
@@ -858,9 +921,14 @@ func EnsureMariaDBAccount(ctx context.Context,
858921
return nil, nil, err
859922
}
860923

861-
dbPassword, err := generateDBPassword()
862-
if err != nil {
863-
return nil, nil, err
924+
var dbPassword string
925+
if exactPassword == "" {
926+
dbPassword, err = generateDBPassword()
927+
if err != nil {
928+
return nil, nil, err
929+
}
930+
} else {
931+
dbPassword = exactPassword
864932
}
865933

866934
dbSecret = &corev1.Secret{
@@ -874,7 +942,7 @@ func EnsureMariaDBAccount(ctx context.Context,
874942
}
875943
}
876944

877-
_, err = createOrPatchAccountAndSecret(ctx, helper, account, dbSecret, map[string]string{})
945+
_, err = createOrPatchAccountAndSecret(ctx, helper, account, dbSecret, labels)
878946
if err != nil {
879947
return nil, nil, err
880948
}
@@ -890,6 +958,7 @@ func EnsureMariaDBAccount(ctx context.Context,
890958
)
891959

892960
return account, dbSecret, nil
961+
893962
}
894963

895964
// generateUniqueUsername creates a MySQL-compliant database username based on

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

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,18 @@ spec:
7878
maximum: 3
7979
minimum: 0
8080
type: integer
81+
rootDatabaseAccount:
82+
description: |-
83+
RootDatabaseAccount - name of MariaDBAccount which will be used to
84+
generate root account / password.
85+
this account is generated if not exists, and a name is chosen based
86+
on a naming convention if not present
87+
type: string
8188
secret:
82-
description: Name of the secret to look for password keys
89+
description: |-
90+
Name of the legacy secret to locate the initial galera root
91+
password
92+
this field will be removed once scripts can adjust to using root_auth.sh
8393
type: string
8494
storageClass:
8595
description: Storage class to host the mariadb databases
@@ -118,7 +128,6 @@ spec:
118128
required:
119129
- containerImage
120130
- replicas
121-
- secret
122131
- storageClass
123132
- storageRequest
124133
type: object
@@ -237,6 +246,9 @@ spec:
237246
the opentack-operator in the top-level CR (e.g. the ContainerImage)
238247
format: int64
239248
type: integer
249+
rootDatabaseSecret:
250+
description: name of the Secret that is being used for the root password
251+
type: string
240252
safeToBootstrap:
241253
description: Name of the node that can safely bootstrap a cluster
242254
type: string

0 commit comments

Comments
 (0)