Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 14 additions & 2 deletions api/bases/mariadb.openstack.org_galeras.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -137,8 +137,18 @@ spec:
More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
type: object
type: object
rootDatabaseAccount:
description: |-
RootDatabaseAccount - name of MariaDBAccount which will be used to
generate root account / password.
this account is generated if not exists, and a name is chosen based
on a naming convention if not present
type: string
secret:
description: Name of the secret to look for password keys
description: |-
Name of the legacy secret to locate the initial galera root
password
this field will be removed once scripts can adjust to using root_auth.sh
type: string
storageClass:
description: Storage class to host the mariadb databases
Expand Down Expand Up @@ -177,7 +187,6 @@ spec:
required:
- containerImage
- replicas
- secret
- storageClass
- storageRequest
type: object
Expand Down Expand Up @@ -296,6 +305,9 @@ spec:
the opentack-operator in the top-level CR (e.g. the ContainerImage)
format: int64
type: integer
rootDatabaseSecret:
description: name of the Secret that is being used for the root password
type: string
safeToBootstrap:
description: Name of the node that can safely bootstrap a cluster
type: string
Expand Down
14 changes: 14 additions & 0 deletions api/bases/mariadb.openstack.org_mariadbaccounts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ spec:
spec:
description: MariaDBAccountSpec defines the desired state of MariaDBAccount
properties:
accountType:
default: User
enum:
- User
- System
type: string
requireTLS:
default: false
description: Account must use TLS to connect to the database
Expand Down Expand Up @@ -108,6 +114,14 @@ spec:
- type
type: object
type: array
currentSecret:
description: |-
the Secret that's currently in use for the account.
keeping a handle to this secret allows us to remove its finalizer
when it's replaced with a new one. It also is useful for storing
the current "root" secret separate from a newly proposed one which is
needed when changing the database root password.
type: string
hash:
additionalProperties:
type: string
Expand Down
7 changes: 7 additions & 0 deletions api/v1beta1/conditions.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ const (
// ReasonDBServiceNameError - error getting the DB service hostname
ReasonDBServiceNameError condition.Reason = "DatabaseServiceNameError"

// ReasonDBResourceDeleted - the galera resource has been marked for deletion
ReasonDBResourceDeleted condition.Reason = "DatabaseResourceDeleted"

// ReasonDBSync - Database sync in progress
ReasonDBSync condition.Reason = "DBSync"
)
Expand Down Expand Up @@ -92,8 +95,12 @@ const (

MariaDBServerNotBootstrappedMessage = "MariaDB / Galera server not bootstrapped"

MariaDBServerDeletedMessage = "MariaDB / Galera server has been marked for deletion"

MariaDBAccountReadyInitMessage = "MariaDBAccount create / drop not started"

MariaDBSystemAccountReadyMessage = "MariaDBAccount System account '%s' creation complete"

MariaDBAccountReadyMessage = "MariaDBAccount creation complete"

MariaDBAccountNotReadyMessage = "MariaDBAccount is not present: %s"
Expand Down
17 changes: 15 additions & 2 deletions api/v1beta1/galera_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,19 @@ type GaleraSpec struct {

// GaleraSpec defines the desired state of Galera
type GaleraSpecCore struct {
// Name of the secret to look for password keys
// +kubebuilder:validation:Required
// Name of the legacy secret to locate the initial galera root
// password
// this field will be removed once scripts can adjust to using root_auth.sh
// +kubebuilder:validation:Optional
Secret string `json:"secret"`

// RootDatabaseAccount - name of MariaDBAccount which will be used to
// generate root account / password.
// this account is generated if not exists, and a name is chosen based
// on a naming convention if not present
// +kubebuilder:validation:Optional
RootDatabaseAccount string `json:"rootDatabaseAccount"`

// Storage class to host the mariadb databases
// +kubebuilder:validation:Required
StorageClass string `json:"storageClass"`
Expand Down Expand Up @@ -113,6 +123,9 @@ type GaleraAttributes struct {
type GaleraStatus struct {
// A map of database node attributes for each pod
Attributes map[string]GaleraAttributes `json:"attributes,omitempty"`
// name of the Secret that is being used for the root password
// +kubebuilder:validation:Optional
RootDatabaseSecret string `json:"rootDatabaseSecret"`
// Name of the node that can safely bootstrap a cluster
SafeToBootstrap string `json:"safeToBootstrap,omitempty"`
// Is the galera cluster currently running
Expand Down
29 changes: 26 additions & 3 deletions api/v1beta1/mariadbaccount_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@ const (
// AccountDeleteHash hash
AccountDeleteHash = "accountdelete"

// DbRootPassword selector for galera root account
DbRootPasswordSelector = "DbRootPassword"

// DatabasePassword selector for MariaDBAccount->Secret
DatabasePasswordSelector = "DatabasePassword"
)
Expand All @@ -48,10 +45,28 @@ type MariaDBAccountSpec struct {
// Account must use TLS to connect to the database
// +kubebuilder:default=false
RequireTLS bool `json:"requireTLS"`

// +kubebuilder:validation:Enum=User;System
// +kubebuilder:default=User
AccountType AccountType `json:"accountType,omitempty"`
}

type AccountType string

const (
User AccountType = "User"
System AccountType = "System"
)

// MariaDBAccountStatus defines the observed state of MariaDBAccount
type MariaDBAccountStatus struct {
// the Secret that's currently in use for the account.
// keeping a handle to this secret allows us to remove its finalizer
// when it's replaced with a new one. It also is useful for storing
// the current "root" secret separate from a newly proposed one which is
// needed when changing the database root password.
CurrentSecret string `json:"currentSecret,omitempty"`

// Deployment Conditions
Conditions condition.Conditions `json:"conditions,omitempty" optional:"true"`

Expand Down Expand Up @@ -85,3 +100,11 @@ type MariaDBAccountList struct {
func init() {
SchemeBuilder.Register(&MariaDBAccount{}, &MariaDBAccountList{})
}

func (mariadbAccount MariaDBAccount) IsSystemAccount() bool {
return mariadbAccount.Spec.AccountType == System
}

func (mariadbAccount MariaDBAccount) IsUserAccount() bool {
return mariadbAccount.Spec.AccountType == "" || mariadbAccount.Spec.AccountType == User
}
129 changes: 99 additions & 30 deletions api/v1beta1/mariadbdatabase_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,50 @@ func DeleteDatabaseAndAccountFinalizers(
namespace string,
) error {

err := DeleteAccountFinalizers(
ctx,
h,
accountName,
namespace,
)
if err != nil {
return err
}

// also do a delete for "unused" MariaDBAccounts, associated with
// this MariaDBDatabase.
err = DeleteUnusedMariaDBAccountFinalizers(
ctx, h, name, accountName, namespace,
)
if err != nil && !k8s_errors.IsNotFound(err) {
return err
}

mariaDBDatabase, err := GetDatabase(ctx, h, name, namespace)
if err != nil && !k8s_errors.IsNotFound(err) {
return err
} else if err == nil && controllerutil.RemoveFinalizer(mariaDBDatabase, h.GetFinalizer()) {
err := h.GetClient().Update(ctx, mariaDBDatabase)
if err != nil && !k8s_errors.IsNotFound(err) {
return err
}
util.LogForObject(h, fmt.Sprintf("Removed finalizer %s from MariaDBDatabase %s", h.GetFinalizer(), mariaDBDatabase.Spec.Name), mariaDBDatabase)
}

return nil
}

// DeleteAccountFinalizers performs just the primary account + secret finalizer
// removal part of DeleteDatabaseAndAccountFinalizers
func DeleteAccountFinalizers(
ctx context.Context,
h *helper.Helper,
accountName string,
namespace string,
) error {
if accountName == "" {
return fmt.Errorf("Account name is blank")
}
databaseAccount, err := GetAccount(ctx, h, accountName, namespace)
if err != nil && !k8s_errors.IsNotFound(err) {
return err
Expand Down Expand Up @@ -572,26 +616,6 @@ func DeleteDatabaseAndAccountFinalizers(
}
}

// also do a delete for "unused" MariaDBAccounts, associated with
// this MariaDBDatabase.
err = DeleteUnusedMariaDBAccountFinalizers(
ctx, h, name, accountName, namespace,
)
if err != nil && !k8s_errors.IsNotFound(err) {
return err
}

mariaDBDatabase, err := GetDatabase(ctx, h, name, namespace)
if err != nil && !k8s_errors.IsNotFound(err) {
return err
} else if err == nil && controllerutil.RemoveFinalizer(mariaDBDatabase, h.GetFinalizer()) {
err := h.GetClient().Update(ctx, mariaDBDatabase)
if err != nil && !k8s_errors.IsNotFound(err) {
return err
}
util.LogForObject(h, fmt.Sprintf("Removed finalizer %s from MariaDBDatabase %s", h.GetFinalizer(), mariaDBDatabase.Spec.Name), mariaDBDatabase)
}

return nil
}

Expand Down Expand Up @@ -806,6 +830,32 @@ func EnsureMariaDBAccount(ctx context.Context,
userNamePrefix string,
) (*MariaDBAccount, *corev1.Secret, error) {

return ensureMariaDBAccount(
ctx, helper, accountName, namespace, requireTLS,
userNamePrefix, "", "", map[string]string{})

}

// EnsureMariaDBSystemAccount ensures a MariaDBAccount has been created for a given
// operator calling the function, and returns the MariaDBAccount and its
// Secret for use in consumption into a configuration.
// Unlike EnsureMariaDBAccount, the function accepts an exact username that
// expected to remain constant, supporting in-place password changes for the
// account.
func EnsureMariaDBSystemAccount(ctx context.Context,
helper *helper.Helper,
accountName string, galeraInstanceName string, namespace string, requireTLS bool,
exactUserName string, exactPassword string) (*MariaDBAccount, *corev1.Secret, error) {
return ensureMariaDBAccount(
ctx, helper, accountName, namespace, requireTLS,
"", exactUserName, exactPassword, map[string]string{"dbName": galeraInstanceName})
}

func ensureMariaDBAccount(ctx context.Context,
helper *helper.Helper,
accountName string, namespace string, requireTLS bool,
userNamePrefix string, exactUserName string, exactPassword string, labels map[string]string,
) (*MariaDBAccount, *corev1.Secret, error) {
if accountName == "" {
return nil, nil, fmt.Errorf("accountName is empty")
}
Expand All @@ -817,9 +867,20 @@ func EnsureMariaDBAccount(ctx context.Context,
return nil, nil, err
}

username, err := generateUniqueUsername(userNamePrefix)
if err != nil {
return nil, nil, err
var username string
var accountType AccountType

if exactUserName == "" {
accountType = "User"
username, err = generateUniqueUsername(userNamePrefix)
if err != nil {
return nil, nil, err
}
} else if userNamePrefix != "" {
return nil, nil, fmt.Errorf("userNamePrefix and exactUserName are mutually exclusive")
} else {
accountType = "System"
username = exactUserName
}

account = &MariaDBAccount{
Expand All @@ -832,9 +893,10 @@ func EnsureMariaDBAccount(ctx context.Context,
// MariaDBAccount once this is filled in
},
Spec: MariaDBAccountSpec{
UserName: username,
Secret: fmt.Sprintf("%s-db-secret", accountName),
RequireTLS: requireTLS,
UserName: username,
Secret: fmt.Sprintf("%s-db-secret", accountName),
RequireTLS: requireTLS,
AccountType: accountType,
},
}

Expand All @@ -844,6 +906,7 @@ func EnsureMariaDBAccount(ctx context.Context,
if account.Spec.Secret == "" {
account.Spec.Secret = fmt.Sprintf("%s-db-secret", accountName)
}

}

dbSecret, _, err := secret.GetSecret(ctx, helper, account.Spec.Secret, namespace)
Expand All @@ -853,9 +916,14 @@ func EnsureMariaDBAccount(ctx context.Context,
return nil, nil, err
}

dbPassword, err := generateDBPassword()
if err != nil {
return nil, nil, err
var dbPassword string
if exactPassword == "" {
dbPassword, err = generateDBPassword()
if err != nil {
return nil, nil, err
}
} else {
dbPassword = exactPassword
}

dbSecret = &corev1.Secret{
Expand All @@ -869,7 +937,7 @@ func EnsureMariaDBAccount(ctx context.Context,
}
}

_, err = createOrPatchAccountAndSecret(ctx, helper, account, dbSecret, map[string]string{})
_, err = createOrPatchAccountAndSecret(ctx, helper, account, dbSecret, labels)
if err != nil {
return nil, nil, err
}
Expand All @@ -885,6 +953,7 @@ func EnsureMariaDBAccount(ctx context.Context,
)

return account, dbSecret, nil

}

// generateUniqueUsername creates a MySQL-compliant database username based on
Expand Down
Loading