From 72f2c521095b353e4ebc5d10d65fbf2c51403985 Mon Sep 17 00:00:00 2001 From: Nikolay Date: Thu, 29 Oct 2020 19:57:28 +0300 Subject: [PATCH] adds filtering for prometheus converter relabelConfig (#93) * adds filtering for prometheus converter now unsupported by vmagent relabel configuration will be skipped https://github.com/VictoriaMetrics/operator/issues/92 * fixes tests * reformat imports, fixes typo --- controllers/converter/apis.go | 27 +++++++++-- controllers/converter/apis_test.go | 35 ++++++++++++-- .../vmprometheusconverter_controller.go | 10 ++-- e2e/prometheus_converter_test.go | 47 +++++++++++++++++++ 4 files changed, 108 insertions(+), 11 deletions(-) diff --git a/controllers/converter/apis.go b/controllers/converter/apis.go index a33d2975..55032506 100644 --- a/controllers/converter/apis.go +++ b/controllers/converter/apis.go @@ -1,11 +1,13 @@ package converter import ( + "strings" + v1beta1vm "github.com/VictoriaMetrics/operator/api/v1beta1" "github.com/VictoriaMetrics/operator/controllers/factory" v1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "strings" + ctrl "sigs.k8s.io/controller-runtime" ) const ( @@ -13,6 +15,8 @@ const ( prometheusConfigmapDir = "/etc/prometheus/configmaps" ) +var log = ctrl.Log.WithValues("controller", "prometheus.converter") + func ConvertPromRule(prom *v1.PrometheusRule) *v1beta1vm.VMRule { ruleGroups := []v1beta1vm.RuleGroup{} @@ -143,9 +147,9 @@ func ConvertRelabelConfig(promRelabelConfig []*v1.RelabelConfig) []*v1beta1vm.Re if promRelabelConfig == nil { return nil } - relalbelConf := []*v1beta1vm.RelabelConfig{} + relabelCfg := []*v1beta1vm.RelabelConfig{} for _, relabel := range promRelabelConfig { - relalbelConf = append(relalbelConf, &v1beta1vm.RelabelConfig{ + relabelCfg = append(relabelCfg, &v1beta1vm.RelabelConfig{ SourceLabels: relabel.SourceLabels, Separator: relabel.Separator, TargetLabel: relabel.TargetLabel, @@ -155,7 +159,7 @@ func ConvertRelabelConfig(promRelabelConfig []*v1.RelabelConfig) []*v1beta1vm.Re Action: relabel.Action, }) } - return relalbelConf + return filterUnsupportedRelabelCfg(relabelCfg) } @@ -248,3 +252,18 @@ func ConvertProbe(probe *v1.Probe) *v1beta1vm.VMProbe { }, } } + +func filterUnsupportedRelabelCfg(relabelCfgs []*v1beta1vm.RelabelConfig) []*v1beta1vm.RelabelConfig { + newRelabelCfg := make([]*v1beta1vm.RelabelConfig, 0, len(relabelCfgs)) + for _, r := range relabelCfgs { + switch r.Action { + case "keep", "hashmod", "drop": + if len(r.SourceLabels) == 0 { + log.Info("filtering unsupported relabelConfig", "action", r.Action, "reason", "source labels are empty") + continue + } + } + newRelabelCfg = append(newRelabelCfg, r) + } + return newRelabelCfg +} diff --git a/controllers/converter/apis_test.go b/controllers/converter/apis_test.go index bb615d00..df307b54 100644 --- a/controllers/converter/apis_test.go +++ b/controllers/converter/apis_test.go @@ -74,6 +74,26 @@ func TestConvertRelabelConfig(t *testing.T) { }, }, }, + { + name: "unsupported config", + args: args{ + promRelabelConfig: []*v1.RelabelConfig{ + { + Action: "drop", + }, + { + Action: "keep", + SourceLabels: []string{"__address__"}, + }, + }, + }, + want: []*v1beta1vm.RelabelConfig{ + { + Action: "keep", + SourceLabels: []string{"__address__"}, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -108,7 +128,11 @@ func TestConvertEndpoint(t *testing.T) { Path: "/metrics", RelabelConfigs: []*v1.RelabelConfig{ { - Action: "drop", + Action: "drop", + SourceLabels: []string{"__meta__instance"}, + }, + { + Action: "keep", }, }, }, @@ -120,7 +144,8 @@ func TestConvertEndpoint(t *testing.T) { Port: "9100", RelabelConfigs: []*v1beta1vm.RelabelConfig{ { - Action: "drop", + Action: "drop", + SourceLabels: []string{"__meta__instance"}, }, }, }, @@ -154,7 +179,8 @@ func TestConvertServiceMonitor(t *testing.T) { { MetricRelabelConfigs: []*v1.RelabelConfig{ { - Action: "drop", + Action: "drop", + SourceLabels: []string{"__meta__instance"}, }, }, }, @@ -168,7 +194,8 @@ func TestConvertServiceMonitor(t *testing.T) { { MetricRelabelConfigs: []*v1beta1vm.RelabelConfig{ { - Action: "drop", + Action: "drop", + SourceLabels: []string{"__meta__instance"}, }, }, }, diff --git a/controllers/vmprometheusconverter_controller.go b/controllers/vmprometheusconverter_controller.go index 16d10a23..84a962d1 100644 --- a/controllers/vmprometheusconverter_controller.go +++ b/controllers/vmprometheusconverter_controller.go @@ -219,6 +219,7 @@ func (c *ConverterController) CreatePrometheusRule(rule interface{}) { if err != nil { if errors.IsAlreadyExists(err) { l.Info("AlertRule already exists") + c.UpdatePrometheusRule(nil, promRule) return } l.Error(err, "cannot create AlertRule from Prometheusrule") @@ -268,6 +269,7 @@ func (c *ConverterController) CreateServiceMonitor(service interface{}) { if err != nil { if errors.IsAlreadyExists(err) { l.Info("vmServiceScrape exists") + c.UpdateServiceMonitor(nil, serviceMon) return } l.Error(err, "cannot create vmServiceScrape") @@ -277,7 +279,7 @@ func (c *ConverterController) CreateServiceMonitor(service interface{}) { } // UpdateServiceMonitor updates VMServiceMonitor -func (c *ConverterController) UpdateServiceMonitor(old, new interface{}) { +func (c *ConverterController) UpdateServiceMonitor(_, new interface{}) { serviceMonNew := new.(*v1.ServiceMonitor) l := log.WithValues("kind", "vmServiceScrape", "name", serviceMonNew.Name, "ns", serviceMonNew.Namespace) l.Info("updating vmServiceScrape") @@ -317,6 +319,7 @@ func (c *ConverterController) CreatePodMonitor(pod interface{}) { if err != nil { if errors.IsAlreadyExists(err) { l.Info("podScrape already exists") + c.UpdatePodMonitor(nil, podMonitor) return } l.Error(err, "cannot create podScrape") @@ -327,7 +330,7 @@ func (c *ConverterController) CreatePodMonitor(pod interface{}) { } // UpdatePodMonitor updates VMPodScrape -func (c *ConverterController) UpdatePodMonitor(old, new interface{}) { +func (c *ConverterController) UpdatePodMonitor(_, new interface{}) { podMonitorNew := new.(*v1.PodMonitor) l := log.WithValues("kind", "podScrape", "name", podMonitorNew.Name, "ns", podMonitorNew.Namespace) podScrape := converter.ConvertPodMonitor(podMonitorNew) @@ -407,6 +410,7 @@ func (c *ConverterController) CreateProbe(obj interface{}) { if err != nil { if errors.IsAlreadyExists(err) { l.Info("vmProbe already exists") + c.UpdateProbe(nil, probe) return } l.Error(err, "cannot create vmProbe") @@ -417,7 +421,7 @@ func (c *ConverterController) CreateProbe(obj interface{}) { } // UpdateProbe updates VMProbe -func (c *ConverterController) UpdateProbe(old, new interface{}) { +func (c *ConverterController) UpdateProbe(_, new interface{}) { probeNew := new.(*v1.Probe) l := log.WithValues("kind", "vmProbe", "name", probeNew.Name, "ns", probeNew.Namespace) vmProbe := converter.ConvertProbe(probeNew) diff --git a/e2e/prometheus_converter_test.go b/e2e/prometheus_converter_test.go index e6a9c4eb..a6e43325 100644 --- a/e2e/prometheus_converter_test.go +++ b/e2e/prometheus_converter_test.go @@ -2,6 +2,8 @@ package e2e import ( "context" + "fmt" + victoriametricsv1beta1 "github.com/VictoriaMetrics/operator/api/v1beta1" monitoringv1 "github.com/coreos/prometheus-operator/pkg/apis/monitoring/v1" @@ -56,6 +58,51 @@ var _ = Describe("test prometheusConverter Controller", func() { }) }, 60, 1).Should(Succeed()) }) + It("should create prometheus ServiceMonitor with relabel filter", func() { + Expect(k8sClient.Create(context.TODO(), &monitoringv1.ServiceMonitor{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: name, + }, + Spec: monitoringv1.ServiceMonitorSpec{ + Endpoints: []monitoringv1.Endpoint{ + { + Port: "8081", + RelabelConfigs: []*monitoringv1.RelabelConfig{ + { + Action: "keep", + }, + { + Action: "drop", + SourceLabels: []string{"__address__"}, + }, + }, + }, + }, + Selector: metav1.LabelSelector{MatchLabels: map[string]string{"managed-by": "vm-operator"}}, + }, + })).To(Succeed()) + Eventually(func() error { + expectedVMServiceScrape := &victoriametricsv1beta1.VMServiceScrape{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }} + err := k8sClient.Get(context.TODO(), types.NamespacedName{Namespace: namespace, Name: name}, expectedVMServiceScrape) + if err != nil { + return err + } + if len(expectedVMServiceScrape.Spec.Endpoints) != 1 { + return fmt.Errorf("unexpected number of endpoints, want 1, got: %d", len(expectedVMServiceScrape.Spec.Endpoints)) + } + endpoint := expectedVMServiceScrape.Spec.Endpoints[0] + if len(endpoint.RelabelConfigs) != 1 { + return fmt.Errorf("unexpected relabelConfig for vmservice scrape, want len 1, got endpoint: %v", endpoint) + } + return nil + }, 60, 1).Should(Succeed()) + }) + }) },