Skip to content

Commit

Permalink
[feat] - selectors
Browse files Browse the repository at this point in the history
Signed-off-by: Hélia Barroso <helia_barroso@hotmail.com>
  • Loading branch information
heliapb committed Dec 11, 2024
1 parent 74e5c11 commit 4d7cf09
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 77 deletions.
81 changes: 5 additions & 76 deletions internal/analyzers/prometheus.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,6 @@ import (
"github.com/prometheus-operator/poctl/internal/k8sutil"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
)

const (
ServiceMonitor = "ServiceMonitor"
PodMonitor = "PodMonitor"
Probe = "Probe"
ScrapeConfig = "ScrapeConfig"
PrometheusRule = "PrometheusRule"
)

func RunPrometheusAnalyzer(ctx context.Context, clientSets *k8sutil.ClientSets, name, namespace string) error {
Expand Down Expand Up @@ -85,88 +76,26 @@ func RunPrometheusAnalyzer(ctx context.Context, clientSets *k8sutil.ClientSets,
return fmt.Errorf("ruleNamespaceSelector is not properly defined: %s", err)
}

if err := checkResourceLabelSelectors(ctx, clientSets, prometheus.Spec.ServiceMonitorSelector, ServiceMonitor, namespace); err != nil {
if err := k8sutil.CheckResourceLabelSelectors(ctx, *clientSets, prometheus.Spec.ServiceMonitorSelector, k8sutil.ServiceMonitor, namespace); err != nil {
return fmt.Errorf("serviceMonitorSelector is not properly defined: %s", err)
}

if err := checkResourceLabelSelectors(ctx, clientSets, prometheus.Spec.PodMonitorSelector, PodMonitor, namespace); err != nil {
if err := k8sutil.CheckResourceLabelSelectors(ctx, *clientSets, prometheus.Spec.PodMonitorSelector, k8sutil.PodMonitor, namespace); err != nil {
return fmt.Errorf("podMonitorSelector is not properly defined: %s", err)
}

if err := checkResourceLabelSelectors(ctx, clientSets, prometheus.Spec.ProbeSelector, Probe, namespace); err != nil {
if err := k8sutil.CheckResourceLabelSelectors(ctx, *clientSets, prometheus.Spec.ProbeSelector, k8sutil.Probe, namespace); err != nil {
return fmt.Errorf("probeSelector is not properly defined: %s", err)
}

if err := checkResourceLabelSelectors(ctx, clientSets, prometheus.Spec.ScrapeConfigSelector, ScrapeConfig, namespace); err != nil {
if err := k8sutil.CheckResourceLabelSelectors(ctx, *clientSets, prometheus.Spec.ScrapeConfigSelector, k8sutil.ScrapeConfig, namespace); err != nil {
return fmt.Errorf("scrapeConfigSelector is not properly defined: %s", err)
}

if err := checkResourceLabelSelectors(ctx, clientSets, prometheus.Spec.RuleSelector, PrometheusRule, namespace); err != nil {
if err := k8sutil.CheckResourceLabelSelectors(ctx, *clientSets, prometheus.Spec.RuleSelector, k8sutil.PrometheusRule, namespace); err != nil {
return fmt.Errorf("ruleSelector is not properly defined: %s", err)
}

slog.Info("Prometheus is compliant, no issues found", "name", name, "namespace", namespace)
return nil
}

func checkResourceLabelSelectors(ctx context.Context, clientSets *k8sutil.ClientSets, labelSelector *metav1.LabelSelector, resourceName, namespace string) error {
if labelSelector == nil {
return fmt.Errorf("%s selector is not defined", resourceName)
}

if len(labelSelector.MatchLabels) == 0 && len(labelSelector.MatchExpressions) == 0 {
return nil
}

labelMap, err := metav1.LabelSelectorAsMap(labelSelector)
if err != nil {
return fmt.Errorf("invalid label selector format in %s: %v", resourceName, err)
}

switch resourceName {
case ServiceMonitor:
serviceMonitors, err := clientSets.MClient.MonitoringV1().ServiceMonitors(namespace).List(ctx, metav1.ListOptions{LabelSelector: labels.SelectorFromSet(labelMap).String()})
if err != nil {
return fmt.Errorf("failed to list ServiceMonitors in %s: %v", namespace, err)
}
if len(serviceMonitors.Items) == 0 {
return fmt.Errorf("no ServiceMonitors match the provided selector in Prometheus %s", namespace)
}
case PodMonitor:
podMonitors, err := clientSets.MClient.MonitoringV1().PodMonitors(namespace).List(ctx, metav1.ListOptions{LabelSelector: labels.SelectorFromSet(labelMap).String()})
if err != nil {
return fmt.Errorf("failed to list PodMonitor in %s: %v", namespace, err)
}
if len(podMonitors.Items) == 0 {
return fmt.Errorf("no PodMonitors match the provided selector in Prometheus %s", namespace)
}
case Probe:
probes, err := clientSets.MClient.MonitoringV1().Probes(namespace).List(ctx, metav1.ListOptions{LabelSelector: labels.SelectorFromSet(labelMap).String()})
if err != nil {
return fmt.Errorf("failed to list Probes in %s: %v", namespace, err)
}
if len(probes.Items) == 0 {
return fmt.Errorf("no Probes match the provided selector in Prometheus %s", namespace)
}
case ScrapeConfig:
scrapeConfigs, err := clientSets.MClient.MonitoringV1alpha1().ScrapeConfigs(namespace).List(ctx, metav1.ListOptions{LabelSelector: labels.SelectorFromSet(labelMap).String()})
if err != nil {
return fmt.Errorf("failed to list ScrapeConfigs in %s: %v", namespace, err)
}
if len(scrapeConfigs.Items) == 0 {
return fmt.Errorf("no ScrapeConfigs match the provided selector in Prometheus %s", namespace)
}
case PrometheusRule:
promRules, err := clientSets.MClient.MonitoringV1().PrometheusRules(namespace).List(ctx, metav1.ListOptions{LabelSelector: labels.SelectorFromSet(labelMap).String()})
if err != nil {
return fmt.Errorf("failed to list Probes in %s: %v", namespace, err)
}
if len(promRules.Items) == 0 {
return fmt.Errorf("no PrometheusRules match the provided selector in Prometheus %s", namespace)
}
default:
return fmt.Errorf("unknown selector type: %s", resourceName)
}

return nil
}
34 changes: 33 additions & 1 deletion internal/analyzers/prometheusagent.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,38 @@ func RunPrometheusAgentAnalyzer(ctx context.Context, clientSets *k8sutil.ClientS
}
}

slog.Info("Prometheus Agent is compliant, no issues found", "name", name, "namespace", namespace)
if err := k8sutil.CheckResourceNamespaceSelectors(ctx, *clientSets, prometheusagent.Spec.PodMonitorNamespaceSelector); err != nil {
return fmt.Errorf("podMonitorNamespaceSelector is not properly defined: %s", err)
}

if err := k8sutil.CheckResourceNamespaceSelectors(ctx, *clientSets, prometheusagent.Spec.ProbeNamespaceSelector); err != nil {
return fmt.Errorf("probeNamespaceSelector is not properly defined: %s", err)
}

if err := k8sutil.CheckResourceNamespaceSelectors(ctx, *clientSets, prometheusagent.Spec.ServiceMonitorNamespaceSelector); err != nil {
return fmt.Errorf("serviceMonitorNamespaceSelector is not properly defined: %s", err)
}

if err := k8sutil.CheckResourceNamespaceSelectors(ctx, *clientSets, prometheusagent.Spec.ScrapeConfigNamespaceSelector); err != nil {
return fmt.Errorf("scrapeConfigNamespaceSelector is not properly defined: %s", err)
}

if err := k8sutil.CheckResourceLabelSelectors(ctx, *clientSets, prometheusagent.Spec.ServiceMonitorSelector, k8sutil.ServiceMonitor, namespace); err != nil {
return fmt.Errorf("serviceMonitorSelector is not properly defined: %s", err)
}

if err := k8sutil.CheckResourceLabelSelectors(ctx, *clientSets, prometheusagent.Spec.PodMonitorSelector, k8sutil.PodMonitor, namespace); err != nil {
return fmt.Errorf("podMonitorSelector is not properly defined: %s", err)
}

if err := k8sutil.CheckResourceLabelSelectors(ctx, *clientSets, prometheusagent.Spec.ProbeSelector, k8sutil.Probe, namespace); err != nil {
return fmt.Errorf("probeSelector is not properly defined: %s", err)
}

if err := k8sutil.CheckResourceLabelSelectors(ctx, *clientSets, prometheusagent.Spec.ScrapeConfigSelector, k8sutil.ScrapeConfig, namespace); err != nil {
return fmt.Errorf("scrapeConfigSelector is not properly defined: %s", err)
}

slog.Info("prometheusagent Agent is compliant, no issues found", "name", name, "namespace", namespace)
return nil
}
70 changes: 70 additions & 0 deletions internal/k8sutil/k8sutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ import (
"k8s.io/client-go/tools/clientcmd"
)

const (
ServiceMonitor = "ServiceMonitor"
PodMonitor = "PodMonitor"
Probe = "Probe"
ScrapeConfig = "ScrapeConfig"
PrometheusRule = "PrometheusRule"
)

var ApplyOption = metav1.ApplyOptions{
FieldManager: "application/apply-patch",
}
Expand Down Expand Up @@ -188,6 +196,68 @@ func CheckResourceNamespaceSelectors(ctx context.Context, clientSets ClientSets,
return nil
}

func CheckResourceLabelSelectors(ctx context.Context, clientSets ClientSets, labelSelector *metav1.LabelSelector, resourceName, namespace string) error {
if labelSelector == nil {
return fmt.Errorf("%s selector is not defined", resourceName)
}

if len(labelSelector.MatchLabels) == 0 && len(labelSelector.MatchExpressions) == 0 {
return nil
}

labelMap, err := metav1.LabelSelectorAsMap(labelSelector)
if err != nil {
return fmt.Errorf("invalid label selector format in %s: %v", resourceName, err)
}

switch resourceName {
case ServiceMonitor:
serviceMonitors, err := clientSets.MClient.MonitoringV1().ServiceMonitors(namespace).List(ctx, metav1.ListOptions{LabelSelector: labels.SelectorFromSet(labelMap).String()})
if err != nil {
return fmt.Errorf("failed to list ServiceMonitors in %s: %v", namespace, err)
}
if len(serviceMonitors.Items) == 0 {
return fmt.Errorf("no ServiceMonitors match the provided selector in Prometheus %s", namespace)
}
case PodMonitor:
podMonitors, err := clientSets.MClient.MonitoringV1().PodMonitors(namespace).List(ctx, metav1.ListOptions{LabelSelector: labels.SelectorFromSet(labelMap).String()})
if err != nil {
return fmt.Errorf("failed to list PodMonitor in %s: %v", namespace, err)
}
if len(podMonitors.Items) == 0 {
return fmt.Errorf("no PodMonitors match the provided selector in Prometheus %s", namespace)
}
case Probe:
probes, err := clientSets.MClient.MonitoringV1().Probes(namespace).List(ctx, metav1.ListOptions{LabelSelector: labels.SelectorFromSet(labelMap).String()})
if err != nil {
return fmt.Errorf("failed to list Probes in %s: %v", namespace, err)
}
if len(probes.Items) == 0 {
return fmt.Errorf("no Probes match the provided selector in Prometheus %s", namespace)
}
case ScrapeConfig:
scrapeConfigs, err := clientSets.MClient.MonitoringV1alpha1().ScrapeConfigs(namespace).List(ctx, metav1.ListOptions{LabelSelector: labels.SelectorFromSet(labelMap).String()})
if err != nil {
return fmt.Errorf("failed to list ScrapeConfigs in %s: %v", namespace, err)
}
if len(scrapeConfigs.Items) == 0 {
return fmt.Errorf("no ScrapeConfigs match the provided selector in Prometheus %s", namespace)
}
case PrometheusRule:
promRules, err := clientSets.MClient.MonitoringV1().PrometheusRules(namespace).List(ctx, metav1.ListOptions{LabelSelector: labels.SelectorFromSet(labelMap).String()})
if err != nil {
return fmt.Errorf("failed to list Probes in %s: %v", namespace, err)
}
if len(promRules.Items) == 0 {
return fmt.Errorf("no PrometheusRules match the provided selector in Prometheus %s", namespace)
}
default:
return fmt.Errorf("unknown selector type: %s", resourceName)
}

return nil
}

func CheckPrometheusClusterRoleRules(crb v1.ClusterRoleBinding, cr *v1.ClusterRole) error {
var errs []string
verbsToCheck := []string{"get", "list", "watch"}
Expand Down

0 comments on commit 4d7cf09

Please sign in to comment.