1
0
Fork 0
mirror of https://github.com/prometheus-operator/prometheus-operator.git synced 2025-04-16 09:16:38 +00:00
prometheus-operator/pkg/prometheus/promcfg_test.go
Matthias Rampke 76d5211a6c
Avoid CI timeouts in TestConfigGeneration (#3432)
This test generates the same configuration many times, for each
Prometheus version, to see if it is deterministic. As the compatibility
matrix grows, test times increase. Now, this sometimes fails in CI
because Travis kills jobs after 10 minutes of no output.

Run each version as a subtest, and run tests with `-v`, so that output
is produced after each version. This avoids the no-output timeout.

Parallelize testing for each Prometheus version.

When the tests are run with `-short` (as in `make test-unit`), only try
one hundred iterations. With the race detector on, as in that target, this takes
around 5 seconds. Without the race detector, short tests on this
package now run quick enough for fast iteration in an IDE.

Add an additional target and Travis job for running the long tests, but
without the race detector. This brings the run time for the full 1000
iterations per version to under a minute.

Signed-off-by: Matthias Rampke <matthias@rampke.de>
2020-08-28 14:53:32 +02:00

3444 lines
77 KiB
Go

// Copyright 2017 The prometheus-operator Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package prometheus
import (
"bytes"
"fmt"
"testing"
"github.com/go-openapi/swag"
"github.com/kylelemons/godebug/pretty"
monitoringv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
"github.com/prometheus-operator/prometheus-operator/pkg/operator"
yaml "gopkg.in/yaml.v2"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/utils/pointer"
)
func TestConfigGeneration(t *testing.T) {
for _, v := range operator.PrometheusCompatibilityMatrix {
t.Run(v, func(t *testing.T) {
t.Parallel()
cfg, err := generateTestConfig(v)
if err != nil {
t.Fatal(err)
}
reps := 1000
if testing.Short() {
reps = 100
}
for i := 0; i < reps; i++ {
testcfg, err := generateTestConfig(v)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(cfg, testcfg) {
t.Fatalf("Config generation is not deterministic.\n\n\nFirst generation: \n\n%s\n\nDifferent generation: \n\n%s\n\n", string(cfg), string(testcfg))
}
}
})
}
}
func TestGlobalSettings(t *testing.T) {
type testCase struct {
EvaluationInterval string
ScrapeInterval string
ScrapeTimeout string
ExternalLabels map[string]string
QueryLogFile string
Version string
Expected string
}
testcases := []testCase{
{
Version: "v2.15.2",
Expected: `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: /
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs: []
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`,
},
{
Version: "v2.15.2",
EvaluationInterval: "60s",
Expected: `global:
evaluation_interval: 60s
scrape_interval: 30s
external_labels:
prometheus: /
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs: []
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`,
},
{
Version: "v2.15.2",
ScrapeInterval: "60s",
Expected: `global:
evaluation_interval: 30s
scrape_interval: 60s
external_labels:
prometheus: /
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs: []
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`,
},
{
Version: "v2.15.2",
ScrapeTimeout: "30s",
Expected: `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: /
prometheus_replica: $(POD_NAME)
scrape_timeout: 30s
rule_files: []
scrape_configs: []
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`,
},
{
Version: "v2.15.2",
ExternalLabels: map[string]string{
"key1": "value1",
"key2": "value2",
},
Expected: `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
key1: value1
key2: value2
prometheus: /
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs: []
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`,
},
{
Version: "v2.16.0",
QueryLogFile: "test.log",
Expected: `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: /
prometheus_replica: $(POD_NAME)
query_log_file: test.log
rule_files: []
scrape_configs: []
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`,
},
}
for _, tc := range testcases {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{},
Spec: monitoringv1.PrometheusSpec{
EvaluationInterval: tc.EvaluationInterval,
ScrapeInterval: tc.ScrapeInterval,
ScrapeTimeout: tc.ScrapeTimeout,
ExternalLabels: tc.ExternalLabels,
QueryLogFile: tc.QueryLogFile,
Version: tc.Version,
},
},
map[string]*monitoringv1.ServiceMonitor{},
nil,
nil,
map[string]BasicAuthCredentials{},
map[string]BearerToken{},
nil,
nil,
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
result := string(cfg)
if tc.Expected != string(cfg) {
fmt.Println(pretty.Compare(tc.Expected, result))
t.Fatal("expected Prometheus configuration and actual configuration do not match")
}
}
}
func TestNamespaceSetCorrectly(t *testing.T) {
type testCase struct {
ServiceMonitor *monitoringv1.ServiceMonitor
IgnoreNamespaceSelectors bool
Expected string
}
testcases := []testCase{
// Test that namespaces from 'MatchNames' are returned instead of the current namespace
{
ServiceMonitor: &monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testservicemonitor1",
Namespace: "default",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.ServiceMonitorSpec{
NamespaceSelector: monitoringv1.NamespaceSelector{
MatchNames: []string{"test1", "test2"},
},
},
},
IgnoreNamespaceSelectors: false,
Expected: `kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- test1
- test2
`,
},
// Test that 'Any' returns an empty list instead of the current namespace
{
ServiceMonitor: &monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testservicemonitor2",
Namespace: "default",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.ServiceMonitorSpec{
NamespaceSelector: monitoringv1.NamespaceSelector{
Any: true,
},
},
},
IgnoreNamespaceSelectors: false,
Expected: `kubernetes_sd_configs:
- role: endpoints
`,
},
// Test that Any takes precedence over MatchNames
{
ServiceMonitor: &monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testservicemonitor2",
Namespace: "default",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.ServiceMonitorSpec{
NamespaceSelector: monitoringv1.NamespaceSelector{
Any: true,
MatchNames: []string{"foo", "bar"},
},
},
},
IgnoreNamespaceSelectors: false,
Expected: `kubernetes_sd_configs:
- role: endpoints
`,
},
// Test that IgnoreNamespaceSelectors overrides Any and MatchNames
{
ServiceMonitor: &monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testservicemonitor2",
Namespace: "default",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.ServiceMonitorSpec{
NamespaceSelector: monitoringv1.NamespaceSelector{
Any: true,
MatchNames: []string{"foo", "bar"},
},
},
},
IgnoreNamespaceSelectors: true,
Expected: `kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- default
`,
},
}
cg := &configGenerator{}
for _, tc := range testcases {
selectedNamespaces := getNamespacesFromNamespaceSelector(&tc.ServiceMonitor.Spec.NamespaceSelector, tc.ServiceMonitor.Namespace, tc.IgnoreNamespaceSelectors)
c := cg.generateK8SSDConfig(selectedNamespaces, nil, nil, kubernetesSDRoleEndpoint)
s, err := yaml.Marshal(yaml.MapSlice{c})
if err != nil {
t.Fatal(err)
}
if tc.Expected != string(s) {
t.Fatalf("Unexpected result.\n\nGot:\n\n%s\n\nExpected:\n\n%s\n\n", string(s), tc.Expected)
}
}
}
func TestNamespaceSetCorrectlyForPodMonitor(t *testing.T) {
pm := &monitoringv1.PodMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testpodmonitor1",
Namespace: "default",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.PodMonitorSpec{
NamespaceSelector: monitoringv1.NamespaceSelector{
MatchNames: []string{"test"},
},
},
}
cg := &configGenerator{}
selectedNamespaces := getNamespacesFromNamespaceSelector(&pm.Spec.NamespaceSelector, pm.Namespace, false)
c := cg.generateK8SSDConfig(selectedNamespaces, nil, nil, kubernetesSDRolePod)
s, err := yaml.Marshal(yaml.MapSlice{c})
if err != nil {
t.Fatal(err)
}
expected := `kubernetes_sd_configs:
- role: pod
namespaces:
names:
- test
`
result := string(s)
if expected != result {
t.Fatalf("Unexpected result.\n\nGot:\n\n%s\n\nExpected:\n\n%s\n\n", result, expected)
}
}
func TestProbeStaticTargetsConfigGeneration(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.PrometheusSpec{
ProbeSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group1",
},
},
},
},
nil,
nil,
map[string]*monitoringv1.Probe{
"probe1": &monitoringv1.Probe{
ObjectMeta: metav1.ObjectMeta{
Name: "testprobe1",
Namespace: "default",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.ProbeSpec{
ProberSpec: monitoringv1.ProberSpec{
Scheme: "http",
URL: "blackbox.exporter.io",
Path: "/probe",
},
Module: "http_2xx",
Targets: monitoringv1.ProbeTargets{
StaticConfig: &monitoringv1.ProbeTargetStaticConfig{
Targets: []string{
"prometheus.io",
"promcon.io",
},
Labels: map[string]string{
"static": "label",
},
},
},
},
},
},
map[string]BasicAuthCredentials{},
nil,
nil,
nil,
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: default/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs:
- job_name: default/testprobe1
honor_timestamps: true
metrics_path: /probe
scheme: http
params:
module:
- http_2xx
static_configs:
- targets:
- prometheus.io
- promcon.io
labels:
static: label
relabel_configs:
- source_labels:
- __address__
target_label: __param_target
- source_labels:
- __param_target
target_label: instance
- target_label: __address__
replacement: blackbox.exporter.io
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`
result := string(cfg)
if expected != result {
t.Fatalf("Unexpected result.\n\nGot:\n\n%s\n\nExpected:\n\n%s\n\n", result, expected)
}
}
func TestProbeStaticTargetsConfigGenerationWithLabelEnforce(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.PrometheusSpec{
EnforcedNamespaceLabel: "namespace",
ProbeSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group1",
},
},
},
},
nil,
nil,
map[string]*monitoringv1.Probe{
"probe1": &monitoringv1.Probe{
ObjectMeta: metav1.ObjectMeta{
Name: "testprobe1",
Namespace: "default",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.ProbeSpec{
ProberSpec: monitoringv1.ProberSpec{
Scheme: "http",
URL: "blackbox.exporter.io",
Path: "/probe",
},
Module: "http_2xx",
Targets: monitoringv1.ProbeTargets{
StaticConfig: &monitoringv1.ProbeTargetStaticConfig{
Targets: []string{
"prometheus.io",
"promcon.io",
},
Labels: map[string]string{
"static": "label",
},
},
},
},
},
},
map[string]BasicAuthCredentials{},
nil,
nil,
nil,
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: default/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs:
- job_name: default/testprobe1
honor_timestamps: true
metrics_path: /probe
scheme: http
params:
module:
- http_2xx
static_configs:
- targets:
- prometheus.io
- promcon.io
labels:
static: label
relabel_configs:
- source_labels:
- __address__
target_label: __param_target
- source_labels:
- __param_target
target_label: instance
- target_label: __address__
replacement: blackbox.exporter.io
- target_label: namespace
replacement: default
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`
result := string(cfg)
if expected != result {
t.Fatalf("Unexpected result.\n\nGot:\n\n%s\n\nExpected:\n\n%s\n\n", result, expected)
}
}
func TestProbeStaticTargetsConfigGenerationWithJobName(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.PrometheusSpec{
ProbeSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group1",
},
},
},
},
nil,
nil,
map[string]*monitoringv1.Probe{
"probe1": &monitoringv1.Probe{
ObjectMeta: metav1.ObjectMeta{
Name: "testprobe1",
Namespace: "default",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.ProbeSpec{
JobName: "blackbox",
ProberSpec: monitoringv1.ProberSpec{
Scheme: "http",
URL: "blackbox.exporter.io",
Path: "/probe",
},
Module: "http_2xx",
Targets: monitoringv1.ProbeTargets{
StaticConfig: &monitoringv1.ProbeTargetStaticConfig{
Targets: []string{
"prometheus.io",
"promcon.io",
},
Labels: map[string]string{
"static": "label",
},
},
},
},
},
},
map[string]BasicAuthCredentials{},
nil,
nil,
nil,
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: default/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs:
- job_name: blackbox
honor_timestamps: true
metrics_path: /probe
scheme: http
params:
module:
- http_2xx
static_configs:
- targets:
- prometheus.io
- promcon.io
labels:
static: label
relabel_configs:
- source_labels:
- __address__
target_label: __param_target
- source_labels:
- __param_target
target_label: instance
- target_label: __address__
replacement: blackbox.exporter.io
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`
result := string(cfg)
if expected != result {
t.Fatalf("Unexpected result.\n\nGot:\n\n%s\n\nExpected:\n\n%s\n\n", result, expected)
}
}
func TestProbeIngressSDConfigGeneration(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.PrometheusSpec{
ProbeSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group1",
},
},
},
},
nil,
nil,
map[string]*monitoringv1.Probe{
"probe1": &monitoringv1.Probe{
ObjectMeta: metav1.ObjectMeta{
Name: "testprobe1",
Namespace: "default",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.ProbeSpec{
ProberSpec: monitoringv1.ProberSpec{
Scheme: "http",
URL: "blackbox.exporter.io",
Path: "/probe",
},
Module: "http_2xx",
Targets: monitoringv1.ProbeTargets{
Ingress: &monitoringv1.ProbeTargetIngress{
Selector: metav1.LabelSelector{
MatchLabels: map[string]string{
"prometheus.io/probe": "true",
},
},
NamespaceSelector: monitoringv1.NamespaceSelector{
Any: true,
},
RelabelConfigs: []*monitoringv1.RelabelConfig{
{
TargetLabel: "foo",
Replacement: "bar",
Action: "replace",
},
},
},
},
},
},
},
map[string]BasicAuthCredentials{},
nil,
nil,
nil,
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: default/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs:
- job_name: default/testprobe1
honor_timestamps: true
metrics_path: /probe
scheme: http
params:
module:
- http_2xx
kubernetes_sd_configs:
- role: ingress
relabel_configs:
- action: keep
source_labels:
- __meta_kubernetes_ingress_label_prometheus_io_probe
regex: "true"
- source_labels:
- __meta_kubernetes_ingress_scheme
- __address__
- __meta_kubernetes_ingress_path
separator: ;
regex: (.+);(.+);(.+)
target_label: __param_target
replacement: ${1}://${2}${3}
action: replace
- source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- source_labels:
- __meta_kubernetes_ingress_name
target_label: ingress
- source_labels:
- __param_target
target_label: instance
- target_label: __address__
replacement: blackbox.exporter.io
- target_label: foo
replacement: bar
action: replace
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`
result := string(cfg)
if expected != result {
t.Fatalf("Unexpected result.\n\nGot:\n\n%s\n\nExpected:\n\n%s\n\n", result, expected)
}
}
func TestProbeIngressSDConfigGenerationWithLabelEnforce(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.PrometheusSpec{
EnforcedNamespaceLabel: "namespace",
ProbeSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group1",
},
},
},
},
nil,
nil,
map[string]*monitoringv1.Probe{
"probe1": &monitoringv1.Probe{
ObjectMeta: metav1.ObjectMeta{
Name: "testprobe1",
Namespace: "default",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.ProbeSpec{
ProberSpec: monitoringv1.ProberSpec{
Scheme: "http",
URL: "blackbox.exporter.io",
Path: "/probe",
},
Module: "http_2xx",
Targets: monitoringv1.ProbeTargets{
Ingress: &monitoringv1.ProbeTargetIngress{
Selector: metav1.LabelSelector{
MatchLabels: map[string]string{
"prometheus.io/probe": "true",
},
},
NamespaceSelector: monitoringv1.NamespaceSelector{
Any: true,
},
RelabelConfigs: []*monitoringv1.RelabelConfig{
{
TargetLabel: "foo",
Replacement: "bar",
Action: "replace",
},
},
},
},
},
},
},
map[string]BasicAuthCredentials{},
nil,
nil,
nil,
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: default/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs:
- job_name: default/testprobe1
honor_timestamps: true
metrics_path: /probe
scheme: http
params:
module:
- http_2xx
kubernetes_sd_configs:
- role: ingress
relabel_configs:
- action: keep
source_labels:
- __meta_kubernetes_ingress_label_prometheus_io_probe
regex: "true"
- source_labels:
- __meta_kubernetes_ingress_scheme
- __address__
- __meta_kubernetes_ingress_path
separator: ;
regex: (.+);(.+);(.+)
target_label: __param_target
replacement: ${1}://${2}${3}
action: replace
- source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- source_labels:
- __meta_kubernetes_ingress_name
target_label: ingress
- source_labels:
- __param_target
target_label: instance
- target_label: __address__
replacement: blackbox.exporter.io
- target_label: foo
replacement: bar
action: replace
- target_label: namespace
replacement: default
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`
result := string(cfg)
if expected != result {
t.Fatalf("Unexpected result.\n\nGot:\n\n%s\n\nExpected:\n\n%s\n\n", result, expected)
}
}
func TestK8SSDConfigGeneration(t *testing.T) {
sm := &monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testservicemonitor1",
Namespace: "default",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.ServiceMonitorSpec{
NamespaceSelector: monitoringv1.NamespaceSelector{
MatchNames: []string{"test"},
},
},
}
cg := &configGenerator{}
testcases := []struct {
apiserverConfig *monitoringv1.APIServerConfig
basicAuthSecrets map[string]BasicAuthCredentials
expected string
}{
{
nil,
nil,
`kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- test
`,
},
{
&monitoringv1.APIServerConfig{
Host: "example.com",
BasicAuth: &monitoringv1.BasicAuth{},
BearerToken: "bearer_token",
BearerTokenFile: "bearer_token_file",
TLSConfig: nil,
},
map[string]BasicAuthCredentials{
"apiserver": {
"foo",
"bar",
},
},
`kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- test
api_server: example.com
basic_auth:
username: foo
password: bar
bearer_token: bearer_token
bearer_token_file: bearer_token_file
`,
},
}
for _, tc := range testcases {
c := cg.generateK8SSDConfig(
getNamespacesFromNamespaceSelector(&sm.Spec.NamespaceSelector, sm.Namespace, false),
tc.apiserverConfig,
tc.basicAuthSecrets,
kubernetesSDRoleEndpoint,
)
s, err := yaml.Marshal(yaml.MapSlice{c})
if err != nil {
t.Fatal(err)
}
result := string(s)
if result != tc.expected {
t.Fatalf("Unexpected result.\n\nGot:\n\n%s\n\nExpected:\n\n%s\n\n", result, tc.expected)
}
}
}
func TestAlertmanagerBearerToken(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.PrometheusSpec{
Alerting: &monitoringv1.AlertingSpec{
Alertmanagers: []monitoringv1.AlertmanagerEndpoints{
{
Name: "alertmanager-main",
Namespace: "default",
Port: intstr.FromString("web"),
BearerTokenFile: "/some/file/on/disk",
},
},
},
},
},
nil,
nil,
nil,
map[string]BasicAuthCredentials{},
map[string]BearerToken{},
nil,
nil,
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
// If this becomes an endless sink of maintenance, then we should just
// change this to check that just the `bearer_token_file` is set with
// something like json-path.
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: default/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs: []
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers:
- path_prefix: /
scheme: http
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- default
bearer_token_file: /some/file/on/disk
relabel_configs:
- action: keep
source_labels:
- __meta_kubernetes_service_name
regex: alertmanager-main
- action: keep
source_labels:
- __meta_kubernetes_endpoint_port_name
regex: web
`
result := string(cfg)
if expected != result {
fmt.Println(pretty.Compare(expected, result))
t.Fatal("expected Prometheus configuration and actual configuration do not match")
}
}
func TestAlertmanagerAPIVersion(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.PrometheusSpec{
Version: "v2.11.0",
Alerting: &monitoringv1.AlertingSpec{
Alertmanagers: []monitoringv1.AlertmanagerEndpoints{
{
Name: "alertmanager-main",
Namespace: "default",
Port: intstr.FromString("web"),
APIVersion: "v2",
},
},
},
},
},
nil,
nil,
nil,
map[string]BasicAuthCredentials{},
map[string]BearerToken{},
nil,
nil,
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
// If this becomes an endless sink of maintenance, then we should just
// change this to check that just the `api_version` is set with
// something like json-path.
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: default/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs: []
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers:
- path_prefix: /
scheme: http
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- default
api_version: v2
relabel_configs:
- action: keep
source_labels:
- __meta_kubernetes_service_name
regex: alertmanager-main
- action: keep
source_labels:
- __meta_kubernetes_endpoint_port_name
regex: web
`
result := string(cfg)
if expected != result {
fmt.Println(pretty.Compare(expected, result))
t.Fatal("expected Prometheus configuration and actual configuration do not match")
}
}
func TestAlertmanagerTimeoutConfig(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.PrometheusSpec{
Version: "v2.11.0",
Alerting: &monitoringv1.AlertingSpec{
Alertmanagers: []monitoringv1.AlertmanagerEndpoints{
{
Name: "alertmanager-main",
Namespace: "default",
Port: intstr.FromString("web"),
APIVersion: "v2",
Timeout: pointer.StringPtr("60s"),
},
},
},
},
},
nil,
nil,
nil,
map[string]BasicAuthCredentials{},
map[string]BearerToken{},
nil,
nil,
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
// If this becomes an endless sink of maintenance, then we should just
// change this to check that just the `api_version` is set with
// something like json-path.
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: default/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs: []
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers:
- path_prefix: /
scheme: http
timeout: 60s
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- default
api_version: v2
relabel_configs:
- action: keep
source_labels:
- __meta_kubernetes_service_name
regex: alertmanager-main
- action: keep
source_labels:
- __meta_kubernetes_endpoint_port_name
regex: web
`
result := string(cfg)
if expected != result {
fmt.Println(pretty.Compare(expected, result))
t.Fatal("expected Prometheus configuration and actual configuration do not match")
}
}
func TestAdditionalAlertRelabelConfigs(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.PrometheusSpec{
Alerting: &monitoringv1.AlertingSpec{
Alertmanagers: []monitoringv1.AlertmanagerEndpoints{
{
Name: "alertmanager-main",
Namespace: "default",
Port: intstr.FromString("web"),
},
},
},
},
},
nil,
nil,
nil,
map[string]BasicAuthCredentials{},
map[string]BearerToken{},
nil,
[]byte(`- action: drop
source_labels: [__meta_kubernetes_node_name]
regex: spot-(.+)
`),
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: default/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs: []
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
- action: drop
source_labels:
- __meta_kubernetes_node_name
regex: spot-(.+)
alertmanagers:
- path_prefix: /
scheme: http
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- default
relabel_configs:
- action: keep
source_labels:
- __meta_kubernetes_service_name
regex: alertmanager-main
- action: keep
source_labels:
- __meta_kubernetes_endpoint_port_name
regex: web
`
result := string(cfg)
if expected != result {
fmt.Println(pretty.Compare(expected, result))
t.Fatal("expected Prometheus configuration and actual configuration do not match")
}
}
func TestNoEnforcedNamespaceLabelServiceMonitor(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "ns-value",
},
Spec: monitoringv1.PrometheusSpec{},
},
map[string]*monitoringv1.ServiceMonitor{
"test": &monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.ServiceMonitorSpec{
Selector: metav1.LabelSelector{
MatchLabels: map[string]string{
"foo": "bar",
},
},
Endpoints: []monitoringv1.Endpoint{
{
Port: "https-metrics",
HonorLabels: true,
Interval: "30s",
MetricRelabelConfigs: []*monitoringv1.RelabelConfig{
{
Action: "drop",
Regex: "container_(network_tcp_usage_total|network_udp_usage_total|tasks_state|cpu_load_average_10s)",
SourceLabels: []string{"__name__"},
},
},
RelabelConfigs: []*monitoringv1.RelabelConfig{
{
Action: "replace",
Regex: "(.+)(?::d+)",
Replacement: "$1:9537",
SourceLabels: []string{"__address__"},
TargetLabel: "__address__",
},
{
Action: "replace",
Replacement: "crio",
TargetLabel: "job",
},
},
},
},
},
},
},
nil,
nil,
map[string]BasicAuthCredentials{},
map[string]BearerToken{},
nil,
nil,
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: ns-value/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs:
- job_name: default/test/0
honor_labels: true
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- default
scrape_interval: 30s
relabel_configs:
- action: keep
source_labels:
- __meta_kubernetes_service_label_foo
regex: bar
- action: keep
source_labels:
- __meta_kubernetes_endpoint_port_name
regex: https-metrics
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Node;(.*)
replacement: ${1}
target_label: node
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Pod;(.*)
replacement: ${1}
target_label: pod
- source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- source_labels:
- __meta_kubernetes_service_name
target_label: service
- source_labels:
- __meta_kubernetes_pod_name
target_label: pod
- source_labels:
- __meta_kubernetes_pod_container_name
target_label: container
- source_labels:
- __meta_kubernetes_service_name
target_label: job
replacement: ${1}
- target_label: endpoint
replacement: https-metrics
- source_labels:
- __address__
target_label: __address__
regex: (.+)(?::d+)
replacement: $1:9537
action: replace
- target_label: job
replacement: crio
action: replace
metric_relabel_configs:
- source_labels:
- __name__
regex: container_(network_tcp_usage_total|network_udp_usage_total|tasks_state|cpu_load_average_10s)
action: drop
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`
result := string(cfg)
if expected != result {
fmt.Println(pretty.Compare(expected, result))
t.Fatal("expected Prometheus configuration and actual configuration do not match")
}
}
func TestEnforcedNamespaceLabelPodMonitor(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "ns-value",
},
Spec: monitoringv1.PrometheusSpec{
EnforcedNamespaceLabel: "ns-key",
},
},
nil,
map[string]*monitoringv1.PodMonitor{
"testpodmonitor1": {
ObjectMeta: metav1.ObjectMeta{
Name: "testpodmonitor1",
Namespace: "pod-monitor-ns",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.PodMonitorSpec{
PodTargetLabels: []string{"example", "env"},
PodMetricsEndpoints: []monitoringv1.PodMetricsEndpoint{
{
Port: "web",
Interval: "30s",
MetricRelabelConfigs: []*monitoringv1.RelabelConfig{
{
Action: "drop",
Regex: "my-job-pod-.+",
SourceLabels: []string{"pod_name"},
TargetLabel: "my-ns",
},
},
RelabelConfigs: []*monitoringv1.RelabelConfig{
{
Action: "replace",
Regex: "(.*)",
Replacement: "$1",
SourceLabels: []string{"__meta_kubernetes_pod_ready"},
},
},
},
},
},
},
},
nil,
map[string]BasicAuthCredentials{},
map[string]BearerToken{},
nil,
nil,
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: ns-value/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs:
- job_name: pod-monitor-ns/testpodmonitor1/0
honor_labels: false
kubernetes_sd_configs:
- role: pod
namespaces:
names:
- pod-monitor-ns
scrape_interval: 30s
relabel_configs:
- action: keep
source_labels:
- __meta_kubernetes_pod_container_port_name
regex: web
- source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- source_labels:
- __meta_kubernetes_pod_container_name
target_label: container
- source_labels:
- __meta_kubernetes_pod_name
target_label: pod
- source_labels:
- __meta_kubernetes_pod_label_example
target_label: example
regex: (.+)
replacement: ${1}
- source_labels:
- __meta_kubernetes_pod_label_env
target_label: env
regex: (.+)
replacement: ${1}
- target_label: job
replacement: pod-monitor-ns/testpodmonitor1
- target_label: endpoint
replacement: web
- source_labels:
- __meta_kubernetes_pod_ready
regex: (.*)
replacement: $1
action: replace
- target_label: ns-key
replacement: pod-monitor-ns
metric_relabel_configs:
- source_labels:
- pod_name
target_label: my-ns
regex: my-job-pod-.+
action: drop
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`
result := string(cfg)
if expected != result {
fmt.Println(pretty.Compare(expected, result))
t.Fatal("expected Prometheus configuration and actual configuration do not match")
}
}
func TestEnforcedNamespaceLabelServiceMonitor(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "ns-value",
},
Spec: monitoringv1.PrometheusSpec{
EnforcedNamespaceLabel: "ns-key",
},
},
map[string]*monitoringv1.ServiceMonitor{
"test": &monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.ServiceMonitorSpec{
Selector: metav1.LabelSelector{
MatchLabels: map[string]string{
"foo": "bar",
},
},
Endpoints: []monitoringv1.Endpoint{
{
Port: "web",
Interval: "30s",
MetricRelabelConfigs: []*monitoringv1.RelabelConfig{
{
Action: "drop",
Regex: "my-job-pod-.+",
SourceLabels: []string{"pod_name"},
TargetLabel: "ns-key",
},
},
RelabelConfigs: []*monitoringv1.RelabelConfig{
{
Action: "replace",
Regex: "(.*)",
Replacement: "$1",
SourceLabels: []string{"__meta_kubernetes_pod_ready"},
},
},
},
},
},
},
},
nil,
nil,
map[string]BasicAuthCredentials{},
map[string]BearerToken{},
nil,
nil,
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: ns-value/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs:
- job_name: default/test/0
honor_labels: false
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- default
scrape_interval: 30s
relabel_configs:
- action: keep
source_labels:
- __meta_kubernetes_service_label_foo
regex: bar
- action: keep
source_labels:
- __meta_kubernetes_endpoint_port_name
regex: web
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Node;(.*)
replacement: ${1}
target_label: node
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Pod;(.*)
replacement: ${1}
target_label: pod
- source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- source_labels:
- __meta_kubernetes_service_name
target_label: service
- source_labels:
- __meta_kubernetes_pod_name
target_label: pod
- source_labels:
- __meta_kubernetes_pod_container_name
target_label: container
- source_labels:
- __meta_kubernetes_service_name
target_label: job
replacement: ${1}
- target_label: endpoint
replacement: web
- source_labels:
- __meta_kubernetes_pod_ready
regex: (.*)
replacement: $1
action: replace
- target_label: ns-key
replacement: default
metric_relabel_configs: []
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`
result := string(cfg)
if expected != result {
fmt.Println(pretty.Compare(expected, result))
t.Fatal("expected Prometheus configuration and actual configuration do not match for enforced namespace label test")
}
}
func TestAdditionalAlertmanagers(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.PrometheusSpec{
Alerting: &monitoringv1.AlertingSpec{
Alertmanagers: []monitoringv1.AlertmanagerEndpoints{
{
Name: "alertmanager-main",
Namespace: "default",
Port: intstr.FromString("web"),
},
},
},
},
},
nil,
nil,
nil,
map[string]BasicAuthCredentials{},
map[string]BearerToken{},
nil,
nil,
[]byte(`- static_configs:
- targets:
- localhost
`),
nil,
)
if err != nil {
t.Fatal(err)
}
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: default/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs: []
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers:
- path_prefix: /
scheme: http
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- default
relabel_configs:
- action: keep
source_labels:
- __meta_kubernetes_service_name
regex: alertmanager-main
- action: keep
source_labels:
- __meta_kubernetes_endpoint_port_name
regex: web
- static_configs:
- targets:
- localhost
`
result := string(cfg)
if expected != result {
fmt.Println(pretty.Compare(expected, result))
t.Fatal("expected Prometheus configuration and actual configuration do not match")
}
}
func TestSettingHonorTimestampsInServiceMonitor(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.PrometheusSpec{
Version: "v2.9.0",
ServiceMonitorSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group1",
},
},
},
},
map[string]*monitoringv1.ServiceMonitor{
"testservicemonitor1": &monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testservicemonitor1",
Namespace: "default",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.ServiceMonitorSpec{
TargetLabels: []string{"example", "env"},
Endpoints: []monitoringv1.Endpoint{
{
HonorTimestamps: swag.Bool(false),
Port: "web",
Interval: "30s",
},
},
},
},
},
nil,
nil,
map[string]BasicAuthCredentials{},
map[string]BearerToken{},
nil,
nil,
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: default/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs:
- job_name: default/testservicemonitor1/0
honor_labels: false
honor_timestamps: false
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- default
scrape_interval: 30s
relabel_configs:
- action: keep
source_labels:
- __meta_kubernetes_endpoint_port_name
regex: web
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Node;(.*)
replacement: ${1}
target_label: node
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Pod;(.*)
replacement: ${1}
target_label: pod
- source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- source_labels:
- __meta_kubernetes_service_name
target_label: service
- source_labels:
- __meta_kubernetes_pod_name
target_label: pod
- source_labels:
- __meta_kubernetes_pod_container_name
target_label: container
- source_labels:
- __meta_kubernetes_service_label_example
target_label: example
regex: (.+)
replacement: ${1}
- source_labels:
- __meta_kubernetes_service_label_env
target_label: env
regex: (.+)
replacement: ${1}
- source_labels:
- __meta_kubernetes_service_name
target_label: job
replacement: ${1}
- target_label: endpoint
replacement: web
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`
result := string(cfg)
if expected != result {
fmt.Println(pretty.Compare(expected, result))
t.Fatal("expected Prometheus configuration and actual configuration do not match")
}
}
func TestSettingHonorTimestampsInPodMonitor(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.PrometheusSpec{
Version: "v2.9.0",
ServiceMonitorSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group1",
},
},
},
},
nil,
map[string]*monitoringv1.PodMonitor{
"testpodmonitor1": {
ObjectMeta: metav1.ObjectMeta{
Name: "testpodmonitor1",
Namespace: "default",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.PodMonitorSpec{
PodTargetLabels: []string{"example", "env"},
PodMetricsEndpoints: []monitoringv1.PodMetricsEndpoint{
{
HonorTimestamps: swag.Bool(false),
Port: "web",
Interval: "30s",
},
},
},
},
},
nil,
map[string]BasicAuthCredentials{},
map[string]BearerToken{},
nil,
nil,
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: default/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs:
- job_name: default/testpodmonitor1/0
honor_labels: false
honor_timestamps: false
kubernetes_sd_configs:
- role: pod
namespaces:
names:
- default
scrape_interval: 30s
relabel_configs:
- action: keep
source_labels:
- __meta_kubernetes_pod_container_port_name
regex: web
- source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- source_labels:
- __meta_kubernetes_pod_container_name
target_label: container
- source_labels:
- __meta_kubernetes_pod_name
target_label: pod
- source_labels:
- __meta_kubernetes_pod_label_example
target_label: example
regex: (.+)
replacement: ${1}
- source_labels:
- __meta_kubernetes_pod_label_env
target_label: env
regex: (.+)
replacement: ${1}
- target_label: job
replacement: default/testpodmonitor1
- target_label: endpoint
replacement: web
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`
result := string(cfg)
if expected != result {
fmt.Println(pretty.Compare(expected, result))
t.Fatal("expected Prometheus configuration and actual configuration do not match")
}
}
func TestHonorTimestampsOverriding(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.PrometheusSpec{
Version: "v2.9.0",
OverrideHonorTimestamps: true,
ServiceMonitorSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group1",
},
},
},
},
map[string]*monitoringv1.ServiceMonitor{
"testservicemonitor1": &monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testservicemonitor1",
Namespace: "default",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.ServiceMonitorSpec{
TargetLabels: []string{"example", "env"},
Endpoints: []monitoringv1.Endpoint{
{
HonorTimestamps: swag.Bool(true),
Port: "web",
Interval: "30s",
},
},
},
},
},
nil,
nil,
map[string]BasicAuthCredentials{},
map[string]BearerToken{},
nil,
nil,
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: default/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs:
- job_name: default/testservicemonitor1/0
honor_labels: false
honor_timestamps: false
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- default
scrape_interval: 30s
relabel_configs:
- action: keep
source_labels:
- __meta_kubernetes_endpoint_port_name
regex: web
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Node;(.*)
replacement: ${1}
target_label: node
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Pod;(.*)
replacement: ${1}
target_label: pod
- source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- source_labels:
- __meta_kubernetes_service_name
target_label: service
- source_labels:
- __meta_kubernetes_pod_name
target_label: pod
- source_labels:
- __meta_kubernetes_pod_container_name
target_label: container
- source_labels:
- __meta_kubernetes_service_label_example
target_label: example
regex: (.+)
replacement: ${1}
- source_labels:
- __meta_kubernetes_service_label_env
target_label: env
regex: (.+)
replacement: ${1}
- source_labels:
- __meta_kubernetes_service_name
target_label: job
replacement: ${1}
- target_label: endpoint
replacement: web
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`
result := string(cfg)
if expected != result {
fmt.Println(pretty.Compare(expected, result))
t.Fatal("expected Prometheus configuration and actual configuration do not match")
}
}
func TestSettingHonorLabels(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.PrometheusSpec{
ServiceMonitorSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group1",
},
},
},
},
map[string]*monitoringv1.ServiceMonitor{
"testservicemonitor1": &monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testservicemonitor1",
Namespace: "default",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.ServiceMonitorSpec{
TargetLabels: []string{"example", "env"},
Endpoints: []monitoringv1.Endpoint{
{
HonorLabels: true,
Port: "web",
Interval: "30s",
},
},
},
},
},
nil,
nil,
map[string]BasicAuthCredentials{},
map[string]BearerToken{},
nil,
nil,
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: default/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs:
- job_name: default/testservicemonitor1/0
honor_labels: true
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- default
scrape_interval: 30s
relabel_configs:
- action: keep
source_labels:
- __meta_kubernetes_endpoint_port_name
regex: web
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Node;(.*)
replacement: ${1}
target_label: node
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Pod;(.*)
replacement: ${1}
target_label: pod
- source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- source_labels:
- __meta_kubernetes_service_name
target_label: service
- source_labels:
- __meta_kubernetes_pod_name
target_label: pod
- source_labels:
- __meta_kubernetes_pod_container_name
target_label: container
- source_labels:
- __meta_kubernetes_service_label_example
target_label: example
regex: (.+)
replacement: ${1}
- source_labels:
- __meta_kubernetes_service_label_env
target_label: env
regex: (.+)
replacement: ${1}
- source_labels:
- __meta_kubernetes_service_name
target_label: job
replacement: ${1}
- target_label: endpoint
replacement: web
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`
result := string(cfg)
if expected != result {
fmt.Println(pretty.Compare(expected, result))
t.Fatal("expected Prometheus configuration and actual configuration do not match")
}
}
func TestHonorLabelsOverriding(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.PrometheusSpec{
OverrideHonorLabels: true,
ServiceMonitorSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group1",
},
},
},
},
map[string]*monitoringv1.ServiceMonitor{
"testservicemonitor1": &monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testservicemonitor1",
Namespace: "default",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.ServiceMonitorSpec{
TargetLabels: []string{"example", "env"},
Endpoints: []monitoringv1.Endpoint{
{
HonorLabels: true,
Port: "web",
Interval: "30s",
},
},
},
},
},
nil,
nil,
map[string]BasicAuthCredentials{},
map[string]BearerToken{},
nil,
nil,
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: default/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs:
- job_name: default/testservicemonitor1/0
honor_labels: false
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- default
scrape_interval: 30s
relabel_configs:
- action: keep
source_labels:
- __meta_kubernetes_endpoint_port_name
regex: web
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Node;(.*)
replacement: ${1}
target_label: node
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Pod;(.*)
replacement: ${1}
target_label: pod
- source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- source_labels:
- __meta_kubernetes_service_name
target_label: service
- source_labels:
- __meta_kubernetes_pod_name
target_label: pod
- source_labels:
- __meta_kubernetes_pod_container_name
target_label: container
- source_labels:
- __meta_kubernetes_service_label_example
target_label: example
regex: (.+)
replacement: ${1}
- source_labels:
- __meta_kubernetes_service_label_env
target_label: env
regex: (.+)
replacement: ${1}
- source_labels:
- __meta_kubernetes_service_name
target_label: job
replacement: ${1}
- target_label: endpoint
replacement: web
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`
result := string(cfg)
if expected != result {
fmt.Println(pretty.Compare(expected, result))
t.Fatal("expected Prometheus configuration and actual configuration do not match")
}
}
func TestTargetLabels(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.PrometheusSpec{
OverrideHonorLabels: false,
ServiceMonitorSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group1",
},
},
},
},
map[string]*monitoringv1.ServiceMonitor{
"testservicemonitor1": &monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testservicemonitor1",
Namespace: "default",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.ServiceMonitorSpec{
TargetLabels: []string{"example", "env"},
Endpoints: []monitoringv1.Endpoint{
{
Port: "web",
Interval: "30s",
},
},
},
},
},
nil,
nil,
map[string]BasicAuthCredentials{},
map[string]BearerToken{},
nil,
nil,
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: default/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs:
- job_name: default/testservicemonitor1/0
honor_labels: false
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- default
scrape_interval: 30s
relabel_configs:
- action: keep
source_labels:
- __meta_kubernetes_endpoint_port_name
regex: web
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Node;(.*)
replacement: ${1}
target_label: node
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Pod;(.*)
replacement: ${1}
target_label: pod
- source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- source_labels:
- __meta_kubernetes_service_name
target_label: service
- source_labels:
- __meta_kubernetes_pod_name
target_label: pod
- source_labels:
- __meta_kubernetes_pod_container_name
target_label: container
- source_labels:
- __meta_kubernetes_service_label_example
target_label: example
regex: (.+)
replacement: ${1}
- source_labels:
- __meta_kubernetes_service_label_env
target_label: env
regex: (.+)
replacement: ${1}
- source_labels:
- __meta_kubernetes_service_name
target_label: job
replacement: ${1}
- target_label: endpoint
replacement: web
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`
result := string(cfg)
if expected != result {
fmt.Println(pretty.Compare(expected, result))
t.Fatal("expected Prometheus configuration and actual configuration do not match")
}
}
func TestPodTargetLabels(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.PrometheusSpec{
ServiceMonitorSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group1",
},
},
},
},
map[string]*monitoringv1.ServiceMonitor{
"testservicemonitor1": &monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testservicemonitor1",
Namespace: "default",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.ServiceMonitorSpec{
PodTargetLabels: []string{"example", "env"},
Endpoints: []monitoringv1.Endpoint{
{
Port: "web",
Interval: "30s",
},
},
},
},
},
nil,
nil,
map[string]BasicAuthCredentials{},
map[string]BearerToken{},
nil,
nil,
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: default/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs:
- job_name: default/testservicemonitor1/0
honor_labels: false
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- default
scrape_interval: 30s
relabel_configs:
- action: keep
source_labels:
- __meta_kubernetes_endpoint_port_name
regex: web
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Node;(.*)
replacement: ${1}
target_label: node
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Pod;(.*)
replacement: ${1}
target_label: pod
- source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- source_labels:
- __meta_kubernetes_service_name
target_label: service
- source_labels:
- __meta_kubernetes_pod_name
target_label: pod
- source_labels:
- __meta_kubernetes_pod_container_name
target_label: container
- source_labels:
- __meta_kubernetes_pod_label_example
target_label: example
regex: (.+)
replacement: ${1}
- source_labels:
- __meta_kubernetes_pod_label_env
target_label: env
regex: (.+)
replacement: ${1}
- source_labels:
- __meta_kubernetes_service_name
target_label: job
replacement: ${1}
- target_label: endpoint
replacement: web
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`
result := string(cfg)
if expected != result {
fmt.Println(pretty.Compare(expected, result))
t.Fatal("expected Prometheus configuration and actual configuration do not match")
}
}
func TestPodTargetLabelsFromPodMonitor(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.PrometheusSpec{
ServiceMonitorSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group1",
},
},
},
},
nil,
map[string]*monitoringv1.PodMonitor{
"testpodmonitor1": {
ObjectMeta: metav1.ObjectMeta{
Name: "testpodmonitor1",
Namespace: "default",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.PodMonitorSpec{
PodTargetLabels: []string{"example", "env"},
PodMetricsEndpoints: []monitoringv1.PodMetricsEndpoint{
{
Port: "web",
Interval: "30s",
},
},
},
},
},
nil,
map[string]BasicAuthCredentials{},
map[string]BearerToken{},
nil,
nil,
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: default/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs:
- job_name: default/testpodmonitor1/0
honor_labels: false
kubernetes_sd_configs:
- role: pod
namespaces:
names:
- default
scrape_interval: 30s
relabel_configs:
- action: keep
source_labels:
- __meta_kubernetes_pod_container_port_name
regex: web
- source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- source_labels:
- __meta_kubernetes_pod_container_name
target_label: container
- source_labels:
- __meta_kubernetes_pod_name
target_label: pod
- source_labels:
- __meta_kubernetes_pod_label_example
target_label: example
regex: (.+)
replacement: ${1}
- source_labels:
- __meta_kubernetes_pod_label_env
target_label: env
regex: (.+)
replacement: ${1}
- target_label: job
replacement: default/testpodmonitor1
- target_label: endpoint
replacement: web
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`
result := string(cfg)
if expected != result {
fmt.Println(pretty.Compare(expected, result))
t.Fatal("expected Prometheus configuration and actual configuration do not match")
}
}
func TestEmptyEndointPorts(t *testing.T) {
cg := &configGenerator{}
cfg, err := cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
},
map[string]*monitoringv1.ServiceMonitor{
"test": &monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.ServiceMonitorSpec{
Selector: metav1.LabelSelector{
MatchLabels: map[string]string{
"foo": "bar",
},
},
Endpoints: []monitoringv1.Endpoint{
// Add a single endpoint with empty configuration.
{},
},
},
},
},
nil,
nil,
map[string]BasicAuthCredentials{},
map[string]BearerToken{},
nil,
nil,
nil,
nil,
)
if err != nil {
t.Fatal(err)
}
// If this becomes an endless sink of maintenance, then we should just
// change this to check that just the `bearer_token_file` is set with
// something like json-path.
expected := `global:
evaluation_interval: 30s
scrape_interval: 30s
external_labels:
prometheus: default/test
prometheus_replica: $(POD_NAME)
rule_files: []
scrape_configs:
- job_name: default/test/0
honor_labels: false
kubernetes_sd_configs:
- role: endpoints
namespaces:
names:
- default
relabel_configs:
- action: keep
source_labels:
- __meta_kubernetes_service_label_foo
regex: bar
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Node;(.*)
replacement: ${1}
target_label: node
- source_labels:
- __meta_kubernetes_endpoint_address_target_kind
- __meta_kubernetes_endpoint_address_target_name
separator: ;
regex: Pod;(.*)
replacement: ${1}
target_label: pod
- source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- source_labels:
- __meta_kubernetes_service_name
target_label: service
- source_labels:
- __meta_kubernetes_pod_name
target_label: pod
- source_labels:
- __meta_kubernetes_pod_container_name
target_label: container
- source_labels:
- __meta_kubernetes_service_name
target_label: job
replacement: ${1}
alerting:
alert_relabel_configs:
- action: labeldrop
regex: prometheus_replica
alertmanagers: []
`
result := string(cfg)
if expected != result {
fmt.Println(pretty.Compare(expected, result))
t.Fatal("expected Prometheus configuration and actual configuration do not match")
}
}
func generateTestConfig(version string) ([]byte, error) {
cg := &configGenerator{}
replicas := int32(1)
return cg.generateConfig(
&monitoringv1.Prometheus{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "default",
},
Spec: monitoringv1.PrometheusSpec{
Alerting: &monitoringv1.AlertingSpec{
Alertmanagers: []monitoringv1.AlertmanagerEndpoints{
{
Name: "alertmanager-main",
Namespace: "default",
Port: intstr.FromString("web"),
},
},
},
ExternalLabels: map[string]string{
"label1": "value1",
"label2": "value2",
},
Version: version,
Replicas: &replicas,
ServiceMonitorSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group1",
},
},
PodMonitorSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group1",
},
},
RuleSelector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"role": "rulefile",
},
},
Resources: v1.ResourceRequirements{
Requests: v1.ResourceList{
v1.ResourceMemory: resource.MustParse("400Mi"),
},
},
RemoteRead: []monitoringv1.RemoteReadSpec{{
URL: "https://example.com/remote_read",
}},
RemoteWrite: []monitoringv1.RemoteWriteSpec{{
URL: "https://example.com/remote_write",
}},
},
},
makeServiceMonitors(),
makePodMonitors(),
nil,
map[string]BasicAuthCredentials{},
map[string]BearerToken{},
nil,
nil,
nil,
nil,
)
}
func makeServiceMonitors() map[string]*monitoringv1.ServiceMonitor {
res := map[string]*monitoringv1.ServiceMonitor{}
res["servicemonitor1"] = &monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testservicemonitor1",
Namespace: "default",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.ServiceMonitorSpec{
Selector: metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group1",
},
},
Endpoints: []monitoringv1.Endpoint{
{
Port: "web",
Interval: "30s",
},
},
},
}
res["servicemonitor2"] = &monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testservicemonitor2",
Namespace: "default",
Labels: map[string]string{
"group": "group2",
},
},
Spec: monitoringv1.ServiceMonitorSpec{
Selector: metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group2",
"group3": "group3",
},
},
Endpoints: []monitoringv1.Endpoint{
{
Port: "web",
Interval: "30s",
},
},
},
}
res["servicemonitor3"] = &monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testservicemonitor3",
Namespace: "default",
Labels: map[string]string{
"group": "group4",
},
},
Spec: monitoringv1.ServiceMonitorSpec{
Selector: metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group4",
"group3": "group5",
},
},
Endpoints: []monitoringv1.Endpoint{
{
Port: "web",
Interval: "30s",
Path: "/federate",
Params: map[string][]string{"metrics[]": {"{__name__=~\"job:.*\"}"}},
},
},
},
}
res["servicemonitor4"] = &monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testservicemonitor4",
Namespace: "default",
Labels: map[string]string{
"group": "group6",
},
},
Spec: monitoringv1.ServiceMonitorSpec{
Selector: metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group6",
"group3": "group7",
},
},
Endpoints: []monitoringv1.Endpoint{
{
Port: "web",
Interval: "30s",
MetricRelabelConfigs: []*monitoringv1.RelabelConfig{
{
Action: "drop",
Regex: "my-job-pod-.+",
SourceLabels: []string{"pod_name"},
},
{
Action: "drop",
Regex: "test",
SourceLabels: []string{"namespace"},
},
},
},
},
},
}
res["servicemonitor5"] = &monitoringv1.ServiceMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testservicemonitor4",
Namespace: "default",
Labels: map[string]string{
"group": "group8",
},
},
Spec: monitoringv1.ServiceMonitorSpec{
Selector: metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group8",
"group3": "group9",
},
},
Endpoints: []monitoringv1.Endpoint{
{
Port: "web",
Interval: "30s",
RelabelConfigs: []*monitoringv1.RelabelConfig{
{
Action: "replace",
Regex: "(.*)",
Replacement: "$1",
SourceLabels: []string{"__meta_kubernetes_pod_ready"},
TargetLabel: "pod_ready",
},
{
Action: "replace",
Regex: "(.*)",
Replacement: "$1",
SourceLabels: []string{"__meta_kubernetes_pod_node_name"},
TargetLabel: "nodename",
},
},
},
},
},
}
return res
}
func makePodMonitors() map[string]*monitoringv1.PodMonitor {
res := map[string]*monitoringv1.PodMonitor{}
res["podmonitor1"] = &monitoringv1.PodMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testpodmonitor1",
Namespace: "default",
Labels: map[string]string{
"group": "group1",
},
},
Spec: monitoringv1.PodMonitorSpec{
Selector: metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group1",
},
},
PodMetricsEndpoints: []monitoringv1.PodMetricsEndpoint{
{
Port: "web",
Interval: "30s",
},
},
},
}
res["podmonitor2"] = &monitoringv1.PodMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testpodmonitor2",
Namespace: "default",
Labels: map[string]string{
"group": "group2",
},
},
Spec: monitoringv1.PodMonitorSpec{
Selector: metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group2",
"group3": "group3",
},
},
PodMetricsEndpoints: []monitoringv1.PodMetricsEndpoint{
{
Port: "web",
Interval: "30s",
},
},
},
}
res["podmonitor3"] = &monitoringv1.PodMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testpodmonitor3",
Namespace: "default",
Labels: map[string]string{
"group": "group4",
},
},
Spec: monitoringv1.PodMonitorSpec{
Selector: metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group4",
"group3": "group5",
},
},
PodMetricsEndpoints: []monitoringv1.PodMetricsEndpoint{
{
Port: "web",
Interval: "30s",
Path: "/federate",
Params: map[string][]string{"metrics[]": {"{__name__=~\"job:.*\"}"}},
},
},
},
}
res["podmonitor4"] = &monitoringv1.PodMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testpodmonitor4",
Namespace: "default",
Labels: map[string]string{
"group": "group6",
},
},
Spec: monitoringv1.PodMonitorSpec{
Selector: metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group6",
"group3": "group7",
},
},
PodMetricsEndpoints: []monitoringv1.PodMetricsEndpoint{
{
Port: "web",
Interval: "30s",
MetricRelabelConfigs: []*monitoringv1.RelabelConfig{
{
Action: "drop",
Regex: "my-job-pod-.+",
SourceLabels: []string{"pod_name"},
},
{
Action: "drop",
Regex: "test",
SourceLabels: []string{"namespace"},
},
},
},
},
},
}
res["podmonitor5"] = &monitoringv1.PodMonitor{
ObjectMeta: metav1.ObjectMeta{
Name: "testpodmonitor4",
Namespace: "default",
Labels: map[string]string{
"group": "group8",
},
},
Spec: monitoringv1.PodMonitorSpec{
Selector: metav1.LabelSelector{
MatchLabels: map[string]string{
"group": "group8",
"group3": "group9",
},
},
PodMetricsEndpoints: []monitoringv1.PodMetricsEndpoint{
{
Port: "web",
Interval: "30s",
RelabelConfigs: []*monitoringv1.RelabelConfig{
{
Action: "replace",
Regex: "(.*)",
Replacement: "$1",
SourceLabels: []string{"__meta_kubernetes_pod_ready"},
TargetLabel: "pod_ready",
},
{
Action: "replace",
Regex: "(.*)",
Replacement: "$1",
SourceLabels: []string{"__meta_kubernetes_pod_node_name"},
TargetLabel: "nodename",
},
},
},
},
},
}
return res
}
func TestHonorLabels(t *testing.T) {
type testCase struct {
UserHonorLabels bool
OverrideHonorLabels bool
Expected bool
}
testCases := []testCase{
{
UserHonorLabels: false,
OverrideHonorLabels: true,
Expected: false,
},
{
UserHonorLabels: true,
OverrideHonorLabels: false,
Expected: true,
},
{
UserHonorLabels: true,
OverrideHonorLabels: true,
Expected: false,
},
{
UserHonorLabels: false,
OverrideHonorLabels: false,
Expected: false,
},
}
for _, tc := range testCases {
hl := honorLabels(tc.UserHonorLabels, tc.OverrideHonorLabels)
if tc.Expected != hl {
t.Fatalf("\nGot: %t, \nExpected: %t\nFor values UserHonorLabels %t, OverrideHonorLabels %t\n", hl, tc.Expected, tc.UserHonorLabels, tc.OverrideHonorLabels)
}
}
}
func TestHonorTimestamps(t *testing.T) {
type testCase struct {
UserHonorTimestamps *bool
OverrideHonorTimestamps bool
Expected string
}
testCases := []testCase{
{
UserHonorTimestamps: nil,
OverrideHonorTimestamps: true,
Expected: "honor_timestamps: false\n",
},
{
UserHonorTimestamps: nil,
OverrideHonorTimestamps: false,
Expected: "{}\n",
},
{
UserHonorTimestamps: swag.Bool(false),
OverrideHonorTimestamps: true,
Expected: "honor_timestamps: false\n",
},
{
UserHonorTimestamps: swag.Bool(false),
OverrideHonorTimestamps: false,
Expected: "honor_timestamps: false\n",
},
{
UserHonorTimestamps: swag.Bool(true),
OverrideHonorTimestamps: true,
Expected: "honor_timestamps: false\n",
},
{
UserHonorTimestamps: swag.Bool(true),
OverrideHonorTimestamps: false,
Expected: "honor_timestamps: true\n",
},
}
for _, tc := range testCases {
hl, _ := yaml.Marshal(honorTimestamps(yaml.MapSlice{}, tc.UserHonorTimestamps, tc.OverrideHonorTimestamps))
cfg := string(hl)
if tc.Expected != cfg {
t.Fatalf("\nGot: %s, \nExpected: %s\nFor values UserHonorTimestamps %+v, OverrideHonorTimestamps %t\n", cfg, tc.Expected, tc.UserHonorTimestamps, tc.OverrideHonorTimestamps)
}
}
}
func TestGetSampleLimit(t *testing.T) {
tcs := []struct {
Enforced uint64
Expected uint64
User uint64
}{
{
Enforced: 100,
User: 1000,
Expected: 100,
},
{
Enforced: 99,
User: 88,
Expected: 88,
},
{
Enforced: 0,
User: 888,
Expected: 888,
},
{
Enforced: 1,
User: 0,
Expected: 1,
},
}
for _, tc := range tcs {
actual := getSampleLimit(tc.User, &tc.Enforced)
if actual != tc.Expected {
t.Fatalf("Got %d, Expected: %d, Enforced: %d, User: %d", actual, tc.Expected, tc.Enforced, tc.User)
}
}
}