diff --git a/pkg/controllers/monitoring/monitoring-stack/alertmanager.go b/pkg/controllers/monitoring/monitoring-stack/alertmanager.go index 93e35750d..3cc522567 100644 --- a/pkg/controllers/monitoring/monitoring-stack/alertmanager.go +++ b/pkg/controllers/monitoring/monitoring-stack/alertmanager.go @@ -157,7 +157,7 @@ func newAlertmanagerPDB(ms *stack.MonitoringStack, instanceSelectorKey string, i } } -func newAlertManagerClusterRole(ms *stack.MonitoringStack, rbacResourceName string, rbacVerbs []string) *rbacv1.ClusterRole { +func newAlertManagerClusterRole(rbacResourceName string, rbacVerbs []string) *rbacv1.ClusterRole { return &rbacv1.ClusterRole{ TypeMeta: metav1.TypeMeta{ APIVersion: rbacv1.SchemeGroupVersion.String(), diff --git a/pkg/controllers/monitoring/monitoring-stack/components.go b/pkg/controllers/monitoring/monitoring-stack/components.go index d32f3e9cc..38c2b8e6b 100644 --- a/pkg/controllers/monitoring/monitoring-stack/components.go +++ b/pkg/controllers/monitoring/monitoring-stack/components.go @@ -25,6 +25,23 @@ const ( prometheusSecretsMountPoint = "/etc/prometheus/secrets" ) +var ( + rbacVerbs = []string{"get", "list", "watch"} +) + +func stackComponentCleanup(ms *stack.MonitoringStack) []reconciler.Reconciler { + prometheusName := ms.Name + "-prometheus" + alertmanagerName := ms.Name + "-alertmanager" + return []reconciler.Reconciler{ + reconciler.NewDeleter(newPrometheusClusterRole(prometheusName, rbacVerbs)), + reconciler.NewDeleter(newClusterRoleBinding(ms, prometheusName)), + reconciler.NewDeleter(newRoleBindingForClusterRole(ms, prometheusName)), + reconciler.NewDeleter(newAlertManagerClusterRole(alertmanagerName, rbacVerbs)), + reconciler.NewDeleter(newClusterRoleBinding(ms, alertmanagerName)), + reconciler.NewDeleter(newRoleBindingForClusterRole(ms, alertmanagerName)), + } +} + func stackComponentReconcilers( ms *stack.MonitoringStack, instanceSelectorKey string, @@ -35,7 +52,6 @@ func stackComponentReconcilers( ) []reconciler.Reconciler { prometheusName := ms.Name + "-prometheus" alertmanagerName := ms.Name + "-alertmanager" - rbacVerbs := []string{"get", "list", "watch"} additionalScrapeConfigsSecretName := ms.Name + "-prometheus-additional-scrape-configs" hasNsSelector := ms.Spec.NamespaceSelector != nil deployAlertmanager := !ms.Spec.AlertmanagerConfig.Disabled @@ -43,7 +59,7 @@ func stackComponentReconcilers( return []reconciler.Reconciler{ // Prometheus Deployment reconciler.NewUpdater(newServiceAccount(prometheusName, ms.Namespace), ms), - reconciler.NewUpdater(newPrometheusClusterRole(ms, prometheusName, rbacVerbs), ms), + reconciler.NewUpdater(newPrometheusClusterRole(prometheusName, rbacVerbs), ms), reconciler.NewUpdater(newAdditionalScrapeConfigsSecret(ms, additionalScrapeConfigsSecretName), ms), reconciler.NewUpdater(newPrometheus(ms, prometheusName, additionalScrapeConfigsSecretName, @@ -60,7 +76,7 @@ func stackComponentReconcilers( reconciler.NewOptionalUpdater(newClusterRoleBinding(ms, prometheusName), ms, hasNsSelector), reconciler.NewOptionalUpdater(newRoleBindingForClusterRole(ms, prometheusName), ms, !hasNsSelector), - reconciler.NewOptionalUpdater(newAlertManagerClusterRole(ms, alertmanagerName, rbacVerbs), ms, deployAlertmanager), + reconciler.NewOptionalUpdater(newAlertManagerClusterRole(alertmanagerName, rbacVerbs), ms, deployAlertmanager), // create clusterrolebinding if alertmanager is enabled and namespace selector is also present in MonitoringStack reconciler.NewOptionalUpdater(newClusterRoleBinding(ms, alertmanagerName), ms, deployAlertmanager && hasNsSelector), @@ -72,7 +88,7 @@ func stackComponentReconcilers( } } -func newPrometheusClusterRole(ms *stack.MonitoringStack, rbacResourceName string, rbacVerbs []string) *rbacv1.ClusterRole { +func newPrometheusClusterRole(rbacResourceName string, rbacVerbs []string) *rbacv1.ClusterRole { return &rbacv1.ClusterRole{ TypeMeta: metav1.TypeMeta{ APIVersion: rbacv1.SchemeGroupVersion.String(), diff --git a/pkg/controllers/monitoring/monitoring-stack/controller.go b/pkg/controllers/monitoring/monitoring-stack/controller.go index 52068406a..4007c36d0 100644 --- a/pkg/controllers/monitoring/monitoring-stack/controller.go +++ b/pkg/controllers/monitoring/monitoring-stack/controller.go @@ -19,6 +19,7 @@ package monitoringstack import ( "context" "fmt" + "slices" "strings" "time" @@ -70,6 +71,8 @@ type Options struct { Thanos ThanosConfiguration } +const finalizerName = "monitoring.observability.openshift.io/finalizer" + // RBAC for managing monitoring stacks //+kubebuilder:rbac:groups=monitoring.rhobs,resources=monitoringstacks,verbs=list;watch;create;update //+kubebuilder:rbac:groups=monitoring.rhobs,resources=monitoringstacks/status,verbs=get;update @@ -144,11 +147,40 @@ func (rm resourceManager) Reconcile(ctx context.Context, req ctrl.Request) (ctrl return ctrl.Result{}, nil } + // Check if the plugin is being deleted if !ms.ObjectMeta.DeletionTimestamp.IsZero() { - logger.V(6).Info("skipping reconcile since object is already schedule for deletion") + logger.V(6).Info("removing cluster scoped resources") + + reconcilers := stackComponentCleanup(ms) + for _, reconciler := range reconcilers { + err := reconciler.Reconcile(ctx, rm.k8sClient, rm.scheme) + if err != nil { + logger.Error(err, "failed to cleanup monitoring stack") + } + } + + // Remove finalizer if present + if slices.Contains(ms.ObjectMeta.Finalizers, finalizerName) { + ms.ObjectMeta.Finalizers = slices.DeleteFunc(ms.ObjectMeta.Finalizers, func(currentFinalizerName string) bool { + return currentFinalizerName == finalizerName + }) + if err := rm.k8sClient.Update(ctx, ms); err != nil { + return ctrl.Result{}, err + } + } + + logger.V(6).Info("skipping reconcile since object is already scheduled for deletion") return ctrl.Result{}, nil } + // Add finalizer if not present + if !slices.Contains(ms.ObjectMeta.Finalizers, finalizerName) { + ms.ObjectMeta.Finalizers = append(ms.ObjectMeta.Finalizers, finalizerName) + if err := rm.k8sClient.Update(ctx, ms); err != nil { + return ctrl.Result{}, err + } + } + reconcilers := stackComponentReconcilers(ms, rm.instanceSelectorKey, rm.instanceSelectorValue,