diff --git a/api/bases/heat.openstack.org_heatapis.yaml b/api/bases/heat.openstack.org_heatapis.yaml index fc6b155b..f7dc99c9 100644 --- a/api/bases/heat.openstack.org_heatapis.yaml +++ b/api/bases/heat.openstack.org_heatapis.yaml @@ -54,15 +54,14 @@ spec: added to to /etc//.conf.d directory as custom.conf file. type: string + databaseAccount: + default: heat + description: DatabaseAccount - optional MariaDBAccount used for heat + DB, defaults to heat. + type: string databaseHostname: description: DatabaseHostname - Heat Database Hostname type: string - databaseUser: - default: heat - description: 'DatabaseUser - optional username used for heat DB, defaults - to heat. TODO: -> implement needs work in mariadb-operator, right - now only heat.' - type: string defaultConfigOverwrite: additionalProperties: type: string @@ -254,7 +253,6 @@ spec: passwordSelectors: default: authEncryptionKey: HeatAuthEncryptionKey - database: HeatDatabasePassword service: HeatPassword description: PasswordSelectors - Selectors to identify the DB and ServiceUser password from the Secret @@ -264,11 +262,6 @@ spec: description: AuthEncryptionKey - Selector to get the heat auth encryption key from the Secret type: string - database: - default: HeatDatabasePassword - description: 'Database - Selector to get the heat Database user - password from the Secret TODO: not used, need change in mariadb-operator' - type: string service: default: HeatPassword description: Service - Selector to get the heat service password diff --git a/api/bases/heat.openstack.org_heatcfnapis.yaml b/api/bases/heat.openstack.org_heatcfnapis.yaml index a27914bd..0a9bfbc3 100644 --- a/api/bases/heat.openstack.org_heatcfnapis.yaml +++ b/api/bases/heat.openstack.org_heatcfnapis.yaml @@ -54,15 +54,14 @@ spec: added to to /etc//.conf.d directory as custom.conf file. type: string + databaseAccount: + default: heat + description: DatabaseAccount - optional MariaDBAccount used for heat + DB, defaults to heat. + type: string databaseHostname: description: DatabaseHostname - Heat Database Hostname type: string - databaseUser: - default: heat - description: 'DatabaseUser - optional username used for heat DB, defaults - to heat. TODO: -> implement needs work in mariadb-operator, right - now only heat.' - type: string defaultConfigOverwrite: additionalProperties: type: string @@ -254,7 +253,6 @@ spec: passwordSelectors: default: authEncryptionKey: HeatAuthEncryptionKey - database: HeatDatabasePassword service: HeatPassword description: PasswordSelectors - Selectors to identify the DB and ServiceUser password from the Secret @@ -264,11 +262,6 @@ spec: description: AuthEncryptionKey - Selector to get the heat auth encryption key from the Secret type: string - database: - default: HeatDatabasePassword - description: 'Database - Selector to get the heat Database user - password from the Secret TODO: not used, need change in mariadb-operator' - type: string service: default: HeatPassword description: Service - Selector to get the heat service password diff --git a/api/bases/heat.openstack.org_heatengines.yaml b/api/bases/heat.openstack.org_heatengines.yaml index 5fc779af..f69e70eb 100644 --- a/api/bases/heat.openstack.org_heatengines.yaml +++ b/api/bases/heat.openstack.org_heatengines.yaml @@ -54,15 +54,14 @@ spec: added to to /etc//.conf.d directory as custom.conf file. type: string + databaseAccount: + default: heat + description: DatabaseAccount - optional MariaDBAccount used for heat + DB, defaults to heat. + type: string databaseHostname: description: DatabaseHostname - Heat Database Hostname type: string - databaseUser: - default: heat - description: 'DatabaseUser - optional username used for heat DB, defaults - to heat. TODO: -> implement needs work in mariadb-operator, right - now only heat.' - type: string defaultConfigOverwrite: additionalProperties: type: string @@ -80,7 +79,6 @@ spec: passwordSelectors: default: authEncryptionKey: HeatAuthEncryptionKey - database: HeatDatabasePassword service: HeatPassword description: PasswordSelectors - Selectors to identify the DB and ServiceUser password from the Secret @@ -90,11 +88,6 @@ spec: description: AuthEncryptionKey - Selector to get the heat auth encryption key from the Secret type: string - database: - default: HeatDatabasePassword - description: 'Database - Selector to get the heat Database user - password from the Secret TODO: not used, need change in mariadb-operator' - type: string service: default: HeatPassword description: Service - Selector to get the heat service password diff --git a/api/bases/heat.openstack.org_heats.yaml b/api/bases/heat.openstack.org_heats.yaml index 5b2a0364..603b3ae4 100644 --- a/api/bases/heat.openstack.org_heats.yaml +++ b/api/bases/heat.openstack.org_heats.yaml @@ -51,17 +51,16 @@ spec: added to to /etc//.conf.d directory as custom.conf file. type: string + databaseAccount: + default: heat + description: DatabaseAccount - optional MariaDBAccount used for heat + DB, defaults to heat. + 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: heat - description: 'DatabaseUser - optional username used for heat DB, defaults - to heat. TODO: -> implement needs work in mariadb-operator, right - now only heat.' - type: string defaultConfigOverwrite: additionalProperties: type: string @@ -771,7 +770,6 @@ spec: passwordSelectors: default: authEncryptionKey: HeatAuthEncryptionKey - database: HeatDatabasePassword service: HeatPassword description: PasswordSelectors - Selectors to identify the DB and ServiceUser password from the Secret @@ -781,11 +779,6 @@ spec: description: AuthEncryptionKey - Selector to get the heat auth encryption key from the Secret type: string - database: - default: HeatDatabasePassword - description: 'Database - Selector to get the heat Database user - password from the Secret TODO: not used, need change in mariadb-operator' - type: string service: default: HeatPassword description: Service - Selector to get the heat service password diff --git a/api/go.mod b/api/go.mod index 2516257b..cc525b04 100644 --- a/api/go.mod +++ b/api/go.mod @@ -38,6 +38,8 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/onsi/ginkgo/v2 v2.15.0 // indirect + github.com/onsi/gomega v1.31.1 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_golang v1.18.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect diff --git a/api/go.sum b/api/go.sum index d87655cb..d1e037bf 100644 --- a/api/go.sum +++ b/api/go.sum @@ -63,8 +63,10 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY= -github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= +github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY= +github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= +github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo= +github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0= github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240214144842-5dcac51e5b36 h1:ZSVQYuevQyYZ+bD/x3NLzZx/oVcrsT2tG5agqFzs8fQ= github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240214144842-5dcac51e5b36/go.mod h1:bQwzyQtWCR9F0+IvWZ30J9d1lB6tcX3CNJ0Ten1smDw= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= diff --git a/api/v1beta1/common_types.go b/api/v1beta1/common_types.go index 9b10754d..e851576a 100644 --- a/api/v1beta1/common_types.go +++ b/api/v1beta1/common_types.go @@ -30,9 +30,8 @@ type HeatTemplate struct { // +kubebuilder:validation:Optional // +kubebuilder:default=heat - // DatabaseUser - optional username used for heat DB, defaults to heat. - // TODO: -> implement needs work in mariadb-operator, right now only heat. - DatabaseUser string `json:"databaseUser"` + // DatabaseAccount - optional MariaDBAccount used for heat DB, defaults to heat. + DatabaseAccount string `json:"databaseAccount"` // +kubebuilder:validation:Required // Secret containing OpenStack password information for heat HeatDatabasePassword, HeatPassword @@ -40,7 +39,7 @@ type HeatTemplate struct { Secret string `json:"secret"` // +kubebuilder:validation:Optional - // +kubebuilder:default={database: HeatDatabasePassword, service: HeatPassword, authEncryptionKey: HeatAuthEncryptionKey} + // +kubebuilder:default={service: HeatPassword, authEncryptionKey: HeatAuthEncryptionKey} // PasswordSelectors - Selectors to identify the DB and ServiceUser password from the Secret PasswordSelectors PasswordSelector `json:"passwordSelectors"` } @@ -89,11 +88,6 @@ type APIOverrideSpec struct { // PasswordSelector .. type PasswordSelector struct { - // +kubebuilder:validation:Optional - // +kubebuilder:default="HeatDatabasePassword" - // Database - Selector to get the heat Database user password from the Secret - // TODO: not used, need change in mariadb-operator - Database string `json:"database"` // +kubebuilder:validation:Optional // +kubebuilder:default="HeatPassword" // Service - Selector to get the heat service password from the Secret diff --git a/config/crd/bases/heat.openstack.org_heatapis.yaml b/config/crd/bases/heat.openstack.org_heatapis.yaml index fc6b155b..f7dc99c9 100644 --- a/config/crd/bases/heat.openstack.org_heatapis.yaml +++ b/config/crd/bases/heat.openstack.org_heatapis.yaml @@ -54,15 +54,14 @@ spec: added to to /etc//.conf.d directory as custom.conf file. type: string + databaseAccount: + default: heat + description: DatabaseAccount - optional MariaDBAccount used for heat + DB, defaults to heat. + type: string databaseHostname: description: DatabaseHostname - Heat Database Hostname type: string - databaseUser: - default: heat - description: 'DatabaseUser - optional username used for heat DB, defaults - to heat. TODO: -> implement needs work in mariadb-operator, right - now only heat.' - type: string defaultConfigOverwrite: additionalProperties: type: string @@ -254,7 +253,6 @@ spec: passwordSelectors: default: authEncryptionKey: HeatAuthEncryptionKey - database: HeatDatabasePassword service: HeatPassword description: PasswordSelectors - Selectors to identify the DB and ServiceUser password from the Secret @@ -264,11 +262,6 @@ spec: description: AuthEncryptionKey - Selector to get the heat auth encryption key from the Secret type: string - database: - default: HeatDatabasePassword - description: 'Database - Selector to get the heat Database user - password from the Secret TODO: not used, need change in mariadb-operator' - type: string service: default: HeatPassword description: Service - Selector to get the heat service password diff --git a/config/crd/bases/heat.openstack.org_heatcfnapis.yaml b/config/crd/bases/heat.openstack.org_heatcfnapis.yaml index a27914bd..0a9bfbc3 100644 --- a/config/crd/bases/heat.openstack.org_heatcfnapis.yaml +++ b/config/crd/bases/heat.openstack.org_heatcfnapis.yaml @@ -54,15 +54,14 @@ spec: added to to /etc//.conf.d directory as custom.conf file. type: string + databaseAccount: + default: heat + description: DatabaseAccount - optional MariaDBAccount used for heat + DB, defaults to heat. + type: string databaseHostname: description: DatabaseHostname - Heat Database Hostname type: string - databaseUser: - default: heat - description: 'DatabaseUser - optional username used for heat DB, defaults - to heat. TODO: -> implement needs work in mariadb-operator, right - now only heat.' - type: string defaultConfigOverwrite: additionalProperties: type: string @@ -254,7 +253,6 @@ spec: passwordSelectors: default: authEncryptionKey: HeatAuthEncryptionKey - database: HeatDatabasePassword service: HeatPassword description: PasswordSelectors - Selectors to identify the DB and ServiceUser password from the Secret @@ -264,11 +262,6 @@ spec: description: AuthEncryptionKey - Selector to get the heat auth encryption key from the Secret type: string - database: - default: HeatDatabasePassword - description: 'Database - Selector to get the heat Database user - password from the Secret TODO: not used, need change in mariadb-operator' - type: string service: default: HeatPassword description: Service - Selector to get the heat service password diff --git a/config/crd/bases/heat.openstack.org_heatengines.yaml b/config/crd/bases/heat.openstack.org_heatengines.yaml index 5fc779af..f69e70eb 100644 --- a/config/crd/bases/heat.openstack.org_heatengines.yaml +++ b/config/crd/bases/heat.openstack.org_heatengines.yaml @@ -54,15 +54,14 @@ spec: added to to /etc//.conf.d directory as custom.conf file. type: string + databaseAccount: + default: heat + description: DatabaseAccount - optional MariaDBAccount used for heat + DB, defaults to heat. + type: string databaseHostname: description: DatabaseHostname - Heat Database Hostname type: string - databaseUser: - default: heat - description: 'DatabaseUser - optional username used for heat DB, defaults - to heat. TODO: -> implement needs work in mariadb-operator, right - now only heat.' - type: string defaultConfigOverwrite: additionalProperties: type: string @@ -80,7 +79,6 @@ spec: passwordSelectors: default: authEncryptionKey: HeatAuthEncryptionKey - database: HeatDatabasePassword service: HeatPassword description: PasswordSelectors - Selectors to identify the DB and ServiceUser password from the Secret @@ -90,11 +88,6 @@ spec: description: AuthEncryptionKey - Selector to get the heat auth encryption key from the Secret type: string - database: - default: HeatDatabasePassword - description: 'Database - Selector to get the heat Database user - password from the Secret TODO: not used, need change in mariadb-operator' - type: string service: default: HeatPassword description: Service - Selector to get the heat service password diff --git a/config/crd/bases/heat.openstack.org_heats.yaml b/config/crd/bases/heat.openstack.org_heats.yaml index 5b2a0364..603b3ae4 100644 --- a/config/crd/bases/heat.openstack.org_heats.yaml +++ b/config/crd/bases/heat.openstack.org_heats.yaml @@ -51,17 +51,16 @@ spec: added to to /etc//.conf.d directory as custom.conf file. type: string + databaseAccount: + default: heat + description: DatabaseAccount - optional MariaDBAccount used for heat + DB, defaults to heat. + 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: heat - description: 'DatabaseUser - optional username used for heat DB, defaults - to heat. TODO: -> implement needs work in mariadb-operator, right - now only heat.' - type: string defaultConfigOverwrite: additionalProperties: type: string @@ -771,7 +770,6 @@ spec: passwordSelectors: default: authEncryptionKey: HeatAuthEncryptionKey - database: HeatDatabasePassword service: HeatPassword description: PasswordSelectors - Selectors to identify the DB and ServiceUser password from the Secret @@ -781,11 +779,6 @@ spec: description: AuthEncryptionKey - Selector to get the heat auth encryption key from the Secret type: string - database: - default: HeatDatabasePassword - description: 'Database - Selector to get the heat Database user - password from the Secret TODO: not used, need change in mariadb-operator' - type: string service: default: HeatPassword description: Service - Selector to get the heat service password diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 522b2e07..9ffc8053 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -68,8 +68,12 @@ rules: resources: - secrets verbs: + - create + - delete - get - list + - patch + - update - watch - apiGroups: - "" diff --git a/config/samples/heat_v1beta1_heatapi.yaml b/config/samples/heat_v1beta1_heatapi.yaml index 577a7296..54547620 100644 --- a/config/samples/heat_v1beta1_heatapi.yaml +++ b/config/samples/heat_v1beta1_heatapi.yaml @@ -4,7 +4,7 @@ metadata: name: heat-api spec: databaseHostname: openstack - databaseUser: heat + databaseAccount: heat passwordSelectors: authEncryptionKey: HeatAuthEncryptionKey database: HeatDatabasePassword diff --git a/config/samples/heat_v1beta1_heatapicfn.yaml b/config/samples/heat_v1beta1_heatapicfn.yaml index 5522eb18..9b7c2b3a 100644 --- a/config/samples/heat_v1beta1_heatapicfn.yaml +++ b/config/samples/heat_v1beta1_heatapicfn.yaml @@ -4,7 +4,7 @@ metadata: name: heat-cfnapi spec: databaseHostname: openstack - databaseUser: heat + databaseAccount: heat passwordSelectors: authEncryptionKey: HeatAuthEncryptionKey database: HeatDatabasePassword diff --git a/config/samples/heat_v1beta1_heatengine.yaml b/config/samples/heat_v1beta1_heatengine.yaml index f4991e54..df696256 100644 --- a/config/samples/heat_v1beta1_heatengine.yaml +++ b/config/samples/heat_v1beta1_heatengine.yaml @@ -4,7 +4,7 @@ metadata: name: heat-engine spec: databaseHostname: openstack - databaseUser: heat + databaseAccount: heat passwordSelectors: authEncryptionKey: HeatAuthEncryptionKey database: HeatDatabasePassword diff --git a/controllers/heat_controller.go b/controllers/heat_controller.go index ef89e707..172eb3c5 100644 --- a/controllers/heat_controller.go +++ b/controllers/heat_controller.go @@ -20,10 +20,10 @@ import ( "github.com/openstack-k8s-operators/lib-common/modules/common" condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition" - configmap "github.com/openstack-k8s-operators/lib-common/modules/common/configmap" "github.com/openstack-k8s-operators/lib-common/modules/common/endpoint" "github.com/openstack-k8s-operators/lib-common/modules/common/env" "github.com/openstack-k8s-operators/lib-common/modules/common/job" + "github.com/openstack-k8s-operators/lib-common/modules/common/secret" "github.com/openstack-k8s-operators/lib-common/modules/common/service" k8s_errors "k8s.io/apimachinery/pkg/api/errors" @@ -83,7 +83,7 @@ var keystoneAPI *keystonev1.KeystoneAPI // +kubebuilder:rbac:groups=heat.openstack.org,resources=heatengines/finalizers,verbs=update // +kubebuilder:rbac:groups=core,resources=configmaps,verbs=get;list;watch;create;update;patch;delete; // +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete; -// +kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch; +// +kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;create;update;patch;delete;watch // +kubebuilder:rbac:groups=core,resources=services,verbs=get;list;watch;create;update;patch;delete; // +kubebuilder:rbac:groups=batch,resources=jobs,verbs=get;list;watch;create;update;patch;delete; // +kubebuilder:rbac:groups=mariadb.openstack.org,resources=mariadbdatabases,verbs=get;list;watch;create;update;patch;delete; @@ -333,7 +333,7 @@ func (r *HeatReconciler) reconcileDelete(ctx context.Context, instance *heatv1be r.Log.Info("Reconciling Heat delete") // remove db finalizer first - db, err := mariadbv1.GetDatabaseByName(ctx, helper, instance.Name) + db, err := mariadbv1.GetDatabaseByNameAndAccount(ctx, helper, instance.Name, instance.Spec.DatabaseAccount, instance.Namespace) if err != nil && !k8s_errors.IsNotFound(err) { return ctrl.Result{}, err } @@ -403,6 +403,32 @@ func (r *HeatReconciler) reconcileNormal(ctx context.Context, instance *heatv1be // run check OpenStack secret - end + // 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, helper, instance.Spec.DatabaseAccount, + instance.Namespace, false, + ) + + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + mariadbv1.MariaDBAccountReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + mariadbv1.MariaDBAccountNotReadyMessage, + err.Error())) + + return ctrl.Result{}, err + } + instance.Status.Conditions.MarkTrue( + mariadbv1.MariaDBAccountReadyCondition, + mariadbv1.MariaDBAccountReadyMessage, + ) + // // Check for required memcached used for caching // @@ -560,6 +586,17 @@ func (r *HeatReconciler) reconcileNormal(ctx context.Context, instance *heatv1be return ctrlResult, err } + // remove finalizers from previous MariaDBAccounts for which we have + // switched. + // TODO(zzzeek) - This is here because I dont have test fixtures to + // simulate all the conditions below in heat_controller_test.go. It's not + // clear if subsequent instructions here are going to be re-deploying new + // versions of services that also need new database credentials. + err = mariadbv1.DeleteUnusedMariaDBAccountFinalizers(ctx, helper, instance.Name, instance.Spec.DatabaseAccount, instance.Namespace) + if err != nil { + return ctrl.Result{}, err + } + // // normal reconcile tasks // @@ -575,6 +612,7 @@ func (r *HeatReconciler) reconcileNormal(ctx context.Context, instance *heatv1be err.Error())) return ctrl.Result{}, err } + if (ctrlResult != ctrl.Result{}) { instance.Status.Conditions.Set(condition.FalseCondition( heatv1beta1.HeatStackDomainReadyCondition, @@ -618,6 +656,7 @@ func (r *HeatReconciler) reconcileNormal(ctx context.Context, instance *heatv1be err.Error())) return ctrl.Result{}, err } + if op != controllerutil.OperationResultNone { r.Log.Info(fmt.Sprintf("Deployment %s successfully reconciled - operation: %s", instance.Name, string(op))) } @@ -668,22 +707,17 @@ func (r *HeatReconciler) reconcileInit(ctx context.Context, // // create service DB instance // - db := mariadbv1.NewDatabaseWithNamespace( - heat.DatabaseName, - instance.Spec.DatabaseUser, - instance.Spec.Secret, - map[string]string{ - "dbName": instance.Spec.DatabaseInstance, - }, - "heat", - instance.Namespace, + db := mariadbv1.NewDatabaseForAccount( + instance.Spec.DatabaseInstance, // mariadb/galera service to target + heat.DatabaseName, // name used in CREATE DATABASE in mariadb + instance.Name, // CR name for MariaDBDatabase + instance.Spec.DatabaseAccount, // CR name for MariaDBAccount + instance.Namespace, // namespace ) + // create or patch the DB - ctrlResult, err := db.CreateOrPatchDBByName( - ctx, - helper, - instance.Spec.DatabaseInstance, - ) + ctrlResult, err := db.CreateOrPatchAll(ctx, helper) + if err != nil { instance.Status.Conditions.Set(condition.FalseCondition( condition.DBReadyCondition, @@ -730,7 +764,9 @@ func (r *HeatReconciler) reconcileInit(ctx context.Context, // run Heat db sync // dbSyncHash := instance.Status.Hash[heatv1beta1.DbSyncHash] + jobDef := heat.DBSyncJob(instance, serviceLabels) + dbSyncjob := job.NewJob( jobDef, heatv1beta1.DbSyncHash, @@ -742,6 +778,7 @@ func (r *HeatReconciler) reconcileInit(ctx context.Context, ctx, helper, ) + if (ctrlResult != ctrl.Result{}) { instance.Status.Conditions.Set(condition.FalseCondition( condition.DBSyncReadyCondition, @@ -759,6 +796,7 @@ func (r *HeatReconciler) reconcileInit(ctx context.Context, err.Error())) return ctrl.Result{}, err } + if dbSyncjob.HasChanged() { instance.Status.Hash[heatv1beta1.DbSyncHash] = dbSyncjob.GetHash() if err := r.Client.Status().Update(ctx, instance); err != nil { @@ -913,6 +951,11 @@ func (r *HeatReconciler) generateServiceConfigMaps( return err } + databaseAccount, dbSecret, err := mariadbv1.GetAccountAndSecret(ctx, h, instance.Spec.DatabaseAccount, instance.Namespace) + if err != nil { + return err + } + templateParameters := map[string]interface{}{ "KeystoneInternalURL": authURL, "ServiceUser": instance.Spec.ServiceUser, @@ -920,6 +963,12 @@ func (r *HeatReconciler) generateServiceConfigMaps( "StackDomainName": heat.StackDomainName, "MemcachedServers": strings.Join(mc.Status.ServerList, ","), "MemcachedServersWithInet": strings.Join(mc.Status.ServerListWithInet, ","), + "DatabaseConnection": fmt.Sprintf("mysql+pymysql://%s:%s@%s/%s", + databaseAccount.Spec.UserName, + string(dbSecret.Data[mariadbv1.DatabasePasswordSelector]), + instance.Status.DatabaseHostname, + heat.DatabaseName, + ), } // create HeatAPI httpd vhost template parameters @@ -973,7 +1022,7 @@ func (r *HeatReconciler) generateServiceConfigMaps( Labels: cmLabels, }, } - return configmap.EnsureConfigMaps(ctx, h, instance, cms, envVars) + return secret.EnsureSecrets(ctx, h, instance, cms, envVars) } func (r *HeatReconciler) reconcileUpgrade(ctx context.Context, instance *heatv1beta1.Heat, helper *helper.Helper) (ctrl.Result, error) { diff --git a/controllers/heatapi_controller.go b/controllers/heatapi_controller.go index 7f463797..0332b6be 100644 --- a/controllers/heatapi_controller.go +++ b/controllers/heatapi_controller.go @@ -45,7 +45,6 @@ import ( keystonev1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1" "github.com/openstack-k8s-operators/lib-common/modules/common" "github.com/openstack-k8s-operators/lib-common/modules/common/condition" - "github.com/openstack-k8s-operators/lib-common/modules/common/configmap" "github.com/openstack-k8s-operators/lib-common/modules/common/deployment" "github.com/openstack-k8s-operators/lib-common/modules/common/endpoint" "github.com/openstack-k8s-operators/lib-common/modules/common/env" @@ -78,7 +77,7 @@ var keystoneServices = []map[string]string{ // +kubebuilder:rbac:groups=heat.openstack.org,resources=heatapis/finalizers,verbs=update // +kubebuilder:rbac:groups=core,resources=configmaps,verbs=get;list;watch;create;update;patch;delete; // +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete; -// +kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch; +// +kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;create;update;patch;delete;watch // +kubebuilder:rbac:groups=core,resources=services,verbs=get;list;watch;create;update;patch;delete; // +kubebuilder:rbac:groups=keystone.openstack.org,resources=keystoneapis,verbs=get;list;watch; // +kubebuilder:rbac:groups=keystone.openstack.org,resources=keystoneservices,verbs=get;list;watch;create;update;patch;delete @@ -602,29 +601,17 @@ func (r *HeatAPIReconciler) reconcileNormal(ctx context.Context, instance *heatv // parentHeatName := heat.GetOwningHeatName(instance) - configMaps := []string{ - fmt.Sprintf("%s-scripts", parentHeatName), // ScriptsConfigMap - fmt.Sprintf("%s-config-data", parentHeatName), // ConfigMap + ctrlResult, err := r.getSecret(ctx, helper, instance, fmt.Sprintf("%s-scripts", parentHeatName), &configMapVars) + if err != nil { + return ctrlResult, err } - - _, err = configmap.GetConfigMaps(ctx, helper, instance, configMaps, instance.Namespace, &configMapVars) + ctrlResult, err = r.getSecret(ctx, helper, instance, fmt.Sprintf("%s-config-data", parentHeatName), &configMapVars) + // note r.getSecret adds Conditions with condition.InputReadyWaitingMessage + // when secret is not found if err != nil { - if k8s_errors.IsNotFound(err) { - instance.Status.Conditions.Set(condition.FalseCondition( - condition.InputReadyCondition, - condition.RequestedReason, - condition.SeverityInfo, - condition.InputReadyWaitingMessage)) - return ctrl.Result{RequeueAfter: time.Second * 10}, fmt.Errorf("could not find all config maps for parent Heat CR %s", parentHeatName) - } - instance.Status.Conditions.Set(condition.FalseCondition( - condition.InputReadyCondition, - condition.ErrorReason, - condition.SeverityWarning, - condition.InputReadyErrorMessage, - err.Error())) - return ctrl.Result{}, err + return ctrlResult, err } + instance.Status.Conditions.MarkTrue(condition.InputReadyCondition, condition.InputReadyMessage) // run check parent Heat CR config maps - end @@ -805,6 +792,40 @@ func (r *HeatAPIReconciler) reconcileUpgrade(ctx context.Context, instance *heat return ctrl.Result{}, nil } +// getSecret - get the specified secret, and add its hash to envVars +func (r *HeatAPIReconciler) getSecret( + ctx context.Context, + h *helper.Helper, + instance *heatv1beta1.HeatAPI, + secretName string, + envVars *map[string]env.Setter, +) (ctrl.Result, error) { + secret, hash, err := secret.GetSecret(ctx, h, secretName, instance.Namespace) + if err != nil { + if k8s_errors.IsNotFound(err) { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.InputReadyCondition, + condition.RequestedReason, + condition.SeverityInfo, + condition.InputReadyWaitingMessage)) + return ctrl.Result{RequeueAfter: time.Duration(10) * time.Second}, fmt.Errorf("Secret %s not found", secretName) + } + instance.Status.Conditions.Set(condition.FalseCondition( + condition.InputReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.InputReadyErrorMessage, + err.Error())) + return ctrl.Result{}, err + } + + // Add a prefix to the var name to avoid accidental collision with other non-secret + // vars. The secret names themselves will be unique. + (*envVars)[secret.Name] = env.SetValue(hash) + + return ctrl.Result{}, nil +} + // generateServiceConfigMaps - create custom configmap to hold service-specific config // TODO add DefaultConfigOverwrite func (r *HeatAPIReconciler) generateServiceConfigMaps( @@ -843,7 +864,7 @@ func (r *HeatAPIReconciler) generateServiceConfigMaps( }, } - return configmap.EnsureConfigMaps(ctx, h, instance, cms, envVars) + return secret.EnsureSecrets(ctx, h, instance, cms, envVars) } // createHashOfInputHashes - creates a hash of hashes which gets added to the resources which requires a restart diff --git a/controllers/heatcfnapi_controller.go b/controllers/heatcfnapi_controller.go index e33a74a1..fc49a593 100644 --- a/controllers/heatcfnapi_controller.go +++ b/controllers/heatcfnapi_controller.go @@ -45,7 +45,6 @@ import ( keystonev1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1" "github.com/openstack-k8s-operators/lib-common/modules/common" "github.com/openstack-k8s-operators/lib-common/modules/common/condition" - "github.com/openstack-k8s-operators/lib-common/modules/common/configmap" "github.com/openstack-k8s-operators/lib-common/modules/common/deployment" "github.com/openstack-k8s-operators/lib-common/modules/common/endpoint" "github.com/openstack-k8s-operators/lib-common/modules/common/env" @@ -78,7 +77,7 @@ var keystoneCfnServices = []map[string]string{ // +kubebuilder:rbac:groups=heat.openstack.org,resources=heatcfnapis/finalizers,verbs=update // +kubebuilder:rbac:groups=core,resources=configmaps,verbs=get;list;watch;create;update;patch;delete; // +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete; -// +kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch; +// +kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;create;update;patch;delete;watch // +kubebuilder:rbac:groups=core,resources=services,verbs=get;list;watch;create;update;patch;delete; // +kubebuilder:rbac:groups=keystone.openstack.org,resources=keystoneapis,verbs=get;list;watch; // +kubebuilder:rbac:groups=keystone.openstack.org,resources=keystoneservices,verbs=get;list;watch;create;update;patch;delete @@ -606,29 +605,17 @@ func (r *HeatCfnAPIReconciler) reconcileNormal(ctx context.Context, instance *he // parentHeatName := heat.GetOwningHeatName(instance) - configMaps := []string{ - fmt.Sprintf("%s-scripts", parentHeatName), // ScriptsConfigMap - fmt.Sprintf("%s-config-data", parentHeatName), // ConfigMap + ctrlResult, err := r.getSecret(ctx, helper, instance, fmt.Sprintf("%s-scripts", parentHeatName), &configMapVars) + if err != nil { + return ctrlResult, err } - - _, err = configmap.GetConfigMaps(ctx, helper, instance, configMaps, instance.Namespace, &configMapVars) + ctrlResult, err = r.getSecret(ctx, helper, instance, fmt.Sprintf("%s-config-data", parentHeatName), &configMapVars) + // note r.getSecret adds Conditions with condition.InputReadyWaitingMessage + // when secret is not found if err != nil { - if k8s_errors.IsNotFound(err) { - instance.Status.Conditions.Set(condition.FalseCondition( - condition.InputReadyCondition, - condition.RequestedReason, - condition.SeverityInfo, - condition.InputReadyWaitingMessage)) - return ctrl.Result{RequeueAfter: time.Second * 10}, fmt.Errorf("could not find all config maps for parent Heat CR %s", parentHeatName) - } - instance.Status.Conditions.Set(condition.FalseCondition( - condition.InputReadyCondition, - condition.ErrorReason, - condition.SeverityWarning, - condition.InputReadyErrorMessage, - err.Error())) - return ctrl.Result{}, err + return ctrlResult, err } + instance.Status.Conditions.MarkTrue(condition.InputReadyCondition, condition.InputReadyMessage) // run check parent Heat CR config maps - end @@ -809,6 +796,38 @@ func (r *HeatCfnAPIReconciler) reconcileUpgrade(ctx context.Context, instance *h return ctrl.Result{}, nil } +// getSecret - get the specified secret, and add its hash to envVars +func (r *HeatCfnAPIReconciler) getSecret( + ctx context.Context, + h *helper.Helper, + instance *heatv1beta1.HeatCfnAPI, + secretName string, + envVars *map[string]env.Setter, +) (ctrl.Result, error) { + secret, hash, err := secret.GetSecret(ctx, h, secretName, instance.Namespace) + if err != nil { + if k8s_errors.IsNotFound(err) { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.InputReadyCondition, + condition.RequestedReason, + condition.SeverityInfo, + condition.InputReadyWaitingMessage)) + return ctrl.Result{RequeueAfter: time.Duration(10) * time.Second}, fmt.Errorf("Secret %s not found", secretName) + } + instance.Status.Conditions.Set(condition.FalseCondition( + condition.InputReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.InputReadyErrorMessage, + err.Error())) + return ctrl.Result{}, err + } + + (*envVars)[secret.Name] = env.SetValue(hash) + + return ctrl.Result{}, nil +} + // generateServiceConfigMaps - create custom configmap to hold service-specific config // TODO add DefaultConfigOverwrite func (r *HeatCfnAPIReconciler) generateServiceConfigMaps( @@ -847,7 +866,7 @@ func (r *HeatCfnAPIReconciler) generateServiceConfigMaps( }, } - return configmap.EnsureConfigMaps(ctx, h, instance, cms, envVars) + return secret.EnsureSecrets(ctx, h, instance, cms, envVars) } // createHashOfInputHashes - creates a hash of hashes which gets added to the resources which requires a restart diff --git a/controllers/heatengine_controller.go b/controllers/heatengine_controller.go index 0b3b9ecb..b73500af 100644 --- a/controllers/heatengine_controller.go +++ b/controllers/heatengine_controller.go @@ -43,7 +43,6 @@ import ( heatengine "github.com/openstack-k8s-operators/heat-operator/pkg/heatengine" "github.com/openstack-k8s-operators/lib-common/modules/common" condition "github.com/openstack-k8s-operators/lib-common/modules/common/condition" - configmap "github.com/openstack-k8s-operators/lib-common/modules/common/configmap" "github.com/openstack-k8s-operators/lib-common/modules/common/deployment" "github.com/openstack-k8s-operators/lib-common/modules/common/env" "github.com/openstack-k8s-operators/lib-common/modules/common/helper" @@ -66,7 +65,7 @@ type HeatEngineReconciler struct { // +kubebuilder:rbac:groups=heat.openstack.org,resources=heatengines/finalizers,verbs=update // +kubebuilder:rbac:groups=core,resources=configmaps,verbs=get;list;watch;create;update;patch;delete; // +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete; -// +kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch; +// +kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;create;update;patch;delete;watch // +kubebuilder:rbac:groups=core,resources=services,verbs=get;list;watch;create;update;patch;delete; // +kubebuilder:rbac:groups=keystone.openstack.org,resources=keystoneapis,verbs=get;list;watch; @@ -359,29 +358,17 @@ func (r *HeatEngineReconciler) reconcileNormal( // parentHeatName := heat.GetOwningHeatName(instance) - configMaps := []string{ - fmt.Sprintf("%s-scripts", parentHeatName), // ScriptsConfigMap - fmt.Sprintf("%s-config-data", parentHeatName), // ConfigMap + ctrlResult, err := r.getSecret(ctx, helper, instance, fmt.Sprintf("%s-scripts", parentHeatName), &configMapVars) + if err != nil { + return ctrlResult, err } - - _, err = configmap.GetConfigMaps(ctx, helper, instance, configMaps, instance.Namespace, &configMapVars) + ctrlResult, err = r.getSecret(ctx, helper, instance, fmt.Sprintf("%s-config-data", parentHeatName), &configMapVars) + // note r.getSecret adds Conditions with condition.InputReadyWaitingMessage + // when secret is not found if err != nil { - if k8s_errors.IsNotFound(err) { - instance.Status.Conditions.Set(condition.FalseCondition( - condition.InputReadyCondition, - condition.RequestedReason, - condition.SeverityInfo, - condition.InputReadyWaitingMessage)) - return ctrl.Result{RequeueAfter: time.Second * 10}, fmt.Errorf("could not find all config maps for parent heat CR %s", parentHeatName) - } - instance.Status.Conditions.Set(condition.FalseCondition( - condition.InputReadyCondition, - condition.ErrorReason, - condition.SeverityWarning, - condition.InputReadyErrorMessage, - err.Error())) - return ctrl.Result{}, err + return ctrlResult, err } + instance.Status.Conditions.MarkTrue(condition.InputReadyCondition, condition.InputReadyMessage) // run check parent heat CR config maps - end @@ -458,7 +445,7 @@ func (r *HeatEngineReconciler) reconcileNormal( } // Handle service init - ctrlResult, err := r.reconcileInit(ctx, instance, helper, serviceLabels) + ctrlResult, err = r.reconcileInit(ctx, instance, helper, serviceLabels) if err != nil || (ctrlResult != ctrl.Result{}) { return ctrlResult, err } @@ -527,6 +514,38 @@ func (r *HeatEngineReconciler) reconcileUpgrade(ctx context.Context, instance *h return ctrl.Result{}, nil } +// getSecret - get the specified secret, and add its hash to envVars +func (r *HeatEngineReconciler) getSecret( + ctx context.Context, + h *helper.Helper, + instance *heatv1beta1.HeatEngine, + secretName string, + envVars *map[string]env.Setter, +) (ctrl.Result, error) { + secret, hash, err := secret.GetSecret(ctx, h, secretName, instance.Namespace) + if err != nil { + if k8s_errors.IsNotFound(err) { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.InputReadyCondition, + condition.RequestedReason, + condition.SeverityInfo, + condition.InputReadyWaitingMessage)) + return ctrl.Result{RequeueAfter: time.Duration(10) * time.Second}, fmt.Errorf("Secret %s not found", secretName) + } + instance.Status.Conditions.Set(condition.FalseCondition( + condition.InputReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.InputReadyErrorMessage, + err.Error())) + return ctrl.Result{}, err + } + + (*envVars)[secret.Name] = env.SetValue(hash) + + return ctrl.Result{}, nil +} + // generateServiceConfigMaps - create custom configmap to hold service-specific config // TODO add DefaultConfigOverwrite func (r *HeatEngineReconciler) generateServiceConfigMaps( @@ -565,7 +584,7 @@ func (r *HeatEngineReconciler) generateServiceConfigMaps( }, } - return configmap.EnsureConfigMaps(ctx, h, instance, cms, envVars) + return secret.EnsureSecrets(ctx, h, instance, cms, envVars) } // createHashOfInputHashes - creates a hash of hashes which gets added to the resources which requires a restart diff --git a/go.mod b/go.mod index e43ae089..b759a1f7 100644 --- a/go.mod +++ b/go.mod @@ -7,8 +7,8 @@ replace github.com/openstack-k8s-operators/heat-operator/api => ./api require ( github.com/go-logr/logr v1.4.1 github.com/google/uuid v1.6.0 - github.com/onsi/ginkgo/v2 v2.14.0 - github.com/onsi/gomega v1.30.0 + github.com/onsi/ginkgo/v2 v2.15.0 + github.com/onsi/gomega v1.31.1 github.com/openstack-k8s-operators/heat-operator/api v0.3.1-0.20240214134649-6643d1b09d49 github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20240214153927-179defb96a33 github.com/openstack-k8s-operators/keystone-operator/api v0.3.1-0.20240214165457-55af8e58473d @@ -87,3 +87,5 @@ require ( // mschuppert: map to latest commit from release-4.13 tag // must consistent within modules and service operators replace github.com/openshift/api => github.com/openshift/api v0.0.0-20230414143018-3367bc7e6ac7 //allow-merging + +replace github.com/openstack-k8s-operators/mariadb-operator/api => github.com/zzzeek/mariadb-operator/api v0.3.1-0.20240222195117-de879c4be63a //allow-merging diff --git a/go.sum b/go.sum index 29d40389..a663d0ba 100644 --- a/go.sum +++ b/go.sum @@ -68,10 +68,10 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/onsi/ginkgo/v2 v2.14.0 h1:vSmGj2Z5YPb9JwCWT6z6ihcUvDhuXLc3sJiqd3jMKAY= -github.com/onsi/ginkgo/v2 v2.14.0/go.mod h1:JkUdW7JkN0V6rFvsHcJ478egV3XH9NxpD27Hal/PhZw= -github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= -github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY= +github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= +github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo= +github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0= github.com/openshift/api v0.0.0-20230414143018-3367bc7e6ac7 h1:rncLxJBpFGqBztyxCMwNRnMjhhIDOWHJowi6q8G6koI= github.com/openshift/api v0.0.0-20230414143018-3367bc7e6ac7/go.mod h1:ctXNyWanKEjGj8sss1KjjHQ3ENKFm33FFnS5BKaIPh4= github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20240214153927-179defb96a33 h1:h3ctaOK8DaCvSYWmfdshd9n6EOZyOqv9JH57vMEuNII= @@ -84,8 +84,6 @@ github.com/openstack-k8s-operators/lib-common/modules/openstack v0.3.1-0.2024021 github.com/openstack-k8s-operators/lib-common/modules/openstack v0.3.1-0.20240214144842-5dcac51e5b36/go.mod h1:8QsCFttAm+X6A8I8EQThGjNjeMAYt2hK7ivbvnR3434= github.com/openstack-k8s-operators/lib-common/modules/test v0.3.1-0.20240214144842-5dcac51e5b36 h1:GXdro9f/BoLdkW1PxPlRs3e/47ml56UiJunjIO6uu3Q= github.com/openstack-k8s-operators/lib-common/modules/test v0.3.1-0.20240214144842-5dcac51e5b36/go.mod h1:82nzS+DbBe1tzaMvNHH8FctmZzQ14ZAJysFGsMJiivo= -github.com/openstack-k8s-operators/mariadb-operator/api v0.3.1-0.20240214153937-3b28b9d3d09b h1:3A0CmqlHswSLJYwddVTfQ/ndB5DfP7W2GKFv6C3jOec= -github.com/openstack-k8s-operators/mariadb-operator/api v0.3.1-0.20240214153937-3b28b9d3d09b/go.mod h1:52Ja/B4RrrytMmKh+Kf+/BPe7Fq40Pi77vcFH4yJeoU= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -108,6 +106,8 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/zzzeek/mariadb-operator/api v0.3.1-0.20240222195117-de879c4be63a h1:eVtZZAIwgoyOGv1BdNsjy1WRsosdvK13NeYhyXikOIo= +github.com/zzzeek/mariadb-operator/api v0.3.1-0.20240222195117-de879c4be63a/go.mod h1:f9IIyWeoskWoeWaDFF3qmAJ2Kqyovfi0Ar/QUfk3qag= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= diff --git a/pkg/heat/dbsync.go b/pkg/heat/dbsync.go index a521f25a..244d90eb 100644 --- a/pkg/heat/dbsync.go +++ b/pkg/heat/dbsync.go @@ -88,10 +88,8 @@ func DBSyncJob( initContainerDetails := APIDetails{ ContainerImage: instance.Spec.HeatAPI.ContainerImage, DatabaseHost: instance.Status.DatabaseHostname, - DatabaseUser: instance.Spec.DatabaseUser, DatabaseName: DatabaseName, OSPSecret: instance.Spec.Secret, - DBPasswordSelector: instance.Spec.PasswordSelectors.Database, UserPasswordSelector: instance.Spec.PasswordSelectors.Service, AuthEncryptionKeySelector: instance.Spec.PasswordSelectors.AuthEncryptionKey, VolumeMounts: initVolumeMounts, diff --git a/pkg/heat/initcontainer.go b/pkg/heat/initcontainer.go index fca8ee7c..520f7562 100644 --- a/pkg/heat/initcontainer.go +++ b/pkg/heat/initcontainer.go @@ -25,11 +25,9 @@ import ( type APIDetails struct { ContainerImage string DatabaseHost string - DatabaseUser string DatabaseName string TransportURL string OSPSecret string - DBPasswordSelector string UserPasswordSelector string AuthEncryptionKeySelector string VolumeMounts []corev1.VolumeMount @@ -56,21 +54,9 @@ func InitContainer(init APIDetails) []corev1.Container { envVars := map[string]env.Setter{} envVars["DatabaseHost"] = env.SetValue(init.DatabaseHost) - envVars["DatabaseUser"] = env.SetValue(init.DatabaseUser) envVars["DatabaseName"] = env.SetValue(init.DatabaseName) envs := []corev1.EnvVar{ - { - Name: "DatabasePassword", - ValueFrom: &corev1.EnvVarSource{ - SecretKeyRef: &corev1.SecretKeySelector{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: init.OSPSecret, - }, - Key: init.DBPasswordSelector, - }, - }, - }, { Name: "HeatPassword", ValueFrom: &corev1.EnvVarSource{ diff --git a/pkg/heat/volumes.go b/pkg/heat/volumes.go index 9f400378..911d79c5 100644 --- a/pkg/heat/volumes.go +++ b/pkg/heat/volumes.go @@ -28,22 +28,18 @@ func GetVolumes(name string) []corev1.Volume { { Name: "scripts", VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ + Secret: &corev1.SecretVolumeSource{ DefaultMode: &scriptsVolumeDefaultMode, - LocalObjectReference: corev1.LocalObjectReference{ - Name: name + "-scripts", - }, + SecretName: name + "-scripts", }, }, }, { Name: "config-data", VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ + Secret: &corev1.SecretVolumeSource{ DefaultMode: &config0640AccessMode, - LocalObjectReference: corev1.LocalObjectReference{ - Name: name + "-config-data", - }, + SecretName: name + "-config-data", }, }, }, diff --git a/pkg/heatapi/deployment.go b/pkg/heatapi/deployment.go index c2f1450b..3dc16ab1 100644 --- a/pkg/heatapi/deployment.go +++ b/pkg/heatapi/deployment.go @@ -169,10 +169,8 @@ func Deployment( initContainerDetails := heat.APIDetails{ ContainerImage: instance.Spec.ContainerImage, DatabaseHost: instance.Spec.DatabaseHostname, - DatabaseUser: instance.Spec.DatabaseUser, DatabaseName: heat.DatabaseName, OSPSecret: instance.Spec.Secret, - DBPasswordSelector: instance.Spec.PasswordSelectors.Database, UserPasswordSelector: instance.Spec.PasswordSelectors.Service, AuthEncryptionKeySelector: instance.Spec.PasswordSelectors.AuthEncryptionKey, VolumeMounts: initVolumeMounts, diff --git a/pkg/heatapi/volumes.go b/pkg/heatapi/volumes.go index 6432497b..6a384878 100644 --- a/pkg/heatapi/volumes.go +++ b/pkg/heatapi/volumes.go @@ -13,11 +13,9 @@ func getVolumes(parentName string, name string) []corev1.Volume { { Name: "config-data-custom", VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ + Secret: &corev1.SecretVolumeSource{ DefaultMode: &config0640AccessMode, - LocalObjectReference: corev1.LocalObjectReference{ - Name: name + "-config-data", - }, + SecretName: name + "-config-data", }, }, }, diff --git a/pkg/heatcfnapi/deployment.go b/pkg/heatcfnapi/deployment.go index f969d237..f7ca2b61 100644 --- a/pkg/heatcfnapi/deployment.go +++ b/pkg/heatcfnapi/deployment.go @@ -169,10 +169,8 @@ func Deployment( initContainerDetails := heat.APIDetails{ ContainerImage: instance.Spec.ContainerImage, DatabaseHost: instance.Spec.DatabaseHostname, - DatabaseUser: instance.Spec.DatabaseUser, DatabaseName: heat.DatabaseName, OSPSecret: instance.Spec.Secret, - DBPasswordSelector: instance.Spec.PasswordSelectors.Database, UserPasswordSelector: instance.Spec.PasswordSelectors.Service, AuthEncryptionKeySelector: instance.Spec.PasswordSelectors.AuthEncryptionKey, VolumeMounts: initVolumeMounts, diff --git a/pkg/heatcfnapi/volumes.go b/pkg/heatcfnapi/volumes.go index 2ee337f0..da4a891c 100644 --- a/pkg/heatcfnapi/volumes.go +++ b/pkg/heatcfnapi/volumes.go @@ -13,11 +13,9 @@ func getVolumes(parentName string, name string) []corev1.Volume { { Name: "config-data-custom", VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ + Secret: &corev1.SecretVolumeSource{ DefaultMode: &config0640AccessMode, - LocalObjectReference: corev1.LocalObjectReference{ - Name: name + "-config-data", - }, + SecretName: name + "-config-data", }, }, }, diff --git a/pkg/heatengine/deployment.go b/pkg/heatengine/deployment.go index e337793a..f5f5ba5d 100644 --- a/pkg/heatengine/deployment.go +++ b/pkg/heatengine/deployment.go @@ -139,10 +139,8 @@ func Deployment(instance *heatv1beta1.HeatEngine, configHash string, labels map[ initContainerDetails := heat.APIDetails{ ContainerImage: instance.Spec.ContainerImage, DatabaseHost: instance.Spec.DatabaseHostname, - DatabaseUser: instance.Spec.DatabaseUser, DatabaseName: heat.DatabaseName, OSPSecret: instance.Spec.Secret, - DBPasswordSelector: instance.Spec.PasswordSelectors.Database, UserPasswordSelector: instance.Spec.PasswordSelectors.Service, AuthEncryptionKeySelector: instance.Spec.PasswordSelectors.AuthEncryptionKey, VolumeMounts: initVolumeMounts, diff --git a/pkg/heatengine/volumes.go b/pkg/heatengine/volumes.go index 137f953e..9f36e787 100644 --- a/pkg/heatengine/volumes.go +++ b/pkg/heatengine/volumes.go @@ -13,11 +13,9 @@ func getVolumes(parentName string, name string) []corev1.Volume { { Name: "config-data-custom", VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ + Secret: &corev1.SecretVolumeSource{ DefaultMode: &config0640AccessMode, - LocalObjectReference: corev1.LocalObjectReference{ - Name: name + "-config-data", - }, + SecretName: name + "-config-data", }, }, }, diff --git a/templates/heat/bin/init.sh b/templates/heat/bin/init.sh index fd356207..13113215 100755 --- a/templates/heat/bin/init.sh +++ b/templates/heat/bin/init.sh @@ -16,10 +16,6 @@ set -ex # Secrets are obtained from ENV variables. -export DB=${DatabaseName:-"heat"} -export DBHOST=${DatabaseHost:?"Please specify a DatabaseHost variable."} -export DBUSER=${DatabaseUser:-"heat"} -export DBPASSWORD=${DatabasePassword:?"Please specify a DatabasePassword variable."} export PASSWORD=${HeatPassword:?"Please specify a HeatPassword variable."} export TRANSPORT_URL=${TransportURL:-""} export AUTH_ENCRYPTION_KEY=${AuthEncryptionKey:-""} @@ -73,7 +69,6 @@ if [ -n "$AUTH_ENCRYPTION_KEY" ]; then crudini --set ${SVC_CFG_MERGED} DEFAULT auth_encryption_key $AUTH_ENCRYPTION_KEY fi -crudini --set ${SVC_CFG_MERGED} database connection mysql+pymysql://${DBUSER}:${DBPASSWORD}@${DBHOST}/${DB} crudini --set ${SVC_CFG_MERGED} keystone_authtoken password $PASSWORD crudini --set ${SVC_CFG_MERGED} DEFAULT stack_domain_admin_password $PASSWORD crudini --set ${SVC_CFG_MERGED} trustee password $PASSWORD diff --git a/templates/heat/config/heat.conf b/templates/heat/config/heat.conf index d7741ea1..d17389ec 100644 --- a/templates/heat/config/heat.conf +++ b/templates/heat/config/heat.conf @@ -13,7 +13,7 @@ enabled=true memcache_servers={{ .MemcachedServers }} [database] -#connection = +connection={{ .DatabaseConnection }} max_retries=-1 db_max_retries=-1 diff --git a/tests/functional/base_test.go b/tests/functional/base_test.go index d102605a..7055e356 100644 --- a/tests/functional/base_test.go +++ b/tests/functional/base_test.go @@ -75,9 +75,8 @@ func CreateHeatSecret(namespace string, name string) *corev1.Secret { return th.CreateSecret( types.NamespacedName{Namespace: namespace, Name: name}, map[string][]byte{ - "HeatPassword": []byte("12345678"), - "HeatDatabasePassword": []byte("12345678"), - "AuthEncryptionKey": []byte("1234567812345678123456781212345678345678"), + "HeatPassword": []byte("12345678"), + "AuthEncryptionKey": []byte("1234567812345678123456781212345678345678"), }, ) } diff --git a/tests/functional/heat_controller_test.go b/tests/functional/heat_controller_test.go index 71c2da1b..63f149ed 100644 --- a/tests/functional/heat_controller_test.go +++ b/tests/functional/heat_controller_test.go @@ -26,6 +26,8 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/utils/ptr" + mariadb_test "github.com/openstack-k8s-operators/mariadb-operator/api/test/helpers" + heatv1 "github.com/openstack-k8s-operators/heat-operator/api/v1beta1" memcachedv1 "github.com/openstack-k8s-operators/infra-operator/apis/memcached/v1beta1" keystonev1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1" @@ -36,7 +38,7 @@ var _ = Describe("Heat controller", func() { var heatName types.NamespacedName var heatTransportURLName types.NamespacedName - var heatConfigMapName types.NamespacedName + var heatConfigSecretName types.NamespacedName var memcachedSpec memcachedv1.MemcachedSpec var keystoneAPI *keystonev1.KeystoneAPI @@ -50,7 +52,7 @@ var _ = Describe("Heat controller", func() { Namespace: namespace, Name: heatName.Name + "-heat-transport", } - heatConfigMapName = types.NamespacedName{ + heatConfigSecretName = types.NamespacedName{ Namespace: namespace, Name: heatName.Name + "-config-data", } @@ -70,7 +72,7 @@ var _ = Describe("Heat controller", func() { It("should have the Spec fields initialized", func() { Heat := GetHeat(heatName) Expect(Heat.Spec.DatabaseInstance).Should(Equal("openstack")) - Expect(Heat.Spec.DatabaseUser).Should(Equal("heat")) + Expect(Heat.Spec.DatabaseAccount).Should(Equal("heat")) Expect(Heat.Spec.RabbitMqClusterName).Should(Equal("rabbitmq")) Expect(Heat.Spec.ServiceUser).Should(Equal("heat")) Expect(*(Heat.Spec.HeatAPI.Replicas)).Should(Equal(int32(1))) @@ -130,8 +132,8 @@ var _ = Describe("Heat controller", func() { }, timeout, interval).Should(ContainElement("Heat")) }) - It("should not create a config map", func() { - th.AssertConfigMapDoesNotExist(heatConfigMapName) + It("should not create a config secret", func() { + th.AssertSecretDoesNotExist(heatConfigSecretName) }) }) @@ -169,8 +171,8 @@ var _ = Describe("Heat controller", func() { ) }) - It("should not create a config map", func() { - th.AssertConfigMapDoesNotExist(heatConfigMapName) + It("should not create a config secret", func() { + th.AssertSecretDoesNotExist(heatConfigSecretName) }) }) @@ -256,8 +258,8 @@ var _ = Describe("Heat controller", func() { ) }) - It("should not create a config map", func() { - th.AssertConfigMapDoesNotExist(heatConfigMapName) + It("should not create a config secret", func() { + th.AssertSecretDoesNotExist(heatConfigSecretName) }) }) @@ -300,8 +302,8 @@ var _ = Describe("Heat controller", func() { ) }) - It("should create a ConfigMap for heat.conf", func() { - cm := th.GetConfigMap(heatConfigMapName) + It("should create a Secret for heat.conf", func() { + cm := th.GetSecret(heatConfigSecretName) Expect(cm.Data["heat.conf"]).Should( ContainSubstring("stack_domain_admin=heat_stack_domain_admin")) @@ -430,4 +432,87 @@ var _ = Describe("Heat controller", func() { ) }) }) + + // Run MariaDBAccount suite tests. these are pre-packaged ginkgo tests + // that exercise standard account create / update patterns that should be + // common to all controllers that ensure MariaDBAccount CRs. + mariadb_test.MariaDBAccountSuiteTests( + "Heat", + // Populate test variables which will run inside of BeforeEach + func(harness *mariadb_test.MariaDBTestHarness) { + harness.PopulateHarness( + heatName.Namespace, + heatName.Name, + "Heat", + mariadb, + timeout, + interval, + ) + }, + // Generate a fully running Keystone service given an accountName + // needs to make it all the way to the end where the mariadb finalizers + // are removed from unused accounts since that's part of what we are testing + func(accountName types.NamespacedName) { + spec := GetDefaultHeatSpec() + spec["databaseAccount"] = accountName.Name + + DeferCleanup( + k8sClient.Delete, ctx, CreateHeatSecret(namespace, SecretName)) + DeferCleanup(th.DeleteInstance, CreateHeat(heatName, spec)) + DeferCleanup(infra.DeleteMemcached, infra.CreateMemcached(namespace, "memcached", memcachedSpec)) + infra.SimulateMemcachedReady(types.NamespacedName{ + Name: "memcached", + Namespace: namespace, + }) + DeferCleanup( + k8sClient.Delete, ctx, CreateHeatMessageBusSecret(namespace, HeatMessageBusSecretName)) + infra.SimulateTransportURLReady(heatTransportURLName) + keystoneAPIName := keystone.CreateKeystoneAPI(namespace) + keystoneAPI = keystone.GetKeystoneAPI(keystoneAPIName) + DeferCleanup(keystone.DeleteKeystoneAPI, keystoneAPIName) + DeferCleanup( + mariadb.DeleteDBService, + mariadb.CreateDBService( + namespace, + GetHeat(heatName).Spec.DatabaseInstance, + corev1.ServiceSpec{ + Ports: []corev1.ServicePort{{Port: 3306}}, + }, + ), + ) + mariadb.SimulateMariaDBAccountCompleted(accountName) + mariadb.SimulateMariaDBDatabaseCompleted(heatName) + dbSyncJobName := types.NamespacedName{ + Name: "heat-db-sync", + Namespace: namespace, + } + th.SimulateJobSuccess(dbSyncJobName) + + // TODO(zzzeek) we would prefer to simulate everything else here + // so we can get to the end of reconcile: + // * ensureStackDomain passes + // * engineDeploymentCreateOrUpdate passes + // * apiDeploymentCreateOrUpdate passes + // * cfnapiDeploymentCreateOrUpdate + + // then in heat_controller we can move + // DeleteUnusedMariaDBAccountFinalizers to the end of the reconcile + // method. + }, + // Change the account name in the service to a new name + func(newAccountName types.NamespacedName) { + + Eventually(func(g Gomega) { + heat := GetHeat(heatName) + heat.Spec.DatabaseAccount = newAccountName.Name + g.Expect(th.K8sClient.Update(ctx, heat)).Should(Succeed()) + }, timeout, interval).Should(Succeed()) + + }, + // delete the keystone instance to exercise finalizer removal + func() { + th.DeleteInstance(GetHeat(heatName)) + }, + ) + }) diff --git a/tests/kuttl/common/assert-sample-deployment.yaml b/tests/kuttl/common/assert-sample-deployment.yaml index a4d54a8f..8794a037 100644 --- a/tests/kuttl/common/assert-sample-deployment.yaml +++ b/tests/kuttl/common/assert-sample-deployment.yaml @@ -19,7 +19,7 @@ spec: [DEFAULT] debug = True databaseInstance: openstack - databaseUser: "heat" + databaseAccount: "heat" heatAPI: replicas: 1 resources: {} @@ -33,7 +33,6 @@ spec: passwordSelectors: authEncryptionKey: HeatAuthEncryptionKey service: HeatPassword - database: HeatDatabasePassword preserveJobs: false rabbitMqClusterName: rabbitmq secret: osp-secret @@ -59,10 +58,9 @@ metadata: name: heat spec: databaseHostname: openstack.heat-kuttl-tests.svc - databaseUser: heat + databaseAccount: heat passwordSelectors: authEncryptionKey: HeatAuthEncryptionKey - database: HeatDatabasePassword service: HeatPassword replicas: 1 resources: {} @@ -87,10 +85,9 @@ metadata: name: heat spec: databaseHostname: openstack.heat-kuttl-tests.svc - databaseUser: heat + databaseAccount: heat passwordSelectors: authEncryptionKey: HeatAuthEncryptionKey - database: HeatDatabasePassword service: HeatPassword replicas: 1 resources: {} @@ -115,10 +112,9 @@ metadata: name: heat spec: databaseHostname: openstack.heat-kuttl-tests.svc - databaseUser: heat + databaseAccount: heat passwordSelectors: authEncryptionKey: HeatAuthEncryptionKey - database: HeatDatabasePassword service: HeatPassword replicas: 1 resources: {} diff --git a/tests/kuttl/tests/heat_tls/01-assert.yaml b/tests/kuttl/tests/heat_tls/01-assert.yaml index baf4d05d..362ba2bb 100644 --- a/tests/kuttl/tests/heat_tls/01-assert.yaml +++ b/tests/kuttl/tests/heat_tls/01-assert.yaml @@ -139,20 +139,20 @@ spec: readOnly: true subPath: tls-ca-bundle.pem volumes: - - configMap: + - name: scripts + secret: defaultMode: 493 - name: heat-scripts - name: scripts - - configMap: + secretName: heat-scripts + - name: config-data + secret: defaultMode: 416 - name: heat-config-data - name: config-data + secretName: heat-config-data - emptyDir: {} name: config-data-merged - - configMap: + - name: config-data-custom + secret: defaultMode: 416 - name: heat-api-config-data - name: config-data-custom + secretName: heat-api-config-data - name: combined-ca-bundle secret: defaultMode: 292 @@ -228,20 +228,20 @@ spec: readOnly: true subPath: tls-ca-bundle.pem volumes: - - configMap: + - name: scripts + secret: defaultMode: 493 - name: heat-scripts - name: scripts - - configMap: + secretName: heat-scripts + - name: config-data + secret: defaultMode: 416 - name: heat-config-data - name: config-data + secretName: heat-config-data - emptyDir: {} name: config-data-merged - - configMap: + - name: config-data-custom + secret: defaultMode: 416 - name: heat-cfnapi-config-data - name: config-data-custom + secretName: heat-cfnapi-config-data - name: combined-ca-bundle secret: defaultMode: 292 @@ -301,20 +301,20 @@ spec: readOnly: true subPath: tls-ca-bundle.pem volumes: - - configMap: + - name: scripts + secret: defaultMode: 493 - name: heat-scripts - name: scripts - - configMap: + secretName: heat-scripts + - name: config-data + secret: defaultMode: 416 - name: heat-config-data - name: config-data + secretName: heat-config-data - emptyDir: {} name: config-data-merged - - configMap: + - name: config-data-custom + secret: defaultMode: 416 - name: heat-engine-config-data - name: config-data-custom + secretName: heat-engine-config-data - name: combined-ca-bundle secret: defaultMode: 292