diff --git a/src/operator/controllers/intents_reconcilers/database/database_reconciler.go b/src/operator/controllers/intents_reconcilers/database/database_reconciler.go index bc01756ec..52246765d 100644 --- a/src/operator/controllers/intents_reconcilers/database/database_reconciler.go +++ b/src/operator/controllers/intents_reconcilers/database/database_reconciler.go @@ -21,14 +21,15 @@ import ( ) const ( - ReasonApplyingDatabaseIntentsFailed = "ApplyingDatabaseIntentsFailed" - ReasonAppliedDatabaseIntents = "AppliedDatabaseIntents" - ReasonErrorFetchingPostgresServerConfig = "ErrorFetchingPostgreSQLServerConfig" - ReasonErrorFetchingMySQLServerConfig = "ErrorFetchingMySQLServerConfig" - ReasonErrorConnectingToDatabase = "ErrorConnectingToDatabase" - ReasonMissingDBServerConfig = "MissingDBServerConfig" - ReasonExcessPermissionsCleanupFailed = "ExcessPermissionsCleanupFailed" - ReasonCreatingDatabaseUserFailed = "CreatingDatabaseUserFailed" + ReasonApplyingDatabaseIntentsFailed = "ApplyingDatabaseIntentsFailed" + ReasonAppliedDatabaseIntents = "AppliedDatabaseIntents" + ReasonErrorFetchingPostgresServerConfig = "ErrorFetchingPostgreSQLServerConfig" + ReasonErrorFetchingMySQLServerConfig = "ErrorFetchingMySQLServerConfig" + ReasonErrorConnectingToDatabase = "ErrorConnectingToDatabase" + ReasonMissingDBServerConfig = "MissingDBServerConfig" + ReasonExcessPermissionsCleanupFailed = "ExcessPermissionsCleanupFailed" + ReasonCreatingDatabaseUserFailed = "CreatingDatabaseUserFailed" + ReasonAnnotatingPodFailedWithDBAccessFailed = "AnnotatingPodFailedWithDBAccessFailed" ) type DatabaseReconciler struct { @@ -205,14 +206,17 @@ func (r *DatabaseReconciler) applyDBInstanceIntentsOnConfigurator( err := r.createDBUser(ctx, dbConfigurator, dbUsername) if err != nil { r.RecordWarningEventf(clientIntents, ReasonCreatingDatabaseUserFailed, - "Failed creating user %s", dbUsername) - return errors.Wrap(err) - } - if err := r.annotateDatabaseAndUsernameOnPod(ctx, *clientIntents, dbUsername, dbInstanceName); err != nil { + "Failed creating user %s: %s", dbUsername, err.Error()) return errors.Wrap(err) } } + if err := r.annotateDatabaseOnPod(ctx, *clientIntents, dbInstanceName); err != nil { + r.RecordWarningEventf(clientIntents, ReasonAnnotatingPodFailedWithDBAccessFailed, + "Failed annotating pod with databse: %s", err.Error()) + return errors.Wrap(err) + } + dbnameToDatabaseResources := getDBNameToDatabaseResourcesFromIntents(dbInstanceIntents) err = dbConfigurator.ApplyDatabasePermissionsForUser(ctx, dbUsername, dbnameToDatabaseResources) if err != nil { @@ -247,13 +251,19 @@ func (r *DatabaseReconciler) getClusterID(ctx context.Context) (string, error) { return clusterID, nil } -func (r *DatabaseReconciler) annotateDatabaseAndUsernameOnPod(ctx context.Context, intents otterizev1alpha3.ClientIntents, username string, dbInstance string) error { +func (r *DatabaseReconciler) annotateDatabaseOnPod(ctx context.Context, intents otterizev1alpha3.ClientIntents, dbInstance string) error { // We annotate a pod here to trigger the credentials operator flow // It will create a user-password secret and modify the databases so those credentials could connect successfully // We only annotate one pod since we just need to trigger the credentials operator once, to create the secret // All pods replicas could then load the secret data and use it as login credentials pod, err := r.serviceIdResolver.ResolveClientIntentToPod(ctx, intents) if err != nil { + if errors.Is(err, serviceidresolver.ErrPodNotFound) { + // no matching pods are deployed yet, but that's OK. + // the first pod to admit with matching database intents will trigger the intents reconcile loop + // which will lead it to this code path again. + return nil + } return errors.Wrap(err) } updatedPod := pod.DeepCopy() diff --git a/src/operator/webhooks/mysqlserverconfigs_webhook.go b/src/operator/webhooks/mysqlserverconfigs_webhook.go index a754d6400..a7aef6f6d 100644 --- a/src/operator/webhooks/mysqlserverconfigs_webhook.go +++ b/src/operator/webhooks/mysqlserverconfigs_webhook.go @@ -60,18 +60,18 @@ func (v *MySQLConfValidator) ValidateDelete(ctx context.Context, obj runtime.Obj // ValidateCreate implements webhook.Validator so a webhook will be registered for the type func (v *MySQLConfValidator) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) { allErrs := field.ErrorList{} - pgServerConf := obj.(*otterizev1alpha3.PostgreSQLServerConfig) + mysqlServerConf := obj.(*otterizev1alpha3.MySQLServerConfig) - err := validateNoDuplicateForCreate(ctx, v.Client, pgServerConf.Name) + err := validateNoDuplicateForCreate(ctx, v.Client, mysqlServerConf.Name) if err != nil { var fieldErr *field.Error if goerrors.As(err, &fieldErr) { allErrs = append(allErrs, fieldErr) - gvk := pgServerConf.GroupVersionKind() + gvk := mysqlServerConf.GroupVersionKind() return nil, k8serrors.NewInvalid( schema.GroupKind{Group: gvk.Group, Kind: gvk.Kind}, - pgServerConf.Name, allErrs) + mysqlServerConf.Name, allErrs) } return nil, errors.Wrap(err)