Skip to content

Commit 915deaa

Browse files
authored
Use Kueue v1beta2 Workload API (DataDog#24563)
* Query Kueue workloads through v1beta2 Prefer the current Kueue Workload API while retaining support for clusters that expose only v1beta1. * Add Kueue changelog entry Document the Workload API compatibility fix in the release notes. * FIx formatting * Preserve Kueue priority class event tags Read the v1beta2 priority class reference while retaining compatibility with v1beta1 Workload objects.
1 parent 50cc010 commit 915deaa

5 files changed

Lines changed: 53 additions & 4 deletions

File tree

kueue/changelog.d/24563.fixed

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Use the current Kueue Workload API for workload event collection, with fallback support for older clusters.

kueue/datadog_checks/kueue/check.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,9 @@ def workload_event_tags(
334334
priority = spec.get('priority')
335335
if priority is not None:
336336
tags.append(f'kueue_workload_priority:{priority}')
337-
if priority_class := spec.get('priorityClassName'):
337+
priority_class_ref = spec.get('priorityClassRef') or {}
338+
priority_class = priority_class_ref.get('name') or spec.get('priorityClassName')
339+
if priority_class:
338340
tags.append(f'kueue_workload_priority_class:{priority_class}')
339341

340342
admission = status.get('admission', {})

kueue/datadog_checks/kueue/kube_client.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from typing import Any
77

88
from kubernetes import client, config
9+
from kubernetes.client.exceptions import ApiException
910

1011

1112
class KubernetesAPIClient:
@@ -22,17 +23,25 @@ def __init__(self, log=None, kube_config_dict: Mapping[str, Any] | None = None):
2223
self.custom_obj_client = client.CustomObjectsApi()
2324

2425
def list_workloads(self, namespace: str | None = None) -> list[dict]:
26+
try:
27+
return self.list_workloads_for_version('v1beta2', namespace)
28+
except ApiException as e:
29+
if e.status != 404:
30+
raise
31+
return self.list_workloads_for_version('v1beta1', namespace)
32+
33+
def list_workloads_for_version(self, version: str, namespace: str | None) -> list[dict]:
2534
if namespace:
2635
return self.custom_obj_client.list_namespaced_custom_object(
2736
group='kueue.x-k8s.io',
28-
version='v1beta1',
37+
version=version,
2938
namespace=namespace,
3039
plural='workloads',
3140
)['items']
3241

3342
return self.custom_obj_client.list_cluster_custom_object(
3443
group='kueue.x-k8s.io',
35-
version='v1beta1',
44+
version=version,
3645
plural='workloads',
3746
)['items']
3847

kueue/tests/fixtures/workloads/admitted.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
"spec": {
1010
"queueName": "gpu",
1111
"priority": 100,
12-
"priorityClassName": "high"
12+
"priorityClassRef": {
13+
"name": "high"
14+
}
1315
},
1416
"status": {
1517
"admission": {

kueue/tests/test_unit.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33
# Licensed under a 3-clause BSD style license (see LICENSE)
44

55
import json
6+
from unittest.mock import Mock
67

78
import pytest
9+
from kubernetes.client.exceptions import ApiException
810

911
from datadog_checks.base.stubs import tagger
1012
from datadog_checks.dev.utils import get_metadata_metrics
1113
from datadog_checks.kueue import KueueCheck
1214
from datadog_checks.kueue.check import OTHER_RESOURCE_NAME, RESOURCE_NAME_MAP
15+
from datadog_checks.kueue.kube_client import KubernetesAPIClient
1316
from datadog_checks.kueue.metrics import LOCAL_QUEUE_METRIC_MAP, METRIC_MAP, RESOURCE_METRIC_MAP
1417

1518
from .common import EXPECTED_METRIC_TAGS, UNIT_METRICS, get_fixture_path
@@ -150,6 +153,23 @@ def test_workload_events_config_can_be_parsed_before_check(instance):
150153
assert check.collect_workload_events is True
151154

152155

156+
@pytest.mark.parametrize(
157+
('namespace', 'method_name'),
158+
[
159+
(None, 'list_cluster_custom_object'),
160+
('default', 'list_namespaced_custom_object'),
161+
],
162+
)
163+
def test_workload_api_version_fallback(namespace, method_name):
164+
kube_client = object.__new__(KubernetesAPIClient)
165+
kube_client.custom_obj_client = Mock()
166+
method = getattr(kube_client.custom_obj_client, method_name)
167+
method.side_effect = [ApiException(status=404), {'items': []}]
168+
169+
assert kube_client.list_workloads(namespace) == []
170+
assert [call.kwargs['version'] for call in method.call_args_list] == ['v1beta2', 'v1beta1']
171+
172+
153173
class FakeKubernetesAPIClient:
154174
def __init__(self, *workload_snapshots):
155175
self.workload_snapshots = list(workload_snapshots)
@@ -196,6 +216,21 @@ def test_workload_events_suppress_first_poll(dd_run_check, aggregator, instance,
196216
assert not aggregator.events
197217

198218

219+
@pytest.mark.parametrize(
220+
('spec', 'priority_class'),
221+
[
222+
({'priorityClassName': 'v1beta1'}, 'v1beta1'),
223+
({'priorityClassName': 'v1beta1', 'priorityClassRef': {'name': 'v1beta2'}}, 'v1beta2'),
224+
],
225+
)
226+
def test_workload_event_tags_priority_class(instance, spec, priority_class):
227+
check = KueueCheck('kueue', {}, [instance])
228+
229+
tags = check.workload_event_tags('admitted', {'spec': spec}, None)
230+
231+
assert f'kueue_workload_priority_class:{priority_class}' in tags
232+
233+
199234
def test_workload_events_transitions(dd_run_check, aggregator, instance, mock_http_response):
200235
mock_http_response(file_path=get_fixture_path('metrics.txt'))
201236
tagger.reset()

0 commit comments

Comments
 (0)