Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
anunarapureddy committed May 5, 2023
1 parent d919583 commit e88ddf8
Show file tree
Hide file tree
Showing 8 changed files with 482 additions and 13 deletions.
37 changes: 29 additions & 8 deletions pkg/collector/reconcile/config_replace.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package reconcile
import (
"fmt"
"net/url"
"strings"

"github.com/mitchellh/mapstructure"
promconfig "github.com/prometheus/prometheus/config"
Expand All @@ -36,15 +37,18 @@ type Config struct {
}

func ReplaceConfig(instance v1alpha1.OpenTelemetryCollector) (string, error) {
// Check if TargetAllocator is enabled, if not, return the original config
if !instance.Spec.TargetAllocator.Enabled {
return instance.Spec.Config, nil
}

config, getStringErr := adapters.ConfigFromString(instance.Spec.Config)
if getStringErr != nil {
return "", getStringErr
}

promCfgMap, getCfgPromErr := ta.ConfigToPromConfig(instance.Spec.Config)
// Get the Prometheus config map with dollar signs replaced to ensure successful validation of Prometheus regex
promCfgMap, getCfgPromErr := ta.ReplaceDollarSignInPromConfig(instance.Spec.Config)
if getCfgPromErr != nil {
return "", getCfgPromErr
}
Expand All @@ -62,21 +66,38 @@ func ReplaceConfig(instance v1alpha1.OpenTelemetryCollector) (string, error) {
return "", fmt.Errorf("error unmarshaling YAML: %w", marshalErr)
}

for i := range cfg.PromConfig.ScrapeConfigs {
escapedJob := url.QueryEscape(cfg.PromConfig.ScrapeConfigs[i].JobName)
cfg.PromConfig.ScrapeConfigs[i].ServiceDiscoveryConfigs = discovery.Configs{
&http.SDConfig{
URL: fmt.Sprintf("http://%s:80/jobs/%s/targets?collector_id=$POD_NAME", naming.TAService(instance), escapedJob),
},
// Escapes default replacement key added by prometheus and resets all other replacement keys to their original values
replacer := strings.NewReplacer(
"$", "$$",
"__DOUBLE_DOLLAR__", "$$",
"__SINGLE_DOLLAR__", "$",
)

// Loop through the scrape configs and escape "$" characters in relabel_configs and metric_relabel_configs
for _, scrapeCfg := range cfg.PromConfig.ScrapeConfigs {
for _, relabelCfg := range scrapeCfg.RelabelConfigs {
relabelCfg.Replacement = replacer.Replace(relabelCfg.Replacement)
}
for _, metricRelabelCfg := range scrapeCfg.MetricRelabelConfigs {
metricRelabelCfg.Replacement = replacer.Replace(metricRelabelCfg.Replacement)
}
// Escape the job name for use in the URL
escapedJob := url.QueryEscape(scrapeCfg.JobName)
// Create the service discovery configuration with the formatted URL
sdConfig := &http.SDConfig{
URL: fmt.Sprintf("http://%s:80/jobs/%s/targets?collector_id=$POD_NAME", naming.TAService(instance), escapedJob),
}
scrapeCfg.ServiceDiscoveryConfigs = discovery.Configs{sdConfig}
}

// Decode the Config struct back to a map and update the Prometheus config map
updPromCfgMap := make(map[string]interface{})
if err := mapstructure.Decode(cfg, &updPromCfgMap); err != nil {
return "", err
}

// type coercion checks are handled in the ConfigToPromConfig method above
// Update the OpenTelemetryCollector instance's config with the updated Prometheus config map
// type coercion checks are handled in the ReplaceDollarSignInPromConfig method above
config["receivers"].(map[interface{}]interface{})["prometheus"].(map[interface{}]interface{})["config"] = updPromCfgMap["PromConfig"]

out, err := yaml.Marshal(config)
Expand Down
29 changes: 29 additions & 0 deletions pkg/collector/reconcile/config_replace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package reconcile

import (
"os"
"testing"

"github.com/prometheus/prometheus/discovery/http"
Expand Down Expand Up @@ -96,3 +97,31 @@ func TestPrometheusParser(t *testing.T) {
})

}

func TestRelabelConfig(t *testing.T) {
param, err := newParams("test/test-img", "../testdata/relabel_config_original.yaml")
assert.NoError(t, err)

t.Run("should escape $ characters in relabel configs replacement key", func(t *testing.T) {
expectedConfigBytes, err := os.ReadFile("../testdata/relabel_config_expected.yaml")
assert.NoError(t, err)
expectedConfig := string(expectedConfigBytes)

actualConfig, err := ReplaceConfig(param.Instance)
assert.NoError(t, err)

assert.Equal(t, expectedConfig, actualConfig)
})

t.Run("should not modify config when TargetAllocator is disabled", func(t *testing.T) {
param.Instance.Spec.TargetAllocator.Enabled = false
expectedConfigBytes, err := os.ReadFile("../testdata/relabel_config_original.yaml")
assert.NoError(t, err)
expectedConfig := string(expectedConfigBytes)

actualConfig, err := ReplaceConfig(param.Instance)
assert.NoError(t, err)

assert.Equal(t, expectedConfig, actualConfig)
})
}
2 changes: 1 addition & 1 deletion pkg/collector/reconcile/configmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func desiredTAConfigMap(params Params) (corev1.ConfigMap, error) {
labels["app.kubernetes.io/version"] = "latest"
}

promConfig, err := ta.ConfigToPromConfig(params.Instance.Spec.Config)
promConfig, err := ta.ReplaceDollarSignInTAPromConfig(params.Instance.Spec.Config)
if err != nil {
return corev1.ConfigMap{}, err
}
Expand Down
63 changes: 63 additions & 0 deletions pkg/collector/testdata/relabel_config_expected.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
exporters:
logging: null
processors: null
receivers:
prometheus:
config:
global:
scrape_interval: 1m
scrape_timeout: 10s
evaluation_interval: 1m
scrape_configs:
- job_name: service-x
honor_timestamps: true
scrape_interval: 1m
scrape_timeout: 10s
metrics_path: /metrics
scheme: http
follow_redirects: true
enable_http2: true
relabel_configs:
- source_labels: [label1]
separator: ;
regex: (.*)
replacement: $$1
action: keep
- source_labels: [label2]
separator: ;
regex: (.*)
target_label: label3
replacement: $$1_$2
action: replace
- source_labels: [label4]
separator: ;
regex: (.*)
replacement: $$1
action: labelmap
- separator: ;
regex: foo_.*
replacement: $$1
action: labeldrop
metric_relabel_configs:
- source_labels: [label1]
separator: ;
regex: (.*)
replacement: $1
action: keep
- source_labels: [label4]
separator: ;
regex: (.*)
replacement: $$1
action: labelmap
http_sd_configs:
- follow_redirects: false
enable_http2: false
url: http://test-targetallocator:80/jobs/service-x/targets?collector_id=$POD_NAME
service:
pipelines:
metrics:
exporters:
- logging
processors: []
receivers:
- prometheus
54 changes: 54 additions & 0 deletions pkg/collector/testdata/relabel_config_original.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
exporters:
logging: null
processors: null
receivers:
prometheus:
config:
global:
scrape_interval: 1m
scrape_timeout: 10s
evaluation_interval: 1m
scrape_configs:
- job_name: service-x
honor_timestamps: true
scrape_interval: 1m
scrape_timeout: 10s
metrics_path: /metrics
scheme: http
follow_redirects: true
enable_http2: true
relabel_configs:
- source_labels: [label1]
regex: (.*)
action: keep
- source_labels: [label2]
separator: ;
regex: (.*)
target_label: label3
replacement: $$1_$2
action: replace
- source_labels: [label4]
separator: ;
regex: (.*)
replacement: $$1
action: labelmap
- regex: foo_.*
action: labeldrop
metric_relabel_configs:
- source_labels: [label1]
separator: ;
regex: (.*)
replacement: $1
action: keep
- source_labels: [label4]
separator: ;
regex: (.*)
action: labelmap
service:
pipelines:
metrics:
exporters:
- logging
processors: []
receivers:
- prometheus
Loading

0 comments on commit e88ddf8

Please sign in to comment.