Skip to content

Commit fa4dc5c

Browse files
vitkyrkaclaude
andauthored
Run Flux CD E2E with the Kubernetes Agent backend (DataDog#24829)
* Run Flux CD E2E tests with the Kubernetes Agent backend Convert fluxcd's dd_environment fixture from host-side port-forwarding to reaching the flux-system controllers from inside the Kind cluster. The flux-system Services only expose each controller's API port, not the Prometheus metrics port, so Service DNS cannot reach /metrics; instead the pod IP of all four single-replica controller Deployments is fetched once during cluster setup and cached via ddev's save_state/get_state, so later `ddev env` invocations (including `stop`) don't need to re-run kubectl against a cluster that may already be gone. Environment: Datadog workspace Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * Add type annotations to get_controller_pod_ip Addresses a Codex review finding on PR DataDog#24829. Environment: Datadog workspace Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
1 parent 4118f31 commit fa4dc5c

1 file changed

Lines changed: 49 additions & 20 deletions

File tree

fluxcd/tests/conftest.py

Lines changed: 49 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,31 @@
11
# (C) Datadog, Inc. 2024-present
22
# All rights reserved
33
# Licensed under a 3-clause BSD style license (see LICENSE)
4+
import json
45
import os
5-
from contextlib import ExitStack
66
from unittest import mock
77

88
import pytest
99

1010
from datadog_checks.dev import get_here
11+
from datadog_checks.dev._env import get_state, save_state
1112
from datadog_checks.dev.kind import kind_run
12-
from datadog_checks.dev.kube_port_forward import port_forward
1313
from datadog_checks.dev.subprocess import run_command
1414
from datadog_checks.fluxcd import FluxcdCheck
1515

1616
HERE = get_here()
1717
opj = os.path.join
1818

19+
# The Services in flux-system (source-controller, notification-controller) only expose the
20+
# controllers' API port (9090) as port 80, not the Prometheus metrics port (8080), so Service DNS
21+
# cannot reach /metrics for any controller. All four controllers are single-replica Deployments, so
22+
# their pod IP is fetched directly and used to reach the metrics port. The `allow-scraping`
23+
# NetworkPolicy shipped in install.yaml explicitly permits cross-namespace ingress on port 8080,
24+
# confirming this is the intended scrape path.
25+
CONTROLLERS = ('source-controller', 'helm-controller', 'kustomize-controller', 'notification-controller')
26+
METRICS_PORT = 8080
27+
POD_IP_STATE_PREFIX = 'fluxcd_pod_ip_'
28+
1929

2030
def setup_fluxcd():
2131
run_command(["kubectl", "apply", "--filename", opj(HERE, 'kind', "install.yaml")])
@@ -31,29 +41,48 @@ def setup_fluxcd():
3141
"--timeout=300s",
3242
]
3343
)
44+
# Save each controller's pod IP now, while the cluster is guaranteed to be up. `dd_environment`
45+
# runs again (without `conditions`, so without this function) on every `ddev env` invocation,
46+
# including `stop`, when the cluster may already be gone.
47+
for controller in CONTROLLERS:
48+
save_state(POD_IP_STATE_PREFIX + controller, get_controller_pod_ip(controller))
49+
50+
51+
def get_controller_pod_ip(controller: str) -> str:
52+
result = run_command(
53+
[
54+
"kubectl",
55+
"get",
56+
"pods",
57+
"--namespace",
58+
"flux-system",
59+
"--selector",
60+
f"app={controller}",
61+
"--output",
62+
"json",
63+
],
64+
capture='out',
65+
check=True,
66+
)
67+
pods = json.loads(result.stdout)['items']
68+
if len(pods) != 1 or not pods[0].get('status', {}).get('podIP'):
69+
raise RuntimeError(f'Expected exactly one ready {controller} pod, found {len(pods)}')
70+
return pods[0]['status']['podIP']
3471

3572

3673
@pytest.fixture(scope='session')
3774
def dd_environment():
3875
with kind_run(conditions=[setup_fluxcd]) as kubeconfig:
39-
instances = []
40-
with ExitStack() as stack:
41-
for controller in (
42-
'source-controller',
43-
'helm-controller',
44-
'kustomize-controller',
45-
'notification-controller',
46-
):
47-
host, port = stack.enter_context(
48-
port_forward(kubeconfig, 'flux-system', 8080, 'deployment', controller)
49-
)
50-
instances.append(
51-
{
52-
'openmetrics_endpoint': 'http://{}:{}/metrics'.format(host, port),
53-
}
54-
)
55-
56-
yield {'instances': instances}
76+
instances = [
77+
{
78+
'openmetrics_endpoint': f'http://{get_state(POD_IP_STATE_PREFIX + controller)}:{METRICS_PORT}/metrics',
79+
}
80+
for controller in CONTROLLERS
81+
]
82+
83+
metadata = {'agent_type': 'kubernetes', 'kubernetes': {'kubeconfig': kubeconfig}}
84+
85+
yield {'instances': instances}, metadata
5786

5887

5988
@pytest.fixture

0 commit comments

Comments
 (0)