Skip to content

Commit 7d627a7

Browse files
laurafitzgeraldchipspeak
authored andcommitted
make local_queue optional
1 parent 028d0d5 commit 7d627a7

File tree

3 files changed

+132
-18
lines changed

3 files changed

+132
-18
lines changed

src/codeflare_sdk/common/kueue/kueue.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from codeflare_sdk.common.kubernetes_cluster.auth import config_check, get_api_client
1818
from kubernetes import client
1919
from kubernetes.client.exceptions import ApiException
20+
import warnings
2021

2122

2223
def get_default_kueue_name(namespace: str) -> Optional[str]:
@@ -157,18 +158,24 @@ def add_queue_label(item: dict, namespace: str, local_queue: Optional[str]):
157158
The namespace of the local queue.
158159
local_queue (str, optional):
159160
The name of the local queue to use. Defaults to None.
160-
161-
Raises:
162-
ValueError:
163-
If the provided or default local queue does not exist in the namespace.
164161
"""
165162
lq_name = local_queue or get_default_kueue_name(namespace)
166163
if lq_name == None:
167164
return
168165
elif not local_queue_exists(namespace, lq_name):
169-
raise ValueError(
170-
"local_queue provided does not exist or is not in this namespace. Please provide the correct local_queue name in Cluster Configuration"
166+
available_queues = list_local_queues(namespace)
167+
if available_queues is None:
168+
warnings.warn(
169+
f"Local queue '{local_queue}' does not exist in namespace '{namespace}'. "
170+
"Unable to retrieve list of available queues."
171+
)
172+
return
173+
available_queue_names = [q["name"] for q in available_queues]
174+
warnings.warn(
175+
f"Local queue '{local_queue}' does not exist in namespace '{namespace}'. "
176+
f"Available queues are: {', '.join(available_queue_names)}"
171177
)
178+
return
172179
if not "labels" in item["metadata"]:
173180
item["metadata"]["labels"] = {}
174181
item["metadata"]["labels"].update({"kueue.x-k8s.io/queue-name": lq_name})

src/codeflare_sdk/common/kueue/test_kueue.py

Lines changed: 101 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,14 @@ def test_get_local_queue_exists_fail(mocker):
118118
)
119119
mocker.patch(
120120
"kubernetes.client.CustomObjectsApi.list_namespaced_custom_object",
121-
return_value=get_local_queue("kueue.x-k8s.io", "v1beta1", "ns", "localqueues"),
121+
return_value={
122+
"items": [
123+
{
124+
"metadata": {"name": "local-queue-default"},
125+
"status": {"flavors": [{"name": "default"}]},
126+
}
127+
]
128+
},
122129
)
123130
config = create_cluster_config()
124131
config.name = "unit-test-aw-kueue"
@@ -267,15 +274,99 @@ def test_add_queue_label_with_valid_local_queue(mocker):
267274
assert item["metadata"]["labels"] == {"kueue.x-k8s.io/queue-name": "valid-queue"}
268275

269276

270-
def test_add_queue_label_with_invalid_local_queue(mocker):
277+
def test_add_queue_label_with_invalid_local_queue_shows_available_queues(mocker):
271278
# Mock the kubernetes.client.CustomObjectsApi and its response
272279
mock_api_instance = mocker.patch("kubernetes.client.CustomObjectsApi")
273280
mock_api_instance.return_value.list_namespaced_custom_object.return_value = {
274281
"items": [
275-
{"metadata": {"name": "valid-queue"}},
282+
{"metadata": {"name": "queue1"}, "status": {"flavors": [{"name": "default"}]}},
283+
{"metadata": {"name": "queue2"}, "status": {"flavors": [{"name": "default"}]}},
284+
]
285+
}
286+
287+
# Mock the local_queue_exists function to return False
288+
mocker.patch("codeflare_sdk.common.kueue.local_queue_exists", return_value=False)
289+
290+
# Define input item and parameters
291+
item = {"metadata": {}}
292+
namespace = "test-namespace"
293+
local_queue = "invalid-queue"
294+
295+
# Call the function and expect a warning with available queues in the message
296+
with pytest.warns(
297+
UserWarning,
298+
match=f"Local queue '{local_queue}' does not exist in namespace '{namespace}'. Available queues are: queue1, queue2",
299+
):
300+
add_queue_label(item, namespace, local_queue)
301+
302+
# Assert that no label is added
303+
assert "labels" not in item["metadata"]
304+
305+
306+
def test_add_queue_label_with_no_local_queue(mocker):
307+
# Mock the kubernetes.client.CustomObjectsApi and its response
308+
mock_api_instance = mocker.patch("kubernetes.client.CustomObjectsApi")
309+
mock_api_instance.return_value.list_namespaced_custom_object.return_value = {
310+
"items": []
311+
}
312+
313+
# Mock get_default_kueue_name to return None
314+
mocker.patch(
315+
"codeflare_sdk.common.kueue.get_default_kueue_name",
316+
return_value=None,
317+
)
318+
319+
# Define input item and parameters
320+
item = {"metadata": {}}
321+
namespace = "test-namespace"
322+
local_queue = None
323+
324+
# Call the function
325+
add_queue_label(item, namespace, local_queue)
326+
327+
# Assert that no label is added
328+
assert "labels" not in item["metadata"]
329+
330+
331+
def test_add_queue_label_with_default_queue(mocker):
332+
# Mock the kubernetes.client.CustomObjectsApi and its response
333+
mock_api_instance = mocker.patch("kubernetes.client.CustomObjectsApi")
334+
mock_api_instance.return_value.list_namespaced_custom_object.return_value = {
335+
"items": [
336+
{
337+
"metadata": {
338+
"name": "default-queue",
339+
"annotations": {"kueue.x-k8s.io/default-queue": "true"}
340+
}
341+
}
276342
]
277343
}
278344

345+
# Mock get_default_kueue_name to return a default queue
346+
mocker.patch(
347+
"codeflare_sdk.common.kueue.get_default_kueue_name",
348+
return_value="default-queue",
349+
)
350+
351+
# Define input item and parameters
352+
item = {"metadata": {}}
353+
namespace = "test-namespace"
354+
local_queue = None
355+
356+
# Call the function
357+
add_queue_label(item, namespace, local_queue)
358+
359+
# Assert that the default queue label is added
360+
assert item["metadata"]["labels"] == {"kueue.x-k8s.io/queue-name": "default-queue"}
361+
362+
363+
def test_add_queue_label_with_invalid_local_queue_and_no_available_queues(mocker):
364+
# Mock the kubernetes.client.CustomObjectsApi and its response
365+
mock_api_instance = mocker.patch("kubernetes.client.CustomObjectsApi")
366+
mock_api_instance.return_value.list_namespaced_custom_object.return_value = {
367+
"items": [] # Empty list instead of None
368+
}
369+
279370
# Mock the local_queue_exists function to return False
280371
mocker.patch("codeflare_sdk.common.kueue.local_queue_exists", return_value=False)
281372

@@ -284,13 +375,16 @@ def test_add_queue_label_with_invalid_local_queue(mocker):
284375
namespace = "test-namespace"
285376
local_queue = "invalid-queue"
286377

287-
# Call the function and expect a ValueError
288-
with pytest.raises(
289-
ValueError,
290-
match="local_queue provided does not exist or is not in this namespace",
378+
# Call the function and expect a warning about unavailable queues
379+
with pytest.warns(
380+
UserWarning,
381+
match=f"Local queue '{local_queue}' does not exist in namespace '{namespace}'. Available queues are:",
291382
):
292383
add_queue_label(item, namespace, local_queue)
293384

385+
# Assert that no label is added
386+
assert "labels" not in item["metadata"]
387+
294388

295389
# Make sure to always keep this function last
296390
def test_cleanup():

src/codeflare_sdk/ray/cluster/build_ray_cluster.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
(in the cluster sub-module) for RayCluster/AppWrapper generation.
1818
"""
1919
from typing import List, Union, Tuple, Dict
20+
21+
from ...common.kueue.kueue import list_local_queues
2022
from ...common import _kube_api_error_handling
2123
from ...common.kubernetes_cluster import get_api_client, config_check
2224
from kubernetes.client.exceptions import ApiException
@@ -482,15 +484,26 @@ def head_worker_extended_resources_from_cluster(
482484
# Local Queue related functions
483485
def add_queue_label(cluster: "codeflare_sdk.ray.cluster.Cluster", labels: dict):
484486
"""
485-
The add_queue_label() function updates the given base labels with the local queue label if Kueue exists on the Cluster
487+
The add_queue_label() function updates the given base labels with the local queue label if Kueue exists on the Cluster.
488+
If no local_queue is provided, no queue label will be added.
486489
"""
487490
lq_name = cluster.config.local_queue or get_default_local_queue(cluster, labels)
488-
if lq_name == None:
491+
if lq_name is None:
489492
return
490-
elif not local_queue_exists(cluster):
491-
raise ValueError(
492-
"local_queue provided does not exist or is not in this namespace. Please provide the correct local_queue name in Cluster Configuration"
493+
elif cluster.config.local_queue and not local_queue_exists(cluster):
494+
available_queues = list_local_queues(cluster.config.namespace)
495+
if available_queues is None:
496+
print(
497+
f"WARNING: Local queue '{cluster.config.local_queue}' does not exist in namespace '{cluster.config.namespace}'. "
498+
"Unable to retrieve list of available queues."
499+
)
500+
return
501+
available_queue_names = [q["name"] for q in available_queues]
502+
print(
503+
f"WARNING: Local queue '{cluster.config.local_queue}' does not exist in namespace '{cluster.config.namespace}'. "
504+
f"Available queues are: {', '.join(available_queue_names)}"
493505
)
506+
return
494507
labels.update({"kueue.x-k8s.io/queue-name": lq_name})
495508

496509

0 commit comments

Comments
 (0)