From 80f688c88a8ee971d09053c896817788f5cf3b6b Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sat, 9 Mar 2024 16:37:17 -0500 Subject: [PATCH] migrate from databaseUsername to databaseAccount and fully use MariaDBAccount --- .../telemetry.openstack.org_autoscalings.yaml | 16 +- .../telemetry.openstack.org_ceilometers.yaml | 5 - .../telemetry.openstack.org_telemetries.yaml | 21 +-- api/v1beta1/autoscaling_types.go | 8 +- api/v1beta1/telemetry_types.go | 5 - .../telemetry.openstack.org_autoscalings.yaml | 16 +- .../telemetry.openstack.org_ceilometers.yaml | 5 - .../telemetry.openstack.org_telemetries.yaml | 21 +-- controllers/aodh_controller.go | 163 +++++++++++------- controllers/autoscaling_controller.go | 17 +- pkg/autoscaling/const.go | 9 +- .../suites/autoscaling/tests/01-deploy.yaml | 2 +- .../kuttl/suites/default/tests/01-deploy.yaml | 2 +- tests/kuttl/suites/tls/tests/02-deploy.yaml | 2 +- 14 files changed, 150 insertions(+), 142 deletions(-) diff --git a/api/bases/telemetry.openstack.org_autoscalings.yaml b/api/bases/telemetry.openstack.org_autoscalings.yaml index a33019cf..51f12fb9 100644 --- a/api/bases/telemetry.openstack.org_autoscalings.yaml +++ b/api/bases/telemetry.openstack.org_autoscalings.yaml @@ -48,16 +48,16 @@ spec: content gets added to to /etc//.conf.d directory as custom.conf file. type: string + databaseAccount: + default: aodh + description: DatabaseAccount - optional MariaDBAccount CR name + used for aodh DB, defaults to aodh + type: string databaseInstance: description: MariaDB instance name Right now required by the maridb-operator to get the credentials from the instance to create the DB Might not be required in future type: string - databaseUser: - default: aodh - description: Database user name Needed to connect to a database - used by aodh - type: string defaultConfigOverwrite: additionalProperties: type: string @@ -255,7 +255,6 @@ spec: passwordSelector: default: aodhService: AodhPassword - database: AodhDatabasePassword description: PasswordSelectors - Selectors to identify the service from the Secret properties: @@ -264,11 +263,6 @@ spec: description: AodhService - Selector to get the aodh service password from the Secret type: string - database: - default: AodhDatabasePassword - description: Database - Selector to get the aodh database - user password from the Secret - type: string service: default: CeilometerPassword description: Service - Selector to get the ceilometer service diff --git a/api/bases/telemetry.openstack.org_ceilometers.yaml b/api/bases/telemetry.openstack.org_ceilometers.yaml index 83f43c66..94ab6afc 100644 --- a/api/bases/telemetry.openstack.org_ceilometers.yaml +++ b/api/bases/telemetry.openstack.org_ceilometers.yaml @@ -76,11 +76,6 @@ spec: description: AodhService - Selector to get the aodh service password from the Secret type: string - database: - default: AodhDatabasePassword - description: Database - Selector to get the aodh database user - password from the Secret - type: string service: default: CeilometerPassword description: Service - Selector to get the ceilometer service diff --git a/api/bases/telemetry.openstack.org_telemetries.yaml b/api/bases/telemetry.openstack.org_telemetries.yaml index 1f798673..2b4de60d 100644 --- a/api/bases/telemetry.openstack.org_telemetries.yaml +++ b/api/bases/telemetry.openstack.org_telemetries.yaml @@ -51,16 +51,16 @@ spec: The content gets added to to /etc//.conf.d directory as custom.conf file. type: string + databaseAccount: + default: aodh + description: DatabaseAccount - optional MariaDBAccount CR + name used for aodh DB, defaults to aodh + type: string databaseInstance: description: MariaDB instance name Right now required by the maridb-operator to get the credentials from the instance to create the DB Might not be required in future type: string - databaseUser: - default: aodh - description: Database user name Needed to connect to a database - used by aodh - type: string defaultConfigOverwrite: additionalProperties: type: string @@ -269,7 +269,6 @@ spec: passwordSelector: default: aodhService: AodhPassword - database: AodhDatabasePassword description: PasswordSelectors - Selectors to identify the service from the Secret properties: @@ -278,11 +277,6 @@ spec: description: AodhService - Selector to get the aodh service password from the Secret type: string - database: - default: AodhDatabasePassword - description: Database - Selector to get the aodh database - user password from the Secret - type: string service: default: CeilometerPassword description: Service - Selector to get the ceilometer @@ -417,11 +411,6 @@ spec: description: AodhService - Selector to get the aodh service password from the Secret type: string - database: - default: AodhDatabasePassword - description: Database - Selector to get the aodh database - user password from the Secret - type: string service: default: CeilometerPassword description: Service - Selector to get the ceilometer service diff --git a/api/v1beta1/autoscaling_types.go b/api/v1beta1/autoscaling_types.go index c56bb219..d589e966 100644 --- a/api/v1beta1/autoscaling_types.go +++ b/api/v1beta1/autoscaling_types.go @@ -68,13 +68,13 @@ type AodhCore struct { // Might not be required in future DatabaseInstance string `json:"databaseInstance"` - // Database user name - // Needed to connect to a database used by aodh + // +kubebuilder:validation:Optional // +kubebuilder:default=aodh - DatabaseUser string `json:"databaseUser,omitempty"` + // DatabaseAccount - optional MariaDBAccount CR name used for aodh DB, defaults to aodh + DatabaseAccount string `json:"databaseAccount"` // PasswordSelectors - Selectors to identify the service from the Secret - // +kubebuilder:default:={aodhService: AodhPassword, database: AodhDatabasePassword} + // +kubebuilder:default:={aodhService: AodhPassword} PasswordSelectors PasswordsSelector `json:"passwordSelector,omitempty"` // ServiceUser - optional username used for this service to register in keystone diff --git a/api/v1beta1/telemetry_types.go b/api/v1beta1/telemetry_types.go index 218d925a..f738a884 100644 --- a/api/v1beta1/telemetry_types.go +++ b/api/v1beta1/telemetry_types.go @@ -36,11 +36,6 @@ type PasswordsSelector struct { // +kubebuilder:validation:Optional // +kubebuilder:default:=AodhPassword AodhService string `json:"aodhService"` - - // Database - Selector to get the aodh database user password from the Secret - // +kubebuilder:validation:Optional - // +kubebuilder:default:=AodhDatabasePassword - Database string `json:"database"` } // TelemetrySpec defines the desired state of Telemetry diff --git a/config/crd/bases/telemetry.openstack.org_autoscalings.yaml b/config/crd/bases/telemetry.openstack.org_autoscalings.yaml index a33019cf..51f12fb9 100644 --- a/config/crd/bases/telemetry.openstack.org_autoscalings.yaml +++ b/config/crd/bases/telemetry.openstack.org_autoscalings.yaml @@ -48,16 +48,16 @@ spec: content gets added to to /etc//.conf.d directory as custom.conf file. type: string + databaseAccount: + default: aodh + description: DatabaseAccount - optional MariaDBAccount CR name + used for aodh DB, defaults to aodh + type: string databaseInstance: description: MariaDB instance name Right now required by the maridb-operator to get the credentials from the instance to create the DB Might not be required in future type: string - databaseUser: - default: aodh - description: Database user name Needed to connect to a database - used by aodh - type: string defaultConfigOverwrite: additionalProperties: type: string @@ -255,7 +255,6 @@ spec: passwordSelector: default: aodhService: AodhPassword - database: AodhDatabasePassword description: PasswordSelectors - Selectors to identify the service from the Secret properties: @@ -264,11 +263,6 @@ spec: description: AodhService - Selector to get the aodh service password from the Secret type: string - database: - default: AodhDatabasePassword - description: Database - Selector to get the aodh database - user password from the Secret - type: string service: default: CeilometerPassword description: Service - Selector to get the ceilometer service diff --git a/config/crd/bases/telemetry.openstack.org_ceilometers.yaml b/config/crd/bases/telemetry.openstack.org_ceilometers.yaml index 83f43c66..94ab6afc 100644 --- a/config/crd/bases/telemetry.openstack.org_ceilometers.yaml +++ b/config/crd/bases/telemetry.openstack.org_ceilometers.yaml @@ -76,11 +76,6 @@ spec: description: AodhService - Selector to get the aodh service password from the Secret type: string - database: - default: AodhDatabasePassword - description: Database - Selector to get the aodh database user - password from the Secret - type: string service: default: CeilometerPassword description: Service - Selector to get the ceilometer service diff --git a/config/crd/bases/telemetry.openstack.org_telemetries.yaml b/config/crd/bases/telemetry.openstack.org_telemetries.yaml index 1f798673..2b4de60d 100644 --- a/config/crd/bases/telemetry.openstack.org_telemetries.yaml +++ b/config/crd/bases/telemetry.openstack.org_telemetries.yaml @@ -51,16 +51,16 @@ spec: The content gets added to to /etc//.conf.d directory as custom.conf file. type: string + databaseAccount: + default: aodh + description: DatabaseAccount - optional MariaDBAccount CR + name used for aodh DB, defaults to aodh + type: string databaseInstance: description: MariaDB instance name Right now required by the maridb-operator to get the credentials from the instance to create the DB Might not be required in future type: string - databaseUser: - default: aodh - description: Database user name Needed to connect to a database - used by aodh - type: string defaultConfigOverwrite: additionalProperties: type: string @@ -269,7 +269,6 @@ spec: passwordSelector: default: aodhService: AodhPassword - database: AodhDatabasePassword description: PasswordSelectors - Selectors to identify the service from the Secret properties: @@ -278,11 +277,6 @@ spec: description: AodhService - Selector to get the aodh service password from the Secret type: string - database: - default: AodhDatabasePassword - description: Database - Selector to get the aodh database - user password from the Secret - type: string service: default: CeilometerPassword description: Service - Selector to get the ceilometer @@ -417,11 +411,6 @@ spec: description: AodhService - Selector to get the aodh service password from the Secret type: string - database: - default: AodhDatabasePassword - description: Database - Selector to get the aodh database - user password from the Secret - type: string service: default: CeilometerPassword description: Service - Selector to get the ceilometer service diff --git a/controllers/aodh_controller.go b/controllers/aodh_controller.go index 87b06d0e..bb7cfa56 100644 --- a/controllers/aodh_controller.go +++ b/controllers/aodh_controller.go @@ -55,7 +55,7 @@ func (r *AutoscalingReconciler) reconcileDeleteAodh( Log.Info("Reconciling Service Aodh delete") // remove db finalizer first - db, err := mariadbv1.GetDatabaseByName(ctx, helper, autoscaling.DatabaseName) + db, err := mariadbv1.GetDatabaseByNameAndAccount(ctx, helper, autoscaling.DatabaseCRName, instance.Spec.Aodh.DatabaseAccount, instance.Namespace) if err != nil && !k8s_errors.IsNotFound(err) { return ctrl.Result{}, err } @@ -147,70 +147,13 @@ func (r *AutoscalingReconciler) reconcileInitAodh( if instance.Status.Hash == nil { instance.Status.Hash = map[string]string{} } - // - // create service DB instance - // - db := mariadbv1.NewDatabaseWithNamespace( - // instance.Name - // TODO: We might want to change the db name. - // The mariadb-operator is currently implemented - // in a way, that the db name needs to be the - // same as the user - instance.Spec.Aodh.DatabaseUser, - instance.Spec.Aodh.DatabaseUser, - instance.Spec.Aodh.Secret, - map[string]string{ - "dbName": instance.Spec.Aodh.DatabaseInstance, - }, - autoscaling.ServiceName, - instance.Namespace, - ) - // create or patch the DB - ctrlResult, err = db.CreateOrPatchDBByName( - ctx, - helper, - instance.Spec.Aodh.DatabaseInstance, - ) + + _, result, err := r.ensureDB(ctx, helper, instance) if err != nil { - instance.Status.Conditions.Set(condition.FalseCondition( - condition.DBReadyCondition, - condition.ErrorReason, - condition.SeverityWarning, - condition.DBReadyErrorMessage, - err.Error())) return ctrl.Result{}, err + } else if (result != ctrl.Result{}) { + return result, nil } - if (ctrlResult != ctrl.Result{}) { - instance.Status.Conditions.Set(condition.FalseCondition( - condition.DBReadyCondition, - condition.RequestedReason, - condition.SeverityInfo, - condition.DBReadyRunningMessage)) - return ctrlResult, nil - } - // wait for the DB to be setup - ctrlResult, err = db.WaitForDBCreated(ctx, helper) - if err != nil { - instance.Status.Conditions.Set(condition.FalseCondition( - condition.DBReadyCondition, - condition.ErrorReason, - condition.SeverityWarning, - condition.DBReadyErrorMessage, - err.Error())) - return ctrlResult, err - } - if (ctrlResult != ctrl.Result{}) { - instance.Status.Conditions.Set(condition.FalseCondition( - condition.DBReadyCondition, - condition.RequestedReason, - condition.SeverityInfo, - condition.DBReadyRunningMessage)) - return ctrlResult, nil - } - // update Status.DatabaseHostname, used to config the service - instance.Status.DatabaseHostname = db.GetDatabaseHostname() - instance.Status.Conditions.MarkTrue(condition.DBReadyCondition, condition.DBReadyMessage) - // create service DB - end // // run Aodh db sync @@ -256,6 +199,94 @@ func (r *AutoscalingReconciler) reconcileInitAodh( return ctrl.Result{}, nil } +// ensureDB - create aodh DB instance +func (r *AutoscalingReconciler) ensureDB( + ctx context.Context, + h *helper.Helper, + instance *telemetryv1.Autoscaling, +) (*mariadbv1.Database, ctrl.Result, error) { + // ensure MariaDBAccount exists. This account record may be created by + // openstack-operator or the cloud operator up front without a specific + // MariaDBDatabase configured yet. Otherwise, a MariaDBAccount CR is + // created here with a generated username as well as a secret with + // generated password. The MariaDBAccount is created without being + // yet associated with any MariaDBDatabase. + _, _, err := mariadbv1.EnsureMariaDBAccount( + ctx, h, instance.Spec.Aodh.DatabaseAccount, + instance.Namespace, false, autoscaling.DatabaseUsernamePrefix, + ) + + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + mariadbv1.MariaDBAccountReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + mariadbv1.MariaDBAccountNotReadyMessage, + err.Error())) + + return nil, ctrl.Result{}, err + } + instance.Status.Conditions.MarkTrue( + mariadbv1.MariaDBAccountReadyCondition, + mariadbv1.MariaDBAccountReadyMessage) + + // create aodh DB instance + // + db := mariadbv1.NewDatabaseForAccount( + instance.Spec.Aodh.DatabaseInstance, // mariadb/galera service to target + autoscaling.DatabaseName, // name used in CREATE DATABASE in mariadb + autoscaling.DatabaseCRName, // CR name for MariaDBDatabase + instance.Spec.Aodh.DatabaseAccount, // CR name for MariaDBAccount + instance.Namespace, // namespace + ) + + // create or patch the DB + ctrlResult, err := db.CreateOrPatchAll(ctx, h) + + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.DBReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.DBReadyErrorMessage, + err.Error())) + return db, ctrl.Result{}, err + } + if (ctrlResult != ctrl.Result{}) { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.DBReadyCondition, + condition.RequestedReason, + condition.SeverityInfo, + condition.DBReadyRunningMessage)) + return db, ctrlResult, nil + } + // wait for the DB to be setup + ctrlResult, err = db.WaitForDBCreated(ctx, h) + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.DBReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.DBReadyErrorMessage, + err.Error())) + return db, ctrlResult, err + } + if (ctrlResult != ctrl.Result{}) { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.DBReadyCondition, + condition.RequestedReason, + condition.SeverityInfo, + condition.DBReadyRunningMessage)) + return db, ctrlResult, nil + } + // update Status.DatabaseHostname, used to config the service + instance.Status.DatabaseHostname = db.GetDatabaseHostname() + instance.Status.Conditions.MarkTrue(condition.DBReadyCondition, condition.DBReadyMessage) + // create service DB - end + + return db, ctrlResult, nil +} + func (r *AutoscalingReconciler) reconcileNormalAodh( ctx context.Context, instance *telemetryv1.Autoscaling, @@ -504,6 +535,14 @@ func (r *AutoscalingReconciler) reconcileNormalAodh( configVars[tls.TLSHashName] = env.SetValue(certsHash) } + // remove finalizers from unused MariaDBAccount records + err = mariadbv1.DeleteUnusedMariaDBAccountFinalizers( + ctx, helper, autoscaling.DatabaseCRName, + instance.Spec.Aodh.DatabaseAccount, instance.Namespace) + if err != nil { + return ctrl.Result{}, err + } + // all cert input checks out so report InputReady instance.Status.Conditions.MarkTrue(condition.TLSInputReadyCondition, condition.InputReadyMessage) diff --git a/controllers/autoscaling_controller.go b/controllers/autoscaling_controller.go index bbc8ddb3..68a045cc 100644 --- a/controllers/autoscaling_controller.go +++ b/controllers/autoscaling_controller.go @@ -436,12 +436,19 @@ func (r *AutoscalingReconciler) reconcileNormal( instance.Status.PrometheusPort = instance.Spec.PrometheusPort } + db, result, err := r.ensureDB(ctx, helper, instance) + if err != nil { + return ctrl.Result{}, err + } else if (result != ctrl.Result{}) { + return result, nil + } + // // create secret required for autoscaling input // - %-scripts configmap holding scripts to e.g. bootstrap the service // - %-config configmap holding minimal autoscaling config required to get the service up, user can add additional files to be added to the service // - err = r.generateServiceConfig(ctx, helper, instance, &configMapVars, memcached) + err = r.generateServiceConfig(ctx, helper, instance, &configMapVars, memcached, db) if err != nil { instance.Status.Conditions.Set(condition.FalseCondition( condition.ServiceConfigReadyCondition, @@ -518,6 +525,7 @@ func (r *AutoscalingReconciler) generateServiceConfig( instance *telemetryv1.Autoscaling, envVars *map[string]env.Setter, mc *memcachedv1.Memcached, + db *mariadbv1.Database, ) error { cmLabels := labels.GetLabels(instance, labels.GetGroupLabel(autoscaling.ServiceName), map[string]string{}) customData := map[string]string{common.CustomServiceConfigFileName: instance.Spec.Aodh.CustomServiceConfig} @@ -545,6 +553,9 @@ func (r *AutoscalingReconciler) generateServiceConfig( return err } + databaseAccount := db.GetAccount() + databaseSecret := db.GetSecret() + templateParameters := map[string]interface{}{ "AodhUser": instance.Spec.Aodh.ServiceUser, "AodhPassword": string(ospSecret.Data[instance.Spec.Aodh.PasswordSelectors.AodhService]), @@ -555,8 +566,8 @@ func (r *AutoscalingReconciler) generateServiceConfig( "MemcachedServers": strings.Join(mc.Status.ServerList, ","), "MemcachedServersWithInet": strings.Join(mc.Status.ServerListWithInet, ","), "DatabaseConnection": fmt.Sprintf("mysql+pymysql://%s:%s@%s/%s", - instance.Spec.Aodh.DatabaseUser, - string(ospSecret.Data[instance.Spec.Aodh.PasswordSelectors.Database]), + databaseAccount.Spec.UserName, + string(databaseSecret.Data[mariadbv1.DatabasePasswordSelector]), instance.Status.DatabaseHostname, autoscaling.DatabaseName), } diff --git a/pkg/autoscaling/const.go b/pkg/autoscaling/const.go index e35ce338..d70be876 100644 --- a/pkg/autoscaling/const.go +++ b/pkg/autoscaling/const.go @@ -26,9 +26,16 @@ const ( // PrometheusRetention - PrometheusRetention = "5h" - // DatabaseName - + // DatabaseName - Name of the database used in CREATE DATABASE statement DatabaseName = "aodh" + // DatabaseCRName - Name of the MariaDBDatabase CR + DatabaseCRName = "aodh" + + // DatabaseUsernamePrefix - used by EnsureMariaDBAccount when a new username + // is to be generated, e.g. "aodh_e5a4", "aodh_78bc", etc + DatabaseUsernamePrefix = "aodh" + // AodhAPIPort - AodhAPIPort = 8042 ) diff --git a/tests/kuttl/suites/autoscaling/tests/01-deploy.yaml b/tests/kuttl/suites/autoscaling/tests/01-deploy.yaml index 7361cbfa..e2d1534f 100644 --- a/tests/kuttl/suites/autoscaling/tests/01-deploy.yaml +++ b/tests/kuttl/suites/autoscaling/tests/01-deploy.yaml @@ -10,7 +10,7 @@ spec: notifierImage: "quay.io/mmagr/openstack-aodh-notifier:current-podified" listenerImage: "quay.io/mmagr/openstack-aodh-listener:current-podified" passwordSelectors: - databaseUser: aodh + databaseAccount: aodh databaseInstance: openstack memcachedInstance: memcached heatInstance: heat diff --git a/tests/kuttl/suites/default/tests/01-deploy.yaml b/tests/kuttl/suites/default/tests/01-deploy.yaml index 89b9c27b..6716a76e 100644 --- a/tests/kuttl/suites/default/tests/01-deploy.yaml +++ b/tests/kuttl/suites/default/tests/01-deploy.yaml @@ -22,7 +22,7 @@ spec: notifierImage: "quay.io/mmagr/openstack-aodh-notifier:current-podified" listenerImage: "quay.io/mmagr/openstack-aodh-listener:current-podified" passwordSelectors: - databaseUser: aodh + databaseAccount: aodh databaseInstance: openstack memcachedInstance: memcached heatInstance: heat diff --git a/tests/kuttl/suites/tls/tests/02-deploy.yaml b/tests/kuttl/suites/tls/tests/02-deploy.yaml index 7679317a..47816ff6 100644 --- a/tests/kuttl/suites/tls/tests/02-deploy.yaml +++ b/tests/kuttl/suites/tls/tests/02-deploy.yaml @@ -10,7 +10,7 @@ spec: notifierImage: "quay.io/mmagr/openstack-aodh-notifier:current-podified" listenerImage: "quay.io/mmagr/openstack-aodh-listener:current-podified" passwordSelectors: - databaseUser: aodh + databaseAccount: aodh databaseInstance: openstack memcachedInstance: memcached tls: