Skip to content

Commit 8147f85

Browse files
authored
prefect: add container-based config discovery support (#24483)
* prefect: add container-based config discovery support * Add changelog entry for #24483
1 parent d6f5698 commit 8147f85

8 files changed

Lines changed: 128 additions & 6 deletions

File tree

prefect/assets/configuration/spec.yaml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
name: Prefect
22
files:
33
- name: prefect.yaml
4+
discovery:
5+
strategies:
6+
- strategy: from_ports
7+
port_hints:
8+
- 4200
9+
candidates:
10+
- prefect_url: "http://{service.host}:{port.number}/api"
411
options:
512
- template: init_config
613
options:
@@ -146,4 +153,11 @@ files:
146153
- type: multi_line
147154
name: python_stack_trace
148155
pattern: '^\d{2}:\d{2}:\d{2}\.\d{3} \|'
156+
- name: auto_conf.yaml
157+
options:
158+
- template: ad_identifiers
159+
overrides:
160+
value.example:
161+
- prefect
162+
- template: auto_conf/discovery
149163

prefect/changelog.d/24483.added

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add container-based config discovery support.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# (C) Datadog, Inc. 2026-present
2+
# All rights reserved
3+
# Licensed under a 3-clause BSD style license (see LICENSE)
4+
5+
# This file is autogenerated.
6+
# To change this file you should edit assets/configuration/spec.yaml and then run the following commands:
7+
# ddev -x validate config -s <INTEGRATION_NAME>
8+
# ddev -x validate models -s <INTEGRATION_NAME>
9+
10+
from __future__ import annotations
11+
12+
from collections.abc import Iterator
13+
from typing import Any
14+
15+
from datadog_checks.base.utils.discovery import Service, candidate_ports
16+
from datadog_checks.prefect.config_models import discovery_overrides
17+
from datadog_checks.prefect.config_models.instance import InstanceConfig
18+
from datadog_checks.prefect.config_models.shared import SharedConfig
19+
20+
21+
def _generated_candidates(service: Service) -> Iterator[dict[str, Any]]:
22+
shared = SharedConfig.model_validate({}, context={'configured_fields': frozenset()}).model_dump(
23+
by_alias=True, mode='json', exclude_none=True
24+
)
25+
# discovery[0]: from_ports
26+
for port in candidate_ports(service, [4200]):
27+
ctx = {'port': port}
28+
instance_data = {
29+
'prefect_url': 'http://{service.host}:{port.number}/api'.format(service=service, **ctx),
30+
}
31+
instance = InstanceConfig.model_validate(
32+
instance_data, context={'configured_fields': frozenset(instance_data)}
33+
).model_dump(by_alias=True, mode='json', exclude_none=True)
34+
yield {'init_config': shared, 'instances': [instance]}
35+
36+
37+
def candidates(service: Service) -> Iterator[dict[str, Any]]:
38+
override = getattr(discovery_overrides, 'candidates', None)
39+
if override is None:
40+
yield from _generated_candidates(service)
41+
else:
42+
yield from override(service, default=_generated_candidates)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# (C) Datadog, Inc. 2026-present
2+
# All rights reserved
3+
# Licensed under a 3-clause BSD style license (see LICENSE)
4+
5+
# Override the generated discovery candidates() for this integration.
6+
#
7+
# Define a candidates(service, default) function to wrap or replace the generated
8+
# candidate generation. `default` is the generated generator; call it to reuse
9+
# the spec-driven candidates, or ignore it to replace them entirely.
10+
#
11+
# def candidates(service, default):
12+
# yield from default(service)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# (C) Datadog, Inc. 2026-present
2+
# All rights reserved
3+
# Licensed under a 3-clause BSD style license (see LICENSE)
4+
5+
# Here you can define custom (local:) discovery strategies for this integration.
6+
#
7+
# Decorate a generator with @discovery_strategy (imported from
8+
# datadog_checks.base.utils.discovery) and reference it from the spec discovery
9+
# stanza as `strategy: local:<function_name>`. The function receives the
10+
# discovered Service plus the inputs declared in the spec and yields one context
11+
# (ctx) mapping per candidate, exposing the keys listed in `provides`.
12+
#
13+
# from datadog_checks.base.utils.discovery import discovery_strategy
14+
#
15+
# @discovery_strategy(provides=('svc',))
16+
# def from_some_config(service, config_path):
17+
# ...
18+
# yield {'svc': ...}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
## @param ad_identifiers - list of strings - required
2+
## A list of container identifiers that are used by Autodiscovery to identify
3+
## which container the check should be run against. For more information, see:
4+
## https://docs.datadoghq.com/agent/guide/ad_identifiers/
5+
#
6+
ad_identifiers:
7+
- prefect
8+
9+
## Enables configuration discovery
10+
#
11+
discovery: {}
12+
13+
## Unused init configuration
14+
#
15+
init_config:
16+
17+
## Unused instance configuration
18+
#
19+
instances: []

prefect/tests/conftest.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import requests
1111

1212
from datadog_checks.dev.conditions import CheckDockerLogs, CheckEndpoints, WaitFor
13-
from datadog_checks.dev.docker import docker_run, get_docker_hostname
13+
from datadog_checks.dev.docker import docker_run, get_docker_hostname, get_e2e_discovery_metadata
1414
from datadog_checks.dev.utils import find_free_port
1515
from datadog_checks.prefect import PrefectCheck
1616

@@ -65,7 +65,7 @@ def dd_environment(instance: Callable[[str], dict[str, str | dict[str, list[str]
6565
):
6666
yield (
6767
{"instances": [instance(prefect_url)]},
68-
E2E_METADATA,
68+
{**E2E_METADATA, **get_e2e_discovery_metadata()},
6969
)
7070

7171

prefect/tests/test_e2e.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
import pytest
66

7+
from datadog_checks.dev.docker import assert_all_discovery_candidates_stable
78
from datadog_checks.dev.utils import get_metadata_metrics
9+
from datadog_checks.prefect import PrefectCheck
810

911
WORK_POOL_TAG_KEYS = ["work_pool_id:", "work_pool_name:", "work_pool_type:"]
1012

@@ -81,10 +83,7 @@
8183
}
8284

8385

84-
@pytest.mark.e2e
85-
def test_e2e_metrics(dd_agent_check):
86-
aggregator = dd_agent_check(check_times=2, pause=20000)
87-
86+
def _assert_e2e_metrics(aggregator):
8887
cross_check_metrics = (
8988
'flow_runs.retry_gaps_duration',
9089
'task_runs.dependency_wait_duration',
@@ -106,3 +105,20 @@ def test_e2e_metrics(dd_agent_check):
106105
for metric_name, expected_tags in E2E_METRIC_TAGS.items():
107106
for tag in expected_tags:
108107
aggregator.assert_metric_has_tag_prefix(metric_name, tag)
108+
109+
110+
@pytest.mark.e2e
111+
def test_e2e_metrics(dd_agent_check):
112+
aggregator = dd_agent_check(check_times=2, pause=20000)
113+
_assert_e2e_metrics(aggregator)
114+
115+
116+
@pytest.mark.e2e
117+
def test_e2e_discovery(dd_agent_check_discovery):
118+
aggregator = dd_agent_check_discovery(check_times=2, pause=20000)
119+
_assert_e2e_metrics(aggregator)
120+
121+
122+
@pytest.mark.e2e
123+
def test_e2e_discovery_all_candidates(dd_agent_check):
124+
assert_all_discovery_candidates_stable(dd_agent_check, PrefectCheck, compose_service='prefect-server')

0 commit comments

Comments
 (0)