Skip to content

Commit 482071f

Browse files
committed
Support openmetrics_endpoint in kube_scheduler check
1 parent 642a5e8 commit 482071f

File tree

6 files changed

+98
-13
lines changed

6 files changed

+98
-13
lines changed

kube_scheduler/assets/configuration/spec.yaml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,23 @@ files:
3131
value:
3232
type: string
3333
example: http://localhost:10251/healthz
34+
- name: openmetrics_endpoint
35+
description: |
36+
The URL exposing metrics in the OpenMetrics format.
37+
One of openmetrics_endpoint or prometheus_url parameter is required.
38+
required: false
39+
value:
40+
type: string
41+
example: http://localhost:10251/metrics
42+
display_priority: 1
3443
- template: instances/openmetrics_legacy
3544
overrides:
3645
prometheus_url.value.example: http://localhost:10251/metrics
37-
prometheus_url.display_priority: 1
46+
prometheus_url.display_priority: 2
47+
prometheus_url.required: false
48+
prometheus_url.description: |
49+
The URL where your application metrics are exposed by Prometheus.
50+
One of openmetrics_endpoint or prometheus_url parameter is required.
3851
3952
- name: auto_conf.yaml
4053
options:

kube_scheduler/datadog_checks/kube_scheduler/config_models/defaults.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,18 @@ def instance_namespace():
7676
return 'service'
7777

7878

79+
def instance_openmetrics_endpoint():
80+
return 'http://localhost:10251/metrics'
81+
82+
7983
def instance_persist_connections():
8084
return False
8185

8286

87+
def instance_prometheus_url():
88+
return 'http://localhost:10251/metrics'
89+
90+
8391
def instance_request_size():
8492
return 10
8593

kube_scheduler/datadog_checks/kube_scheduler/config_models/instance.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,10 +119,11 @@ class InstanceConfig(BaseModel):
119119
min_collection_interval: Optional[float] = None
120120
namespace: Optional[str] = None
121121
ntlm_domain: Optional[str] = None
122+
openmetrics_endpoint: Optional[str] = None
122123
password: Optional[str] = None
123124
persist_connections: Optional[bool] = None
124125
prometheus_metrics_prefix: Optional[str] = None
125-
prometheus_url: str
126+
prometheus_url: Optional[str] = None
126127
proxy: Optional[Proxy] = None
127128
read_timeout: Optional[float] = None
128129
request_size: Optional[float] = None
@@ -138,7 +139,6 @@ class InstanceConfig(BaseModel):
138139
timeout: Optional[float] = None
139140
tls_ca_cert: Optional[str] = None
140141
tls_cert: Optional[str] = None
141-
tls_ciphers: Optional[tuple[str, ...]] = None
142142
tls_ignore_warning: Optional[bool] = None
143143
tls_private_key: Optional[str] = None
144144
tls_protocols_allowed: Optional[tuple[str, ...]] = None

kube_scheduler/datadog_checks/kube_scheduler/config_models/validators.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,19 @@
33
# Licensed under a 3-clause BSD style license (see LICENSE)
44

55
# Here you can include additional config validators or transformers
6-
#
7-
# def initialize_instance(values, **kwargs):
8-
# if 'my_option' not in values and 'my_legacy_option' in values:
9-
# values['my_option'] = values['my_legacy_option']
10-
# if values.get('my_number') > 10:
11-
# raise ValueError('my_number max value is 10, got %s' % str(values.get('my_number')))
12-
#
13-
# return values
6+
7+
8+
def initialize_instance(values, **kwargs):
9+
"""
10+
Normalize instances to support both field names.
11+
Parse prometheus_url first, if not available, fall back to openmetrics_endpoint.
12+
"""
13+
# Map openmetrics_endpoint to prometheus_url if prometheus_url is not present
14+
if 'openmetrics_endpoint' in values and 'prometheus_url' not in values:
15+
values['prometheus_url'] = values['openmetrics_endpoint']
16+
17+
# Ensure at least one endpoint is provided
18+
if not values.get('prometheus_url') and not values.get('openmetrics_endpoint'):
19+
raise ValueError('Field `openmetrics_endpoint` or `prometheus_url` must be set')
20+
21+
return values

kube_scheduler/datadog_checks/kube_scheduler/data/conf.yaml.example

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,12 @@ init_config:
4545
#
4646
instances:
4747

48-
## @param prometheus_url - string - required
48+
-
49+
## @param prometheus_url - string - optional - default: http://localhost:10251/metrics
4950
## The URL where your application metrics are exposed by Prometheus.
51+
## One of openmetrics_endpoint or prometheus_url parameter is required.
5052
#
51-
- prometheus_url: http://localhost:10251/metrics
53+
# prometheus_url: http://localhost:10251/metrics
5254

5355
## @param leader_election - boolean - optional - default: true
5456
## Monitor the leader-election process on the kube-system:kube-scheduler.
@@ -71,6 +73,12 @@ instances:
7173
#
7274
# health_url: http://localhost:10251/healthz
7375

76+
## @param openmetrics_endpoint - string - optional - default: http://localhost:10251/metrics
77+
## The URL exposing metrics in the OpenMetrics format.
78+
## One of openmetrics_endpoint or prometheus_url parameter is required.
79+
#
80+
# openmetrics_endpoint: http://localhost:10251/metrics
81+
7482
## @param prometheus_metrics_prefix - string - optional
7583
## Removes a given <PREFIX> from exposed Prometheus metrics.
7684
#
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# (C) Datadog, Inc. 2025-present
2+
# All rights reserved
3+
# Licensed under a 3-clause BSD style license (see LICENSE)
4+
5+
import pytest
6+
7+
from datadog_checks.kube_scheduler.config_models.validators import initialize_instance
8+
9+
10+
class TestValidators:
11+
def test_openmetrics_endpoint_only(self):
12+
"""Test that openmetrics_endpoint gets mapped to prometheus_url when prometheus_url is not present"""
13+
config = {"openmetrics_endpoint": "http://localhost:10251/metrics"}
14+
15+
# This should not raise an exception and should map openmetrics_endpoint to prometheus_url
16+
result = initialize_instance(config)
17+
assert result["openmetrics_endpoint"] == "http://localhost:10251/metrics"
18+
assert result["prometheus_url"] == "http://localhost:10251/metrics" # Should be mapped
19+
20+
def test_prometheus_url_only(self):
21+
"""Test that prometheus_url works without openmetrics_endpoint"""
22+
config = {"prometheus_url": "http://localhost:10251/metrics"}
23+
24+
# This should not raise an exception
25+
result = initialize_instance(config)
26+
assert result["prometheus_url"] == "http://localhost:10251/metrics"
27+
assert result.get("openmetrics_endpoint") is None
28+
29+
def test_both_endpoints(self):
30+
"""Test that both endpoints can be provided and prometheus_url takes precedence (no mapping occurs)"""
31+
config = {
32+
"openmetrics_endpoint": "http://openmetrics.example.com:8080/metrics",
33+
"prometheus_url": "http://prometheus.example.com:9090/metrics",
34+
}
35+
36+
# This should not raise an exception and prometheus_url should not be overwritten
37+
# The mapping should NOT occur when both are present
38+
result = initialize_instance(config)
39+
assert result["openmetrics_endpoint"] == "http://openmetrics.example.com:8080/metrics"
40+
assert result["prometheus_url"] == "http://prometheus.example.com:9090/metrics" # Should remain unchanged
41+
42+
def test_no_endpoints(self):
43+
"""Test that validation fails when neither endpoint is provided"""
44+
config = {}
45+
46+
# This should raise a ValueError
47+
with pytest.raises(ValueError, match="Field `openmetrics_endpoint` or `prometheus_url` must be set"):
48+
initialize_instance(config)

0 commit comments

Comments
 (0)