diff --git a/bundle/manifests/monitoring.rhobs_monitoringstacks.yaml b/bundle/manifests/monitoring.rhobs_monitoringstacks.yaml index 3eb499399..67d956d8c 100644 --- a/bundle/manifests/monitoring.rhobs_monitoringstacks.yaml +++ b/bundle/manifests/monitoring.rhobs_monitoringstacks.yaml @@ -50,6 +50,21 @@ spec: default: false description: Disables the deployment of Alertmanager. type: boolean + matcherStrategy: + default: None + description: |- + Define how AlertmanagerConfig objects process incoming alerts. + With OnNamespace, routes only match alerts with a namespace label + equal to the namespace of the AlertmanagerConfig. + With OnNamespaceExceptForAlertmanagerNamespace, routes behave like + OnNamespace but AlertmanagerConfig resources in the Alertmanager's + own namespace match all alerts. + With None, routes match all incoming alerts regardless of namespace. + enum: + - OnNamespace + - OnNamespaceExceptForAlertmanagerNamespace + - None + type: string replicas: default: 2 description: Number of replicas/pods to deploy for Alertmanager. diff --git a/bundle/manifests/observability-operator.clusterserviceversion.yaml b/bundle/manifests/observability-operator.clusterserviceversion.yaml index cd6831d02..a843a1f31 100644 --- a/bundle/manifests/observability-operator.clusterserviceversion.yaml +++ b/bundle/manifests/observability-operator.clusterserviceversion.yaml @@ -43,7 +43,7 @@ metadata: certified: "false" console.openshift.io/operator-monitoring-default: "true" containerImage: observability-operator:1.3.0 - createdAt: "2026-05-18T17:17:51Z" + createdAt: "2026-05-19T06:53:02Z" description: A Go based Kubernetes operator to setup and manage highly available Monitoring Stack using Prometheus, Alertmanager and Thanos Querier. operatorframework.io/cluster-monitoring: "true" diff --git a/deploy/crds/common/monitoring.rhobs_monitoringstacks.yaml b/deploy/crds/common/monitoring.rhobs_monitoringstacks.yaml index e4fd8f377..376c6b876 100644 --- a/deploy/crds/common/monitoring.rhobs_monitoringstacks.yaml +++ b/deploy/crds/common/monitoring.rhobs_monitoringstacks.yaml @@ -50,6 +50,21 @@ spec: default: false description: Disables the deployment of Alertmanager. type: boolean + matcherStrategy: + default: None + description: |- + Define how AlertmanagerConfig objects process incoming alerts. + With OnNamespace, routes only match alerts with a namespace label + equal to the namespace of the AlertmanagerConfig. + With OnNamespaceExceptForAlertmanagerNamespace, routes behave like + OnNamespace but AlertmanagerConfig resources in the Alertmanager's + own namespace match all alerts. + With None, routes match all incoming alerts regardless of namespace. + enum: + - OnNamespace + - OnNamespaceExceptForAlertmanagerNamespace + - None + type: string replicas: default: 2 description: Number of replicas/pods to deploy for Alertmanager. diff --git a/docs/api.md b/docs/api.md index 550f99792..1dbd2ce6b 100644 --- a/docs/api.md +++ b/docs/api.md @@ -230,6 +230,22 @@ Define Alertmanager config Default: false
false + + matcherStrategy + enum + + Define how AlertmanagerConfig objects process incoming alerts. +With OnNamespace, routes only match alerts with a namespace label +equal to the namespace of the AlertmanagerConfig. +With OnNamespaceExceptForAlertmanagerNamespace, routes behave like +OnNamespace but AlertmanagerConfig resources in the Alertmanager's +own namespace match all alerts. +With None, routes match all incoming alerts regardless of namespace.
+
+ Enum: OnNamespace, OnNamespaceExceptForAlertmanagerNamespace, None
+ Default: None
+ + false replicas integer diff --git a/pkg/apis/monitoring/v1alpha1/types.go b/pkg/apis/monitoring/v1alpha1/types.go index 02c64de88..9918ea809 100644 --- a/pkg/apis/monitoring/v1alpha1/types.go +++ b/pkg/apis/monitoring/v1alpha1/types.go @@ -55,6 +55,9 @@ const ( // +kubebuilder:validation:Enum=CreateClusterRoleBindings;NoClusterRoleBindings type ClusterRoleBindingPolicy string +// +kubebuilder:validation:Enum=OnNamespace;OnNamespaceExceptForAlertmanagerNamespace;None +type AlertmanagerConfigMatcherStrategyType string + const ( // CreateClusterRoleBindings instructs the MonitoringStack to create the // default ClusterRoleBindings if a NamespaceSelector is present. Note that @@ -69,6 +72,22 @@ const ( NoClusterRoleBindings ClusterRoleBindingPolicy = "NoClusterRoleBindings" ) +const ( + // OnNamespaceMatcherStrategy configures AlertmanagerConfig routes to only + // match alerts with a namespace label equal to the namespace of the + // AlertmanagerConfig resource. + OnNamespaceMatcherStrategy AlertmanagerConfigMatcherStrategyType = "OnNamespace" + + // OnNamespaceExceptForAlertmanagerNamespaceMatcherStrategy behaves like + // OnNamespace, but AlertmanagerConfig resources in the same namespace as + // the Alertmanager instance match all alerts regardless of namespace. + OnNamespaceExceptForAlertmanagerNamespaceMatcherStrategy AlertmanagerConfigMatcherStrategyType = "OnNamespaceExceptForAlertmanagerNamespace" + + // NoneMatcherStrategy configures AlertmanagerConfig routes to match all + // incoming alerts regardless of namespace. + NoneMatcherStrategy AlertmanagerConfigMatcherStrategyType = "None" +) + // MonitoringStackSpec is the specification for desired Monitoring Stack type MonitoringStackSpec struct { // +optional @@ -264,6 +283,17 @@ type AlertmanagerConfig struct { // +kubebuilder:validation:Minimum=0 Replicas *int32 `json:"replicas,omitempty"` + // Define how AlertmanagerConfig objects process incoming alerts. + // With OnNamespace, routes only match alerts with a namespace label + // equal to the namespace of the AlertmanagerConfig. + // With OnNamespaceExceptForAlertmanagerNamespace, routes behave like + // OnNamespace but AlertmanagerConfig resources in the Alertmanager's + // own namespace match all alerts. + // With None, routes match all incoming alerts regardless of namespace. + // +optional + // +kubebuilder:default="None" + MatcherStrategy AlertmanagerConfigMatcherStrategyType `json:"matcherStrategy,omitempty"` + // Configure TLS options for the Alertmanager web server. // +optional WebTLSConfig *WebTLSConfig `json:"webTLSConfig,omitempty"` diff --git a/pkg/controllers/monitoring/monitoring-stack/alertmanager.go b/pkg/controllers/monitoring/monitoring-stack/alertmanager.go index 3f512e468..c849290b9 100644 --- a/pkg/controllers/monitoring/monitoring-stack/alertmanager.go +++ b/pkg/controllers/monitoring/monitoring-stack/alertmanager.go @@ -38,8 +38,11 @@ func newAlertmanager( Replicas: ms.Spec.AlertmanagerConfig.Replicas, ServiceAccountName: rbacResourceName, AlertmanagerConfigSelector: resourceSelector, - NodeSelector: ms.Spec.NodeSelector, - Tolerations: ms.Spec.Tolerations, + AlertmanagerConfigMatcherStrategy: monv1.AlertmanagerConfigMatcherStrategy{ + Type: monv1.AlertmanagerConfigMatcherStrategyType(ms.Spec.AlertmanagerConfig.MatcherStrategy), + }, + NodeSelector: ms.Spec.NodeSelector, + Tolerations: ms.Spec.Tolerations, Affinity: &corev1.Affinity{ PodAntiAffinity: &corev1.PodAntiAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: []corev1.PodAffinityTerm{ diff --git a/pkg/controllers/monitoring/monitoring-stack/alertmanager_test.go b/pkg/controllers/monitoring/monitoring-stack/alertmanager_test.go new file mode 100644 index 000000000..36f9304da --- /dev/null +++ b/pkg/controllers/monitoring/monitoring-stack/alertmanager_test.go @@ -0,0 +1,52 @@ +package monitoringstack + +import ( + "testing" + + monv1 "github.com/rhobs/obo-prometheus-operator/pkg/apis/monitoring/v1" + "gotest.tools/v3/assert" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + stack "github.com/rhobs/observability-operator/pkg/apis/monitoring/v1alpha1" +) + +func TestNewAlertmanagerMatcherStrategy(t *testing.T) { + for _, tc := range []struct { + name string + strategy stack.AlertmanagerConfigMatcherStrategyType + expected monv1.AlertmanagerConfigMatcherStrategyType + }{ + { + name: "None", + strategy: stack.NoneMatcherStrategy, + expected: monv1.NoneConfigMatcherStrategyType, + }, + { + name: "OnNamespace", + strategy: stack.OnNamespaceMatcherStrategy, + expected: monv1.OnNamespaceConfigMatcherStrategyType, + }, + { + name: "OnNamespaceExceptForAlertmanagerNamespace", + strategy: stack.OnNamespaceExceptForAlertmanagerNamespaceMatcherStrategy, + expected: monv1.OnNamespaceExceptForAlertmanagerNamespaceConfigMatcherStrategyType, + }, + } { + t.Run(tc.name, func(t *testing.T) { + ms := &stack.MonitoringStack{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "test-ns", + }, + Spec: stack.MonitoringStackSpec{ + AlertmanagerConfig: stack.AlertmanagerConfig{ + MatcherStrategy: tc.strategy, + }, + }, + } + + am := newAlertmanager(ms, "test-sa", AlertmanagerConfiguration{}) + assert.Equal(t, am.Spec.AlertmanagerConfigMatcherStrategy.Type, tc.expected) + }) + } +}