From cdcb1f39a449cd3c939fa21f00f32e6527d543c2 Mon Sep 17 00:00:00 2001 From: Minyi Zhu Date: Wed, 27 Aug 2025 01:13:49 -0400 Subject: [PATCH] Support openmetrics_endpoint in kube_scheduler check --- kube_scheduler/CHANGELOG.md | 1 + kube_scheduler/assets/configuration/spec.yaml | 15 +++++- kube_scheduler/changelog.d/21178.added | 1 + .../kube_scheduler/config_models/defaults.py | 8 ++++ .../kube_scheduler/config_models/instance.py | 3 +- .../config_models/validators.py | 24 ++++++---- .../kube_scheduler/data/conf.yaml.example | 12 ++++- kube_scheduler/tests/test_validators.py | 48 +++++++++++++++++++ 8 files changed, 100 insertions(+), 12 deletions(-) create mode 100644 kube_scheduler/changelog.d/21178.added create mode 100644 kube_scheduler/tests/test_validators.py diff --git a/kube_scheduler/CHANGELOG.md b/kube_scheduler/CHANGELOG.md index d74d38962a35d..6597389a220e6 100644 --- a/kube_scheduler/CHANGELOG.md +++ b/kube_scheduler/CHANGELOG.md @@ -2,6 +2,7 @@ + ## 7.0.1 / 2025-08-07 ***Fixed***: diff --git a/kube_scheduler/assets/configuration/spec.yaml b/kube_scheduler/assets/configuration/spec.yaml index 4ec38188ba3e6..333114e6c9b03 100644 --- a/kube_scheduler/assets/configuration/spec.yaml +++ b/kube_scheduler/assets/configuration/spec.yaml @@ -31,10 +31,23 @@ files: value: type: string example: http://localhost:10251/healthz + - name: openmetrics_endpoint + description: | + The URL exposing metrics in the OpenMetrics format. + One of openmetrics_endpoint or prometheus_url parameter is required. + required: false + value: + type: string + example: http://localhost:10251/metrics + display_priority: 1 - template: instances/openmetrics_legacy overrides: prometheus_url.value.example: http://localhost:10251/metrics - prometheus_url.display_priority: 1 + prometheus_url.display_priority: 2 + prometheus_url.required: false + prometheus_url.description: | + The URL where your application metrics are exposed by Prometheus. + One of openmetrics_endpoint or prometheus_url parameter is required. - name: auto_conf.yaml options: diff --git a/kube_scheduler/changelog.d/21178.added b/kube_scheduler/changelog.d/21178.added new file mode 100644 index 0000000000000..9a861aff34292 --- /dev/null +++ b/kube_scheduler/changelog.d/21178.added @@ -0,0 +1 @@ +Add support for openmetrics_endpoint configuration parameter as an alternative to prometheus_url diff --git a/kube_scheduler/datadog_checks/kube_scheduler/config_models/defaults.py b/kube_scheduler/datadog_checks/kube_scheduler/config_models/defaults.py index 07501e01d2bf8..4dd9e09dbe42a 100644 --- a/kube_scheduler/datadog_checks/kube_scheduler/config_models/defaults.py +++ b/kube_scheduler/datadog_checks/kube_scheduler/config_models/defaults.py @@ -76,10 +76,18 @@ def instance_namespace(): return 'service' +def instance_openmetrics_endpoint(): + return 'http://localhost:10251/metrics' + + def instance_persist_connections(): return False +def instance_prometheus_url(): + return 'http://localhost:10251/metrics' + + def instance_request_size(): return 10 diff --git a/kube_scheduler/datadog_checks/kube_scheduler/config_models/instance.py b/kube_scheduler/datadog_checks/kube_scheduler/config_models/instance.py index c76600d7e2889..f7f0a7ce18bc2 100644 --- a/kube_scheduler/datadog_checks/kube_scheduler/config_models/instance.py +++ b/kube_scheduler/datadog_checks/kube_scheduler/config_models/instance.py @@ -119,10 +119,11 @@ class InstanceConfig(BaseModel): min_collection_interval: Optional[float] = None namespace: Optional[str] = None ntlm_domain: Optional[str] = None + openmetrics_endpoint: Optional[str] = None password: Optional[str] = None persist_connections: Optional[bool] = None prometheus_metrics_prefix: Optional[str] = None - prometheus_url: str + prometheus_url: Optional[str] = None proxy: Optional[Proxy] = None read_timeout: Optional[float] = None request_size: Optional[float] = None diff --git a/kube_scheduler/datadog_checks/kube_scheduler/config_models/validators.py b/kube_scheduler/datadog_checks/kube_scheduler/config_models/validators.py index 1b99ebf855087..74a13110a0137 100644 --- a/kube_scheduler/datadog_checks/kube_scheduler/config_models/validators.py +++ b/kube_scheduler/datadog_checks/kube_scheduler/config_models/validators.py @@ -3,11 +3,19 @@ # Licensed under a 3-clause BSD style license (see LICENSE) # Here you can include additional config validators or transformers -# -# def initialize_instance(values, **kwargs): -# if 'my_option' not in values and 'my_legacy_option' in values: -# values['my_option'] = values['my_legacy_option'] -# if values.get('my_number') > 10: -# raise ValueError('my_number max value is 10, got %s' % str(values.get('my_number'))) -# -# return values + + +def initialize_instance(values, **kwargs): + """ + Normalize instances to support both field names. + Parse prometheus_url first, if not available, fall back to openmetrics_endpoint. + """ + # Map openmetrics_endpoint to prometheus_url if prometheus_url is not present + if 'openmetrics_endpoint' in values and 'prometheus_url' not in values: + values['prometheus_url'] = values['openmetrics_endpoint'] + + # Ensure at least one endpoint is provided + if not values.get('prometheus_url') and not values.get('openmetrics_endpoint'): + raise ValueError('Field `openmetrics_endpoint` or `prometheus_url` must be set') + + return values diff --git a/kube_scheduler/datadog_checks/kube_scheduler/data/conf.yaml.example b/kube_scheduler/datadog_checks/kube_scheduler/data/conf.yaml.example index b2a399e094ab6..4fd09f5dffe8f 100644 --- a/kube_scheduler/datadog_checks/kube_scheduler/data/conf.yaml.example +++ b/kube_scheduler/datadog_checks/kube_scheduler/data/conf.yaml.example @@ -45,10 +45,12 @@ init_config: # instances: - ## @param prometheus_url - string - required + - + ## @param prometheus_url - string - optional - default: http://localhost:10251/metrics ## The URL where your application metrics are exposed by Prometheus. + ## One of openmetrics_endpoint or prometheus_url parameter is required. # - - prometheus_url: http://localhost:10251/metrics + # prometheus_url: http://localhost:10251/metrics ## @param leader_election - boolean - optional - default: true ## Monitor the leader-election process on the kube-system:kube-scheduler. @@ -71,6 +73,12 @@ instances: # # health_url: http://localhost:10251/healthz + ## @param openmetrics_endpoint - string - optional - default: http://localhost:10251/metrics + ## The URL exposing metrics in the OpenMetrics format. + ## One of openmetrics_endpoint or prometheus_url parameter is required. + # + # openmetrics_endpoint: http://localhost:10251/metrics + ## @param prometheus_metrics_prefix - string - optional ## Removes a given from exposed Prometheus metrics. # diff --git a/kube_scheduler/tests/test_validators.py b/kube_scheduler/tests/test_validators.py new file mode 100644 index 0000000000000..da7e328a911e6 --- /dev/null +++ b/kube_scheduler/tests/test_validators.py @@ -0,0 +1,48 @@ +# (C) Datadog, Inc. 2025-present +# All rights reserved +# Licensed under a 3-clause BSD style license (see LICENSE) + +import pytest + +from datadog_checks.kube_scheduler.config_models.validators import initialize_instance + + +class TestValidators: + def test_openmetrics_endpoint_only(self): + """Test that openmetrics_endpoint gets mapped to prometheus_url when prometheus_url is not present""" + config = {"openmetrics_endpoint": "http://localhost:10251/metrics"} + + # This should not raise an exception and should map openmetrics_endpoint to prometheus_url + result = initialize_instance(config) + assert result["openmetrics_endpoint"] == "http://localhost:10251/metrics" + assert result["prometheus_url"] == "http://localhost:10251/metrics" # Should be mapped + + def test_prometheus_url_only(self): + """Test that prometheus_url works without openmetrics_endpoint""" + config = {"prometheus_url": "http://localhost:10251/metrics"} + + # This should not raise an exception + result = initialize_instance(config) + assert result["prometheus_url"] == "http://localhost:10251/metrics" + assert result.get("openmetrics_endpoint") is None + + def test_both_endpoints(self): + """Test that both endpoints can be provided and prometheus_url takes precedence (no mapping occurs)""" + config = { + "openmetrics_endpoint": "http://openmetrics.example.com:8080/metrics", + "prometheus_url": "http://prometheus.example.com:9090/metrics", + } + + # This should not raise an exception and prometheus_url should not be overwritten + # The mapping should NOT occur when both are present + result = initialize_instance(config) + assert result["openmetrics_endpoint"] == "http://openmetrics.example.com:8080/metrics" + assert result["prometheus_url"] == "http://prometheus.example.com:9090/metrics" # Should remain unchanged + + def test_no_endpoints(self): + """Test that validation fails when neither endpoint is provided""" + config = {} + + # This should raise a ValueError + with pytest.raises(ValueError, match="Field `openmetrics_endpoint` or `prometheus_url` must be set"): + initialize_instance(config)