Skip to content

Commit b71de06

Browse files
committed
feat - svc, pod
Signed-off-by: Hélia Barroso <[email protected]>
1 parent 2e19719 commit b71de06

File tree

3 files changed

+136
-90
lines changed

3 files changed

+136
-90
lines changed

cmd/analyze.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,12 @@ import (
2828
type AnalyzeKind string
2929

3030
const (
31-
ServiceMonitor AnalyzeKind = "servicemonitor"
32-
Operator AnalyzeKind = "operator"
33-
Prometheus AnalyzeKind = "prometheus"
34-
Alertmanager AnalyzeKind = "alertmanager"
35-
PrometheusAgent AnalyzeKind = "prometheusagent"
36-
MonitoringOverlapping AnalyzeKind = "monitoroverlapping"
31+
ServiceMonitor AnalyzeKind = "servicemonitor"
32+
Operator AnalyzeKind = "operator"
33+
Prometheus AnalyzeKind = "prometheus"
34+
Alertmanager AnalyzeKind = "alertmanager"
35+
PrometheusAgent AnalyzeKind = "prometheusagent"
36+
Overlapping AnalyzeKind = "overlapping"
3737
)
3838

3939
type AnalyzeFlags struct {
@@ -88,8 +88,8 @@ func run(cmd *cobra.Command, _ []string) error {
8888
return analyzers.RunAlertmanagerAnalyzer(cmd.Context(), clientSets, analyzerFlags.Name, analyzerFlags.Namespace)
8989
case PrometheusAgent:
9090
return analyzers.RunPrometheusAgentAnalyzer(cmd.Context(), clientSets, analyzerFlags.Name, analyzerFlags.Namespace)
91-
case MonitoringOverlapping:
92-
return analyzers.RunMonitoringOverlappingAnalyzer(cmd.Context(), clientSets, analyzerFlags.Name, analyzerFlags.Namespace)
91+
case Overlapping:
92+
return analyzers.RunOverlappingAnalyzer(cmd.Context(), clientSets, analyzerFlags.Name, analyzerFlags.Namespace)
9393
default:
9494
return fmt.Errorf("kind %s not supported", analyzerFlags.Kind)
9595
}

internal/analyzers/monitoroverlapping.go

Lines changed: 0 additions & 82 deletions
This file was deleted.

internal/analyzers/overlapping.go

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// Copyright 2024 The prometheus-operator Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package analyzers
16+
17+
import (
18+
"context"
19+
"fmt"
20+
"log/slog"
21+
"strings"
22+
23+
"github.com/prometheus-operator/poctl/internal/k8sutil"
24+
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
25+
"k8s.io/apimachinery/pkg/api/errors"
26+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27+
)
28+
29+
func RunOverlappingAnalyzer(ctx context.Context, clientSets *k8sutil.ClientSets, name, namespace string) error {
30+
var monitorsListErrs []string
31+
32+
serviceMonitors, err := clientSets.MClient.MonitoringV1().ServiceMonitors(namespace).List(ctx, metav1.ListOptions{})
33+
if err != nil {
34+
if errors.IsNotFound(err) {
35+
monitorsListErrs = append(monitorsListErrs, fmt.Sprintf("No ServiceMonitors found in namespace %s", namespace))
36+
}
37+
monitorsListErrs = append(monitorsListErrs, fmt.Sprintf("No ServiceMonitors found in namespace %s", namespace))
38+
}
39+
40+
podMonitors, err := clientSets.MClient.MonitoringV1().PodMonitors(namespace).List(ctx, metav1.ListOptions{})
41+
if err != nil {
42+
if errors.IsNotFound(err) {
43+
monitorsListErrs = append(monitorsListErrs, fmt.Sprintf("No PodMonitors found in namespace %s", namespace))
44+
}
45+
monitorsListErrs = append(monitorsListErrs, fmt.Sprintf("No PodMonitors found in namespace %s", namespace))
46+
}
47+
48+
if len(monitorsListErrs) > 0 {
49+
return fmt.Errorf("errors listing Pod/Service Monitors")
50+
}
51+
52+
serviceOverlaps := make(map[string][]string)
53+
podOverlaps := make(map[string][]string)
54+
var overlapErrs []string
55+
56+
for _, servicemonitor := range serviceMonitors.Items {
57+
if err := checkOverlappingServiceMonitors(ctx, clientSets, servicemonitor, serviceOverlaps); err != nil {
58+
overlapErrs = append(overlapErrs, err.Error())
59+
}
60+
}
61+
for _, podmonitor := range podMonitors.Items {
62+
if err := checkOverlappingPodMonitors(ctx, clientSets, podmonitor, podOverlaps); err != nil {
63+
overlapErrs = append(overlapErrs, err.Error())
64+
}
65+
}
66+
67+
for key, svcMonitors := range serviceOverlaps {
68+
if len(svcMonitors) > 1 {
69+
overlapErrs = append(overlapErrs, fmt.Sprintf("Overlapping ServiceMonitors found for service/port %s: %v", key, svcMonitors))
70+
}
71+
}
72+
73+
for key, pdMonitors := range podOverlaps {
74+
if len(pdMonitors) > 1 {
75+
overlapErrs = append(overlapErrs, fmt.Sprintf("Overlapping PodMonitors found for pod/port %s: %v", key, pdMonitors))
76+
}
77+
}
78+
79+
if len(overlapErrs) > 0 {
80+
return fmt.Errorf("multiple issues found:\n%s", strings.Join(overlapErrs, "\n"))
81+
}
82+
83+
slog.Info("no overlapping monitoring configurations found in", "namespace", namespace)
84+
return nil
85+
}
86+
87+
func checkOverlappingServiceMonitors(ctx context.Context, clientSets *k8sutil.ClientSets, servicemonitor *monitoringv1.ServiceMonitor, serviceOverlaps map[string][]string) error {
88+
selector, err := metav1.LabelSelectorAsSelector(&servicemonitor.Spec.Selector)
89+
if err != nil {
90+
return fmt.Errorf("invalid selector in ServiceMonitor %s/%s: %v", servicemonitor.Namespace, servicemonitor.Name, err)
91+
}
92+
93+
services, err := clientSets.KClient.CoreV1().Services(servicemonitor.Namespace).List(ctx, metav1.ListOptions{LabelSelector: selector.String()})
94+
if err != nil {
95+
return fmt.Errorf("error listing services for ServiceMonitor %s/%s: %v", servicemonitor.Namespace, servicemonitor.Name, err)
96+
}
97+
98+
for _, service := range services.Items {
99+
for _, scvPort := range service.Spec.Ports {
100+
servicekey := fmt.Sprintf("%s/%s:%d", service.Namespace, service.Name, scvPort.Port)
101+
serviceOverlaps[servicekey] = append(serviceOverlaps[servicekey], servicemonitor.Name)
102+
103+
}
104+
}
105+
106+
return nil
107+
}
108+
109+
func checkOverlappingPodMonitors(ctx context.Context, clientSets *k8sutil.ClientSets, podmonitor *monitoringv1.PodMonitor, podOverlaps map[string][]string) error {
110+
selector, err := metav1.LabelSelectorAsSelector(&podmonitor.Spec.Selector)
111+
if err != nil {
112+
return fmt.Errorf("invalid selector in PodMonitor %s/%s: %v", podmonitor.Namespace, podmonitor.Name, err)
113+
}
114+
115+
pods, err := clientSets.KClient.CoreV1().Pods(podmonitor.Namespace).List(ctx, metav1.ListOptions{LabelSelector: selector.String()})
116+
if err != nil {
117+
return fmt.Errorf("error listing pods for PodMonitor %s/%s: %v", podmonitor.Namespace, podmonitor.Name, err)
118+
}
119+
120+
for _, pod := range pods.Items {
121+
for _, podPort := range podmonitor.Spec.PodMetricsEndpoints {
122+
podKey := fmt.Sprintf("%s/%s:%s", pod.Namespace, pod.Name, podPort.Port)
123+
podOverlaps[podKey] = append(podOverlaps[podKey], podmonitor.Name)
124+
}
125+
}
126+
127+
return nil
128+
}

0 commit comments

Comments
 (0)