From ac54d9647e55842dc2978d86f65c2ac088e0a90d Mon Sep 17 00:00:00 2001 From: Sri Roopa Ramesh Babu Date: Wed, 13 Aug 2025 02:07:50 -0400 Subject: [PATCH 1/6] Reconciling when ca cert deleted for postgres pod. --- internal/controller/constants.go | 4 ++ .../controller/ols_app_postgres_assets.go | 16 ++++--- .../ols_app_postgres_reconciliator.go | 13 +++--- .../ols_app_server_reconciliator.go | 46 +++++++++++++++++++ internal/controller/olsconfig_controller.go | 1 + internal/controller/resource_watchers.go | 11 +++++ test/e2e/client.go | 21 +++++++++ 7 files changed, 99 insertions(+), 13 deletions(-) diff --git a/internal/controller/constants.go b/internal/controller/constants.go index c4c70b6e8..2c4e4e032 100644 --- a/internal/controller/constants.go +++ b/internal/controller/constants.go @@ -244,6 +244,10 @@ ssl_ca_file = '/etc/certs/cm-olspostgresca/service-ca.crt' PostgresConfigHashStateCacheKey = "olspostgresconfig-hash" // #nosec G101 PostgresSecretHashStateCacheKey = "olspostgressecret-hash" + // PostgresCAHashKey is the key of the hash value of the OLS Postgres CA certificates + PostgresCAHashKey = "hash/postgres-ca" + // PostgresCAHashStateCacheKey is the key of the hash value of the OLS Postgres CA certificates in state cache + PostgresCAHashStateCacheKey = "olspostgresca-hash" // OperatorNetworkPolicyName is the name of the network policy for the operator OperatorNetworkPolicyName = "lightspeed-operator" // OperatorMetricsPort is the port number of the operator metrics endpoint diff --git a/internal/controller/ols_app_postgres_assets.go b/internal/controller/ols_app_postgres_assets.go index ee6157722..489d36ad2 100644 --- a/internal/controller/ols_app_postgres_assets.go +++ b/internal/controller/ols_app_postgres_assets.go @@ -256,16 +256,18 @@ func (r *OLSConfigReconciler) updatePostgresDeployment(ctx context.Context, exis // Validate deployment annotations. if existingDeployment.Annotations == nil || existingDeployment.Annotations[PostgresConfigHashKey] != r.stateCache[PostgresConfigHashStateCacheKey] || - existingDeployment.Annotations[PostgresSecretHashKey] != r.stateCache[PostgresSecretHashStateCacheKey] { - updateDeploymentAnnotations(existingDeployment, map[string]string{ + existingDeployment.Annotations[PostgresSecretHashKey] != r.stateCache[PostgresSecretHashStateCacheKey] || + (r.stateCache[PostgresCAHashStateCacheKey] != "" && existingDeployment.Annotations[PostgresCAHashKey] != r.stateCache[PostgresCAHashStateCacheKey]) { + ann := map[string]string{ PostgresConfigHashKey: r.stateCache[PostgresConfigHashStateCacheKey], PostgresSecretHashKey: r.stateCache[PostgresSecretHashStateCacheKey], - }) + } + if r.stateCache[PostgresCAHashStateCacheKey] != "" { + ann[PostgresCAHashKey] = r.stateCache[PostgresCAHashStateCacheKey] + } + updateDeploymentAnnotations(existingDeployment, ann) // update the deployment template annotation triggers the rolling update - updateDeploymentTemplateAnnotations(existingDeployment, map[string]string{ - PostgresConfigHashKey: r.stateCache[PostgresConfigHashStateCacheKey], - PostgresSecretHashKey: r.stateCache[PostgresSecretHashStateCacheKey], - }) + updateDeploymentTemplateAnnotations(existingDeployment, ann) if _, err := setDeploymentContainerEnvs(existingDeployment, desiredDeployment.Spec.Template.Spec.Containers[0].Env, PostgresDeploymentName); err != nil { return err diff --git a/internal/controller/ols_app_postgres_reconciliator.go b/internal/controller/ols_app_postgres_reconciliator.go index 3706b5e80..a236ec155 100644 --- a/internal/controller/ols_app_postgres_reconciliator.go +++ b/internal/controller/ols_app_postgres_reconciliator.go @@ -70,14 +70,15 @@ func (r *OLSConfigReconciler) reconcilePostgresDeployment(ctx context.Context, c existingDeployment := &appsv1.Deployment{} err = r.Client.Get(ctx, client.ObjectKey{Name: PostgresDeploymentName, Namespace: r.Options.Namespace}, existingDeployment) if err != nil && errors.IsNotFound(err) { - updateDeploymentAnnotations(desiredDeployment, map[string]string{ + ann := map[string]string{ PostgresConfigHashKey: r.stateCache[PostgresConfigHashStateCacheKey], PostgresSecretHashKey: r.stateCache[PostgresSecretHashStateCacheKey], - }) - updateDeploymentTemplateAnnotations(desiredDeployment, map[string]string{ - PostgresConfigHashKey: r.stateCache[PostgresConfigHashStateCacheKey], - PostgresSecretHashKey: r.stateCache[PostgresSecretHashStateCacheKey], - }) + } + if r.stateCache[PostgresCAHashStateCacheKey] != "" { + ann[PostgresCAHashKey] = r.stateCache[PostgresCAHashStateCacheKey] + } + updateDeploymentAnnotations(desiredDeployment, ann) + updateDeploymentTemplateAnnotations(desiredDeployment, ann) r.logger.Info("creating a new OLS postgres deployment", "deployment", desiredDeployment.Name) err = r.Create(ctx, desiredDeployment) if err != nil { diff --git a/internal/controller/ols_app_server_reconciliator.go b/internal/controller/ols_app_server_reconciliator.go index aa5fb9178..8e1c2f04d 100644 --- a/internal/controller/ols_app_server_reconciliator.go +++ b/internal/controller/ols_app_server_reconciliator.go @@ -74,6 +74,10 @@ func (r *OLSConfigReconciler) reconcileAppServer(ctx context.Context, olsconfig Name: "reconcile Proxy CA ConfigMap", Task: r.reconcileProxyCAConfigMap, }, + { + Name: "reconcile Postgres CA ConfigMap", + Task: r.reconcilePostgresCAConfigMap, + }, } for _, task := range tasks { @@ -206,6 +210,48 @@ func (r *OLSConfigReconciler) reconcileProxyCAConfigMap(ctx context.Context, cr return nil } +func (r *OLSConfigReconciler) reconcilePostgresCAConfigMap(ctx context.Context, cr *olsv1alpha1.OLSConfig) error { + // Get the openshift-service-ca.crt configmap used by postgres + cm := &corev1.ConfigMap{} + err := r.Client.Get(ctx, client.ObjectKey{Name: OLSCAConfigMap, Namespace: r.Options.Namespace}, cm) + if err != nil { + // If the service-ca configmap is not present yet, skip without failing reconciliation + if errors.IsNotFound(err) { + r.logger.Info("Postgres CA configmap not found yet, skipping", "configmap", OLSCAConfigMap) + return nil + } + return fmt.Errorf("failed to get postgres CA configmap %s: %w", OLSCAConfigMap, err) + } + + // Annotate the configmap for watcher to trigger reconciliation when it changes + annotateConfigMapWatcher(cm) + err = r.Update(ctx, cm) + if err != nil { + return fmt.Errorf("failed to update postgres CA configmap %s: %w", OLSCAConfigMap, err) + } + + // Calculate hash of CA certificate data to detect changes + certBytes := []byte{} + for key, value := range cm.Data { + certBytes = append(certBytes, []byte(key)...) + certBytes = append(certBytes, []byte(value)...) + } + + foundCmHash, err := hashBytes(certBytes) + if err != nil { + return fmt.Errorf("failed to generate postgres CA certs hash: %w", err) + } + + if foundCmHash == r.stateCache[PostgresCAHashStateCacheKey] { + r.logger.Info("Postgres CA reconciliation skipped", "hash", foundCmHash) + return nil + } + + r.stateCache[PostgresCAHashStateCacheKey] = foundCmHash + r.logger.Info("postgres CA configmap reconciled", "configmap", cm.Name, "hash", foundCmHash) + return nil +} + func (r *OLSConfigReconciler) reconcileServiceAccount(ctx context.Context, cr *olsv1alpha1.OLSConfig) error { sa, err := r.generateServiceAccount(cr) if err != nil { diff --git a/internal/controller/olsconfig_controller.go b/internal/controller/olsconfig_controller.go index bb074ce2b..c1c0be6b3 100644 --- a/internal/controller/olsconfig_controller.go +++ b/internal/controller/olsconfig_controller.go @@ -249,6 +249,7 @@ func (r *OLSConfigReconciler) SetupWithManager(mgr ctrl.Manager) error { Watches(&corev1.Secret{}, handler.EnqueueRequestsFromMapFunc(secretWatcherFilter)). Watches(&corev1.Secret{}, handler.EnqueueRequestsFromMapFunc(telemetryPullSecretWatcherFilter)). Watches(&corev1.ConfigMap{}, handler.EnqueueRequestsFromMapFunc(configMapWatcherFilter)). + Watches(&corev1.ConfigMap{}, handler.EnqueueRequestsFromMapFunc(postgresCAConfigMapWatcherFilter)). Owns(&consolev1.ConsolePlugin{}). Owns(&monv1.ServiceMonitor{}). Owns(&monv1.PrometheusRule{}). diff --git a/internal/controller/resource_watchers.go b/internal/controller/resource_watchers.go index c54747c12..6020b7bec 100644 --- a/internal/controller/resource_watchers.go +++ b/internal/controller/resource_watchers.go @@ -69,3 +69,14 @@ func annotateConfigMapWatcher(cm *corev1.ConfigMap) { annotations[WatcherAnnotationKey] = OLSConfigName cm.SetAnnotations(annotations) } + +func postgresCAConfigMapWatcherFilter(ctx context.Context, obj client.Object) []reconcile.Request { + if obj.GetName() != OLSCAConfigMap { + return nil + } + return []reconcile.Request{ + {NamespacedName: types.NamespacedName{ + Name: OLSConfigName, + }}, + } +} diff --git a/test/e2e/client.go b/test/e2e/client.go index c5884b198..bd125fd53 100644 --- a/test/e2e/client.go +++ b/test/e2e/client.go @@ -566,3 +566,24 @@ func (c *Client) CreatePersistentVolume(name, storageClassName string, volumeSiz } }, nil } + +func (c *Client) ExecInPod(podName, namespace, containerName string, command []string) (string, error) { + ctx, cancel := context.WithTimeout(c.ctx, c.timeout) + defer cancel() + + // Build kubectl exec command + args := []string{"exec", "-n", namespace, podName} + if containerName != "" { + args = append(args, "-c", containerName) + } + args = append(args, "--") + args = append(args, command...) + + cmd := exec.CommandContext(ctx, "kubectl", args...) + if c.kubeconfigPath != "" { + cmd.Env = append(os.Environ(), fmt.Sprintf("KUBECONFIG=%s", c.kubeconfigPath)) + } + + output, err := cmd.CombinedOutput() + return string(output), err +} From 992071359011ff32d10ad3d2c1fad1aa58588695 Mon Sep 17 00:00:00 2001 From: Sri Roopa Ramesh Babu Date: Tue, 19 Aug 2025 11:14:35 -0400 Subject: [PATCH 2/6] Fixing errors. --- test/e2e/client.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/e2e/client.go b/test/e2e/client.go index 879821b63..d9e889237 100644 --- a/test/e2e/client.go +++ b/test/e2e/client.go @@ -585,7 +585,6 @@ func (c *Client) CreatePersistentVolume(name, storageClassName string, volumeSiz }, nil } - func (c *Client) CreatePVC(name, storageClassName string, volumeSize resource.Quantity) (func(), error) { pv := &corev1.PersistentVolumeClaim{ ObjectMeta: metav1.ObjectMeta{ @@ -620,8 +619,8 @@ func (c *Client) CreatePVC(name, storageClassName string, volumeSize resource.Qu logf.Log.Error(err, "Error deleting PersistentVolumeClaim") } }, nil +} - <<<<<<< postgres-image-update func (c *Client) ExecInPod(podName, namespace, containerName string, command []string) (string, error) { ctx, cancel := context.WithTimeout(c.ctx, c.timeout) defer cancel() From 9206ff34f4979a000b93f55a9fee8c6aec899d76 Mon Sep 17 00:00:00 2001 From: Sri Roopa Ramesh Babu Date: Mon, 1 Sep 2025 19:52:45 -0400 Subject: [PATCH 3/6] Postgres pod reconcilation during ca cert alteration. --- .../ols_app_server_reconciliator.go | 11 --------- internal/controller/olsconfig_controller.go | 23 +++++++++++++++++++ 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/internal/controller/ols_app_server_reconciliator.go b/internal/controller/ols_app_server_reconciliator.go index 8e1c2f04d..6b042d8a2 100644 --- a/internal/controller/ols_app_server_reconciliator.go +++ b/internal/controller/ols_app_server_reconciliator.go @@ -74,10 +74,6 @@ func (r *OLSConfigReconciler) reconcileAppServer(ctx context.Context, olsconfig Name: "reconcile Proxy CA ConfigMap", Task: r.reconcileProxyCAConfigMap, }, - { - Name: "reconcile Postgres CA ConfigMap", - Task: r.reconcilePostgresCAConfigMap, - }, } for _, task := range tasks { @@ -223,13 +219,6 @@ func (r *OLSConfigReconciler) reconcilePostgresCAConfigMap(ctx context.Context, return fmt.Errorf("failed to get postgres CA configmap %s: %w", OLSCAConfigMap, err) } - // Annotate the configmap for watcher to trigger reconciliation when it changes - annotateConfigMapWatcher(cm) - err = r.Update(ctx, cm) - if err != nil { - return fmt.Errorf("failed to update postgres CA configmap %s: %w", OLSCAConfigMap, err) - } - // Calculate hash of CA certificate data to detect changes certBytes := []byte{} for key, value := range cm.Data { diff --git a/internal/controller/olsconfig_controller.go b/internal/controller/olsconfig_controller.go index 4529103c1..1f12eeeca 100644 --- a/internal/controller/olsconfig_controller.go +++ b/internal/controller/olsconfig_controller.go @@ -162,6 +162,17 @@ func (r *OLSConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( // Update status condition for Console Plugin r.updateStatusCondition(ctx, olsconfig, typeConsolePluginReady, true, "All components are successfully deployed", nil) + // Reconcile postgres CA certificate first to ensure hash is updated before postgres deployment reconciliation + // Only do this if we have a CA certificate to reconcile + if r.shouldReconcilePostgresCA(ctx) { + err = r.reconcilePostgresCAConfigMap(ctx, olsconfig) + if err != nil { + r.logger.Error(err, "Failed to reconcile postgres CA configmap") + r.updateStatusCondition(ctx, olsconfig, typeCRReconciled, false, "Failed", err) + return ctrl.Result{RequeueAfter: 1 * time.Second}, err + } + } + err = r.reconcilePostgresServer(ctx, olsconfig) if err != nil { r.logger.Error(err, "Failed to reconcile ols postgres") @@ -200,6 +211,18 @@ func (r *OLSConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( return ctrl.Result{RequeueAfter: r.Options.ReconcileInterval}, nil } +// shouldReconcilePostgresCA checks if we should reconcile the postgres CA certificate +func (r *OLSConfigReconciler) shouldReconcilePostgresCA(ctx context.Context) bool { + // Check if the openshift-service-ca.crt configmap exists + cm := &corev1.ConfigMap{} + err := r.Client.Get(ctx, client.ObjectKey{Name: OLSCAConfigMap, Namespace: r.Options.Namespace}, cm) + if err != nil { + // If the configmap doesn't exist, we don't need to reconcile + return false + } + return true +} + // updateStatusCondition updates the status condition of the OLSConfig Custom Resource instance. // TODO: Should we support Unknown status and ObservedGeneration? // TODO: conditionType must be metav1.Condition? From 37aac9c2a797c04f6f6c0293583f3cb2b9466ccd Mon Sep 17 00:00:00 2001 From: Sri Roopa Ramesh Babu Date: Tue, 2 Sep 2025 08:34:55 -0400 Subject: [PATCH 4/6] Reconciling openshift-service-ca.crt with postgres. --- cmd/main.go | 6 ++ .../controller/ols_app_postgres_assets.go | 3 - .../ols_app_server_reconciliator.go | 62 +++++++++---- internal/controller/olsconfig_controller.go | 18 ++-- internal/controller/resource_watchers.go | 92 ++++++++++++------- 5 files changed, 120 insertions(+), 61 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index 9bb1a977f..0f09b4052 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -244,6 +244,12 @@ func main() { controller.TelemetryPullSecretNamespace: {}, }, }, + &corev1.ConfigMap{}: { + Namespaces: map[string]cache.Config{ + namespace: {}, + "openshift-config": {}, + }, + }, }, }, }) diff --git a/internal/controller/ols_app_postgres_assets.go b/internal/controller/ols_app_postgres_assets.go index 489d36ad2..a902af1a0 100644 --- a/internal/controller/ols_app_postgres_assets.go +++ b/internal/controller/ols_app_postgres_assets.go @@ -294,9 +294,6 @@ func (r *OLSConfigReconciler) generatePostgresService(cr *olsv1alpha1.OLSConfig) Name: PostgresServiceName, Namespace: r.Options.Namespace, Labels: generatePostgresSelectorLabels(), - Annotations: map[string]string{ - ServingCertSecretAnnotationKey: PostgresCertsSecretName, - }, }, Spec: corev1.ServiceSpec{ Ports: []corev1.ServicePort{ diff --git a/internal/controller/ols_app_server_reconciliator.go b/internal/controller/ols_app_server_reconciliator.go index 6b042d8a2..c8f32b813 100644 --- a/internal/controller/ols_app_server_reconciliator.go +++ b/internal/controller/ols_app_server_reconciliator.go @@ -206,38 +206,64 @@ func (r *OLSConfigReconciler) reconcileProxyCAConfigMap(ctx context.Context, cr return nil } -func (r *OLSConfigReconciler) reconcilePostgresCAConfigMap(ctx context.Context, cr *olsv1alpha1.OLSConfig) error { - // Get the openshift-service-ca.crt configmap used by postgres - cm := &corev1.ConfigMap{} - err := r.Client.Get(ctx, client.ObjectKey{Name: OLSCAConfigMap, Namespace: r.Options.Namespace}, cm) +func (r *OLSConfigReconciler) reconcilePostgresCASecret(ctx context.Context, cr *olsv1alpha1.OLSConfig) error { + // Read OpenShift service CA configmap + openshiftCA := &corev1.ConfigMap{} + err := r.Client.Get(ctx, client.ObjectKey{Name: "openshift-service-ca.crt", Namespace: "openshift-config"}, openshiftCA) + if err != nil { + r.logger.Info("OpenShift service CA configmap not found, skipping", "configmap", "openshift-service-ca.crt") + // Continue with just the secret + } + + // Read PostgreSQL CA secret + secret := &corev1.Secret{} + err = r.Client.Get(ctx, client.ObjectKey{Name: PostgresCertsSecretName, Namespace: r.Options.Namespace}, secret) if err != nil { - // If the service-ca configmap is not present yet, skip without failing reconciliation + // If the CA certificates secret is not present yet, set a special "deleted" hash to trigger deployment update if errors.IsNotFound(err) { - r.logger.Info("Postgres CA configmap not found yet, skipping", "configmap", OLSCAConfigMap) + deletedHash := "DELETED-" + fmt.Sprintf("%d", time.Now().Unix()) + r.stateCache[PostgresCAHashStateCacheKey] = deletedHash return nil } - return fmt.Errorf("failed to get postgres CA configmap %s: %w", OLSCAConfigMap, err) + return fmt.Errorf("failed to get postgres CA certificates secret %s: %w", PostgresCertsSecretName, err) } - // Calculate hash of CA certificate data to detect changes - certBytes := []byte{} - for key, value := range cm.Data { - certBytes = append(certBytes, []byte(key)...) - certBytes = append(certBytes, []byte(value)...) + // Calculate hash combining both OpenShift service CA and PostgreSQL CA data + hashData := "" + + // Add OpenShift service CA data if available + if openshiftCA.Name != "" { + for key, value := range openshiftCA.Data { + hashData += fmt.Sprintf("openshift-%s:%s:", key, value) + } + hashData += fmt.Sprintf("openshift-version:%s:", openshiftCA.GetResourceVersion()) } - foundCmHash, err := hashBytes(certBytes) + // Add PostgreSQL CA secret data + caCertData, exists := secret.Data["service-ca.crt"] + if exists { + hashData += fmt.Sprintf("postgres-service-ca:%s:", string(caCertData)) + } + hashData += fmt.Sprintf("postgres-version:%s", secret.GetResourceVersion()) + + computedHash, err := hashBytes([]byte(hashData)) if err != nil { - return fmt.Errorf("failed to generate postgres CA certs hash: %w", err) + return fmt.Errorf("failed to generate postgres CA cert hash: %w", err) } - if foundCmHash == r.stateCache[PostgresCAHashStateCacheKey] { - r.logger.Info("Postgres CA reconciliation skipped", "hash", foundCmHash) + // Store the computed hash in state cache for comparison + oldHash := r.stateCache[PostgresCAHashStateCacheKey] + r.stateCache[PostgresCAHashStateCacheKey] = computedHash + + // Debug logging to check for idempotency issues + r.logger.Info("CA hash debug", "existing", oldHash, "computed", computedHash, "openshift-version", openshiftCA.GetResourceVersion(), "postgres-version", secret.GetResourceVersion()) + + if oldHash == computedHash { + r.logger.Info("Postgres CA reconciliation skipped - hash unchanged", "hash", computedHash) return nil } - r.stateCache[PostgresCAHashStateCacheKey] = foundCmHash - r.logger.Info("postgres CA configmap reconciled", "configmap", cm.Name, "hash", foundCmHash) + r.logger.Info("Postgres CA hash changed, will trigger deployment update", "oldHash", oldHash, "newHash", computedHash) return nil } diff --git a/internal/controller/olsconfig_controller.go b/internal/controller/olsconfig_controller.go index 1f12eeeca..e6e019273 100644 --- a/internal/controller/olsconfig_controller.go +++ b/internal/controller/olsconfig_controller.go @@ -151,7 +151,7 @@ func (r *OLSConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( r.logger.Error(err, "Failed to get olsconfig") return ctrl.Result{RequeueAfter: 1 * time.Second}, err } - r.logger.Info("reconciliation starts", "olsconfig generation", olsconfig.Generation) + r.logger.Info("reconciliation starts", "olsconfig generation", olsconfig.Generation, "triggered by", req.NamespacedName) err = r.reconcileConsoleUI(ctx, olsconfig) if err != nil { @@ -165,12 +165,16 @@ func (r *OLSConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( // Reconcile postgres CA certificate first to ensure hash is updated before postgres deployment reconciliation // Only do this if we have a CA certificate to reconcile if r.shouldReconcilePostgresCA(ctx) { - err = r.reconcilePostgresCAConfigMap(ctx, olsconfig) + r.logger.Info("Starting postgres CA certificates secret reconciliation") + err = r.reconcilePostgresCASecret(ctx, olsconfig) if err != nil { - r.logger.Error(err, "Failed to reconcile postgres CA configmap") + r.logger.Error(err, "Failed to reconcile postgres CA certificates secret") r.updateStatusCondition(ctx, olsconfig, typeCRReconciled, false, "Failed", err) return ctrl.Result{RequeueAfter: 1 * time.Second}, err } + r.logger.Info("Completed postgres CA certificates secret reconciliation") + } else { + r.logger.Info("Skipping postgres CA certificates secret reconciliation") } err = r.reconcilePostgresServer(ctx, olsconfig) @@ -213,11 +217,9 @@ func (r *OLSConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( // shouldReconcilePostgresCA checks if we should reconcile the postgres CA certificate func (r *OLSConfigReconciler) shouldReconcilePostgresCA(ctx context.Context) bool { - // Check if the openshift-service-ca.crt configmap exists - cm := &corev1.ConfigMap{} - err := r.Client.Get(ctx, client.ObjectKey{Name: OLSCAConfigMap, Namespace: r.Options.Namespace}, cm) + secret := &corev1.Secret{} + err := r.Client.Get(ctx, client.ObjectKey{Name: PostgresCertsSecretName, Namespace: r.Options.Namespace}, secret) if err != nil { - // If the configmap doesn't exist, we don't need to reconcile return false } return true @@ -271,9 +273,7 @@ func (r *OLSConfigReconciler) SetupWithManager(mgr ctrl.Manager) error { Owns(&corev1.Secret{}). Owns(&corev1.PersistentVolumeClaim{}). Watches(&corev1.Secret{}, handler.EnqueueRequestsFromMapFunc(secretWatcherFilter)). - Watches(&corev1.Secret{}, handler.EnqueueRequestsFromMapFunc(telemetryPullSecretWatcherFilter)). Watches(&corev1.ConfigMap{}, handler.EnqueueRequestsFromMapFunc(configMapWatcherFilter)). - Watches(&corev1.ConfigMap{}, handler.EnqueueRequestsFromMapFunc(postgresCAConfigMapWatcherFilter)). Owns(&consolev1.ConsolePlugin{}). Owns(&monv1.ServiceMonitor{}). Owns(&monv1.PrometheusRule{}). diff --git a/internal/controller/resource_watchers.go b/internal/controller/resource_watchers.go index 6020b7bec..d3957680f 100644 --- a/internal/controller/resource_watchers.go +++ b/internal/controller/resource_watchers.go @@ -10,19 +10,56 @@ import ( ) func secretWatcherFilter(ctx context.Context, obj client.Object) []reconcile.Request { - annotations := obj.GetAnnotations() - if annotations == nil { - return nil + // Try each specific watcher in order + if requests := postgresCASecretWatcher(ctx, obj); len(requests) > 0 { + return requests } - crName, exist := annotations[WatcherAnnotationKey] - if !exist { - return nil + + if requests := telemetryPullSecretWatcher(ctx, obj); len(requests) > 0 { + return requests } - return []reconcile.Request{ - {NamespacedName: types.NamespacedName{ - Name: crName, - }}, + + if requests := annotatedSecretWatcher(ctx, obj); len(requests) > 0 { + return requests } + + return nil +} + +func postgresCASecretWatcher(ctx context.Context, obj client.Object) []reconcile.Request { + if obj.GetName() == PostgresCertsSecretName && obj.GetNamespace() == "openshift-lightspeed" { + return []reconcile.Request{ + {NamespacedName: types.NamespacedName{ + Name: OLSConfigName, + }}, + } + } + return nil +} + +func telemetryPullSecretWatcher(ctx context.Context, obj client.Object) []reconcile.Request { + if obj.GetNamespace() == TelemetryPullSecretNamespace && obj.GetName() == TelemetryPullSecretName { + return []reconcile.Request{ + {NamespacedName: types.NamespacedName{ + Name: OLSConfigName, + }}, + } + } + return nil +} + +func annotatedSecretWatcher(ctx context.Context, obj client.Object) []reconcile.Request { + annotations := obj.GetAnnotations() + if annotations != nil { + if crName, exist := annotations[WatcherAnnotationKey]; exist { + return []reconcile.Request{ + {NamespacedName: types.NamespacedName{ + Name: crName, + }}, + } + } + } + return nil } func annotateSecretWatcher(secret *corev1.Secret) { @@ -34,31 +71,24 @@ func annotateSecretWatcher(secret *corev1.Secret) { secret.SetAnnotations(annotations) } -func telemetryPullSecretWatcherFilter(ctx context.Context, obj client.Object) []reconcile.Request { - if obj.GetNamespace() != TelemetryPullSecretNamespace || obj.GetName() != TelemetryPullSecretName { - return nil - } - return []reconcile.Request{ - {NamespacedName: types.NamespacedName{ - Name: OLSConfigName, - }}, +func configMapWatcherFilter(ctx context.Context, obj client.Object) []reconcile.Request { + // Check for OpenShift service CA configmap first + if obj.GetName() == "openshift-service-ca.crt" && obj.GetNamespace() == "openshift-config" { + return []reconcile.Request{{NamespacedName: types.NamespacedName{Name: OLSConfigName}}} } -} -func configMapWatcherFilter(ctx context.Context, obj client.Object) []reconcile.Request { + // Check for annotated configmaps annotations := obj.GetAnnotations() - if annotations == nil { - return nil - } - crName, exist := annotations[WatcherAnnotationKey] - if !exist { - return nil - } - return []reconcile.Request{ - {NamespacedName: types.NamespacedName{ - Name: crName, - }}, + if annotations != nil { + if crName, exist := annotations[WatcherAnnotationKey]; exist { + return []reconcile.Request{ + {NamespacedName: types.NamespacedName{ + Name: crName, + }}, + } + } } + return nil } func annotateConfigMapWatcher(cm *corev1.ConfigMap) { From ece11b5ce963b89aadabd3cbc97a8c87acb3867c Mon Sep 17 00:00:00 2001 From: Sri Roopa Ramesh Babu Date: Tue, 2 Sep 2025 09:45:03 -0400 Subject: [PATCH 5/6] Fixiing linter issues and unit tests. --- cmd/main.go | 2 +- internal/controller/ols_app_postgres_assets.go | 3 +++ internal/controller/olsconfig_controller.go | 5 +---- internal/controller/resource_watchers.go | 11 ----------- 4 files changed, 5 insertions(+), 16 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index 0f09b4052..e0b1d8935 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -246,7 +246,7 @@ func main() { }, &corev1.ConfigMap{}: { Namespaces: map[string]cache.Config{ - namespace: {}, + namespace: {}, "openshift-config": {}, }, }, diff --git a/internal/controller/ols_app_postgres_assets.go b/internal/controller/ols_app_postgres_assets.go index a902af1a0..786b082b1 100644 --- a/internal/controller/ols_app_postgres_assets.go +++ b/internal/controller/ols_app_postgres_assets.go @@ -294,6 +294,9 @@ func (r *OLSConfigReconciler) generatePostgresService(cr *olsv1alpha1.OLSConfig) Name: PostgresServiceName, Namespace: r.Options.Namespace, Labels: generatePostgresSelectorLabels(), + Annotations: map[string]string{ + "service.beta.openshift.io/serving-cert-secret-name": PostgresCertsSecretName, + }, }, Spec: corev1.ServiceSpec{ Ports: []corev1.ServicePort{ diff --git a/internal/controller/olsconfig_controller.go b/internal/controller/olsconfig_controller.go index e6e019273..19b9b098a 100644 --- a/internal/controller/olsconfig_controller.go +++ b/internal/controller/olsconfig_controller.go @@ -219,10 +219,7 @@ func (r *OLSConfigReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( func (r *OLSConfigReconciler) shouldReconcilePostgresCA(ctx context.Context) bool { secret := &corev1.Secret{} err := r.Client.Get(ctx, client.ObjectKey{Name: PostgresCertsSecretName, Namespace: r.Options.Namespace}, secret) - if err != nil { - return false - } - return true + return err == nil } // updateStatusCondition updates the status condition of the OLSConfig Custom Resource instance. diff --git a/internal/controller/resource_watchers.go b/internal/controller/resource_watchers.go index d3957680f..8c720231b 100644 --- a/internal/controller/resource_watchers.go +++ b/internal/controller/resource_watchers.go @@ -99,14 +99,3 @@ func annotateConfigMapWatcher(cm *corev1.ConfigMap) { annotations[WatcherAnnotationKey] = OLSConfigName cm.SetAnnotations(annotations) } - -func postgresCAConfigMapWatcherFilter(ctx context.Context, obj client.Object) []reconcile.Request { - if obj.GetName() != OLSCAConfigMap { - return nil - } - return []reconcile.Request{ - {NamespacedName: types.NamespacedName{ - Name: OLSConfigName, - }}, - } -} From 6e5fbdd8348f8c2422b22e7ddbefd68615c6f286 Mon Sep 17 00:00:00 2001 From: Sri Roopa Ramesh Babu Date: Wed, 3 Sep 2025 02:36:07 -0400 Subject: [PATCH 6/6] Ensuring health of postgres pod. --- internal/controller/ols_app_postgres_assets.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/internal/controller/ols_app_postgres_assets.go b/internal/controller/ols_app_postgres_assets.go index 786b082b1..a2a78272f 100644 --- a/internal/controller/ols_app_postgres_assets.go +++ b/internal/controller/ols_app_postgres_assets.go @@ -201,6 +201,15 @@ func (r *OLSConfigReconciler) generatePostgresDeployment(cr *olsv1alpha1.OLSConf }, VolumeMounts: volumeMounts, Resources: *databaseResources, + ReadinessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"pg_isready", "-U", PostgresDefaultUser, "-d", PostgresDefaultDbName}, + }, + }, + InitialDelaySeconds: 10, + PeriodSeconds: 5, + }, Env: []corev1.EnvVar{ { Name: "POSTGRESQL_USER",