Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion keda/assets/configuration/spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ name: Keda
fleet_configurable: true
files:
- name: keda.yaml
discovery:
strategies:
- template: discovery/openmetrics_from_named_ports
options:
- template: init_config
options:
Expand All @@ -13,4 +16,13 @@ files:
openmetrics_endpoint.value.example: http://localhost:8080/metrics
openmetrics_endpoint.description: |
Endpoint exposing the Keda's Prometheus metrics. For more information refer to:
https://keda.sh/docs/2.16/integrations/prometheus/
https://keda.sh/docs/2.16/integrations/prometheus/
- name: auto_conf.yaml
options:
- template: ad_identifiers
overrides:
value.example:
- keda
- keda-admission-webhooks
- keda-metrics-apiserver
- template: auto_conf/discovery
1 change: 1 addition & 0 deletions keda/changelog.d/24459.added
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add container-based config discovery support.
2 changes: 1 addition & 1 deletion keda/datadog_checks/keda/config_models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# (C) Datadog, Inc. 2024-present
# (C) Datadog, Inc. 2026-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)

Expand Down
2 changes: 1 addition & 1 deletion keda/datadog_checks/keda/config_models/defaults.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# (C) Datadog, Inc. 2024-present
# (C) Datadog, Inc. 2026-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)

Expand Down
42 changes: 42 additions & 0 deletions keda/datadog_checks/keda/config_models/discovery.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# (C) Datadog, Inc. 2026-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)

# This file is autogenerated.
# To change this file you should edit assets/configuration/spec.yaml and then run the following commands:
# ddev -x validate config -s <INTEGRATION_NAME>
# ddev -x validate models -s <INTEGRATION_NAME>

from __future__ import annotations

from collections.abc import Iterator
from typing import Any

from datadog_checks.base.utils.discovery import Service, candidate_ports_by_name
from datadog_checks.keda.config_models import discovery_overrides
from datadog_checks.keda.config_models.instance import InstanceConfig
from datadog_checks.keda.config_models.shared import SharedConfig


def _generated_candidates(service: Service) -> Iterator[dict[str, Any]]:
shared = SharedConfig.model_validate({}, context={'configured_fields': frozenset()}).model_dump(
by_alias=True, mode='json', exclude_none=True
)
# discovery[0]: from_named_ports
for port in candidate_ports_by_name(service, ['metrics']):
ctx = {'port': port}
instance_data = {
'openmetrics_endpoint': 'http://{service.host}:{port.number}/metrics'.format(service=service, **ctx),
}
instance = InstanceConfig.model_validate(
instance_data, context={'configured_fields': frozenset(instance_data)}
).model_dump(by_alias=True, mode='json', exclude_none=True)
yield {'init_config': shared, 'instances': [instance]}


def candidates(service: Service) -> Iterator[dict[str, Any]]:
override = getattr(discovery_overrides, 'candidates', None)
if override is None:
yield from _generated_candidates(service)
else:
yield from override(service, default=_generated_candidates)
12 changes: 12 additions & 0 deletions keda/datadog_checks/keda/config_models/discovery_overrides.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# (C) Datadog, Inc. 2026-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)

# Override the generated discovery candidates() for this integration.
#
# Define a candidates(service, default) function to wrap or replace the generated
# candidate generation. `default` is the generated generator; call it to reuse
# the spec-driven candidates, or ignore it to replace them entirely.
#
# def candidates(service, default):
# yield from default(service)
18 changes: 18 additions & 0 deletions keda/datadog_checks/keda/config_models/discovery_strategies.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# (C) Datadog, Inc. 2026-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)

# Here you can define custom (local:) discovery strategies for this integration.
#
# Decorate a generator with @discovery_strategy (imported from
# datadog_checks.base.utils.discovery) and reference it from the spec discovery
# stanza as `strategy: local:<function_name>`. The function receives the
# discovered Service plus the inputs declared in the spec and yields one context
# (ctx) mapping per candidate, exposing the keys listed in `provides`.
#
# from datadog_checks.base.utils.discovery import discovery_strategy
#
# @discovery_strategy(provides=('svc',))
# def from_some_config(service, config_path):
# ...
# yield {'svc': ...}
2 changes: 1 addition & 1 deletion keda/datadog_checks/keda/config_models/instance.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# (C) Datadog, Inc. 2024-present
# (C) Datadog, Inc. 2026-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)

Expand Down
2 changes: 1 addition & 1 deletion keda/datadog_checks/keda/config_models/shared.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# (C) Datadog, Inc. 2024-present
# (C) Datadog, Inc. 2026-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)

Expand Down
21 changes: 21 additions & 0 deletions keda/datadog_checks/keda/data/auto_conf.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
## @param ad_identifiers - list of strings - required
## A list of container identifiers that are used by Autodiscovery to identify
## which container the check should be run against. For more information, see:
## https://docs.datadoghq.com/agent/guide/ad_identifiers/
#
ad_identifiers:
- keda
- keda-admission-webhooks
- keda-metrics-apiserver

## Enables configuration discovery
#
discovery: {}

## Unused init configuration
#
init_config:

## Unused instance configuration
#
instances: []
2 changes: 2 additions & 0 deletions keda/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import pytest

from datadog_checks.dev.kind import kind_run
from datadog_checks.dev.kube_discovery import setup_discovery_agent
from datadog_checks.dev.kube_port_forward import port_forward
from datadog_checks.dev.subprocess import run_command

Expand All @@ -28,6 +29,7 @@ def setup_ked():
@pytest.fixture(scope='session')
def dd_environment():
with kind_run(conditions=[setup_ked], sleep=30) as kubeconfig, ExitStack() as stack:
setup_discovery_agent(kubeconfig)
keda_host, keda_port = stack.enter_context(
port_forward(kubeconfig, 'keda', 8080, 'deployment', 'keda-operator-metrics-apiserver')
)
Expand Down
33 changes: 33 additions & 0 deletions keda/tests/test_e2e.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,45 @@
# (C) Datadog, Inc. 2024-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)
import pytest

from datadog_checks.base.constants import ServiceCheck
from datadog_checks.dev.kube_discovery import (
assert_all_discovery_candidates_stable_kubernetes,
run_discovery_check_kubernetes,
)
from datadog_checks.dev.utils import assert_service_checks
from datadog_checks.keda import KedaCheck

KEDA_POD_SELECTORS = (
'app=keda-operator',
'app=keda-operator-metrics-apiserver',
'app=keda-admission-webhooks',
)


def test_e2e_openmetrics_v2(dd_agent_check):
aggregator = dd_agent_check()

aggregator.assert_service_check('keda.openmetrics.health', ServiceCheck.OK, count=1)
assert_service_checks(aggregator)


@pytest.mark.e2e
def test_e2e_discovery(aggregator, datadog_agent):
run_discovery_check_kubernetes(aggregator, datadog_agent, discovery_min_instances=len(KEDA_POD_SELECTORS))

aggregator.assert_service_check('keda.openmetrics.health', ServiceCheck.OK, count=len(KEDA_POD_SELECTORS))
assert_service_checks(aggregator)


@pytest.mark.e2e
@pytest.mark.parametrize('pod_selector', KEDA_POD_SELECTORS)
def test_e2e_discovery_all_candidates(aggregator, datadog_agent, pod_selector):
assert_all_discovery_candidates_stable_kubernetes(
KedaCheck,
aggregator,
datadog_agent,
namespace='keda',
pod_selector=pod_selector,
)
Loading