From 76e1a88b2db76230d75a6a1a06eaa38625bfc0e0 Mon Sep 17 00:00:00 2001 From: Vincent Whitchurch Date: Tue, 11 Aug 2026 14:17:22 +0000 Subject: [PATCH 1/3] Run Argo Workflows E2E with the Kubernetes Agent backend Convert the argo_workflows E2E environment to run the Agent inside the Kind cluster instead of port-forwarding from the host. Since workflow-controller has no backing Service, the pod IP is fetched directly via kubectl and used to build the openmetrics_endpoint. Environment: Datadog workspace Co-Authored-By: Claude Sonnet 5 --- argo_workflows/tests/conftest.py | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/argo_workflows/tests/conftest.py b/argo_workflows/tests/conftest.py index 097d6692644c4..386f2a9d2f5d9 100644 --- a/argo_workflows/tests/conftest.py +++ b/argo_workflows/tests/conftest.py @@ -1,14 +1,13 @@ # (C) Datadog, Inc. 2024-present # All rights reserved # Licensed under a 3-clause BSD style license (see LICENSE) +import json import os -from contextlib import ExitStack import pytest from datadog_checks.dev import get_here from datadog_checks.dev.kind import kind_run -from datadog_checks.dev.kube_port_forward import port_forward from datadog_checks.dev.subprocess import run_command HERE = get_here() @@ -23,18 +22,26 @@ def setup_argo_wf(): # run_command(["kubectl", "wait", "pods", "--all", "--for=condition=Ready", "--timeout=300s"]) +def get_workflow_controller_pod_ip() -> str: + # There is no Service for workflow-controller, so the pod IP is fetched directly. + result = run_command( + ["kubectl", "get", "pods", "--namespace", "argo", "--selector", "app=workflow-controller", "--output", "json"], + capture='out', + check=True, + ) + pods = json.loads(result.stdout)['items'] + if len(pods) != 1 or not pods[0].get('status', {}).get('podIP'): + raise RuntimeError(f'Expected exactly one ready workflow-controller pod, found {len(pods)}') + return pods[0]['status']['podIP'] + + @pytest.fixture(scope='session') def dd_environment(): with kind_run(conditions=[setup_argo_wf]) as kubeconfig: - with ExitStack() as stack: - controller_host, controller_port = stack.enter_context( - # there is no service for workflow-controller - port_forward(kubeconfig, 'argo', 9090, 'deployment', 'workflow-controller') - ) - # save this instance to use for openmetrics_v2 instance, since the endpoint is different each run - # dd_save_state("argocd_instance", instance) - - yield {'openmetrics_endpoint': f'http://{controller_host}:{controller_port}/metrics'} + controller_ip = get_workflow_controller_pod_ip() + metadata = {'agent_type': 'kubernetes', 'kubernetes': {'kubeconfig': kubeconfig}} + + yield {'openmetrics_endpoint': f'http://{controller_ip}:9090/metrics'}, metadata @pytest.fixture From 0a45fc3fb4a52290db6c78a06a41abcba6941de7 Mon Sep 17 00:00:00 2001 From: Vincent Whitchurch Date: Tue, 11 Aug 2026 14:39:34 +0000 Subject: [PATCH 2/3] Cache the workflow-controller pod IP to fix ddev env stop CI failed because dd_environment re-runs get_workflow_controller_pod_ip() on every invocation, including the one ddev env stop uses to tear down the fixture after the Kind cluster is already deleted. Resolve the pod IP once inside setup_argo_wf (which only runs on cluster creation) and cache it with save_state/get_state, matching the pattern used by velero's node-agent lookup. Environment: Datadog workspace Co-Authored-By: Claude Sonnet 5 --- argo_workflows/tests/conftest.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/argo_workflows/tests/conftest.py b/argo_workflows/tests/conftest.py index 386f2a9d2f5d9..257058f44fd4a 100644 --- a/argo_workflows/tests/conftest.py +++ b/argo_workflows/tests/conftest.py @@ -7,11 +7,14 @@ import pytest from datadog_checks.dev import get_here +from datadog_checks.dev._env import get_state, save_state from datadog_checks.dev.kind import kind_run from datadog_checks.dev.subprocess import run_command HERE = get_here() +CONTROLLER_IP_STATE = 'argo_workflows_controller_ip' + def setup_argo_wf(): run_command(["kubectl", "create", "ns", "argo"]) @@ -21,6 +24,11 @@ def setup_argo_wf(): ) # run_command(["kubectl", "wait", "pods", "--all", "--for=condition=Ready", "--timeout=300s"]) + # This only runs once, when the Kind cluster is created, so the resolved pod IP is cached here + # rather than re-resolved by `dd_environment` on every invocation (e.g. `ddev env stop`, which + # runs in a fresh process after the cluster has already been torn down). + save_state(CONTROLLER_IP_STATE, get_workflow_controller_pod_ip()) + def get_workflow_controller_pod_ip() -> str: # There is no Service for workflow-controller, so the pod IP is fetched directly. @@ -38,7 +46,7 @@ def get_workflow_controller_pod_ip() -> str: @pytest.fixture(scope='session') def dd_environment(): with kind_run(conditions=[setup_argo_wf]) as kubeconfig: - controller_ip = get_workflow_controller_pod_ip() + controller_ip = get_state(CONTROLLER_IP_STATE) metadata = {'agent_type': 'kubernetes', 'kubernetes': {'kubeconfig': kubeconfig}} yield {'openmetrics_endpoint': f'http://{controller_ip}:9090/metrics'}, metadata From a686e38c11d80f0dbde702f3dce15844721dc586 Mon Sep 17 00:00:00 2001 From: Vincent Whitchurch Date: Wed, 12 Aug 2026 09:58:59 +0200 Subject: [PATCH 3/3] Fix comment --- argo_workflows/tests/conftest.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/argo_workflows/tests/conftest.py b/argo_workflows/tests/conftest.py index 257058f44fd4a..21e77680a0fe3 100644 --- a/argo_workflows/tests/conftest.py +++ b/argo_workflows/tests/conftest.py @@ -25,8 +25,7 @@ def setup_argo_wf(): # run_command(["kubectl", "wait", "pods", "--all", "--for=condition=Ready", "--timeout=300s"]) # This only runs once, when the Kind cluster is created, so the resolved pod IP is cached here - # rather than re-resolved by `dd_environment` on every invocation (e.g. `ddev env stop`, which - # runs in a fresh process after the cluster has already been torn down). + # rather than re-resolved by `dd_environment` on every invocation. save_state(CONTROLLER_IP_STATE, get_workflow_controller_pod_ip())