Skip to content

Commit 674aee7

Browse files
committed
add tests
Signed-off-by: oliver könig <okoenig@nvidia.com>
1 parent 8cf5f42 commit 674aee7

1 file changed

Lines changed: 186 additions & 14 deletions

File tree

test/run/ray/test_kuberay.py

Lines changed: 186 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,6 @@ def test_create_basic_cluster(self, cluster_with_basic_executor, mock_k8s_client
217217
assert body["metadata"]["name"] == "testuser-test-cluster-raycluster"
218218
assert body["metadata"]["namespace"] == "test-namespace"
219219
assert body["spec"]["rayVersion"] == "2.43.0"
220-
221220
def test_create_advanced_cluster(self, cluster_with_advanced_executor, mock_k8s_clients):
222221
"""Test creating an advanced Ray cluster with volumes and custom settings."""
223222
mock_api, _ = mock_k8s_clients
@@ -748,11 +747,9 @@ class TestKubeRayExecutorUtilityFunctions:
748747
@pytest.fixture
749748
def basic_cluster_dict(self):
750749
"""Create a basic cluster dictionary for testing."""
751-
from nemo_run.core.execution.kuberay import (
752-
populate_meta,
753-
populate_ray_head,
754-
populate_worker_group,
755-
)
750+
from nemo_run.core.execution.kuberay import (populate_meta,
751+
populate_ray_head,
752+
populate_worker_group)
756753

757754
cluster = {}
758755
cluster = populate_meta(cluster, "test-cluster", "default", {}, "2.43.0")
@@ -866,7 +863,8 @@ def test_populate_ray_head_missing_spec(self):
866863

867864
def test_populate_ray_head_without_dashboard_host(self):
868865
"""Test populate_ray_head automatically adds dashboard-host."""
869-
from nemo_run.core.execution.kuberay import populate_meta, populate_ray_head
866+
from nemo_run.core.execution.kuberay import (populate_meta,
867+
populate_ray_head)
870868

871869
cluster = populate_meta({}, "test-cluster", "default", {}, "2.43.0")
872870
ray_start_params = {}
@@ -893,7 +891,8 @@ def test_populate_ray_head_without_dashboard_host(self):
893891

894892
def test_update_worker_group_replicas_success(self, basic_cluster_dict):
895893
"""Test successfully updating worker group replicas."""
896-
from nemo_run.core.execution.kuberay import update_worker_group_replicas
894+
from nemo_run.core.execution.kuberay import \
895+
update_worker_group_replicas
897896

898897
cluster, success = update_worker_group_replicas(
899898
basic_cluster_dict, "workers", max_replicas=5, min_replicas=1, replicas=3
@@ -907,7 +906,8 @@ def test_update_worker_group_replicas_success(self, basic_cluster_dict):
907906

908907
def test_update_worker_group_replicas_not_found(self, basic_cluster_dict):
909908
"""Test updating non-existent worker group replicas."""
910-
from nemo_run.core.execution.kuberay import update_worker_group_replicas
909+
from nemo_run.core.execution.kuberay import \
910+
update_worker_group_replicas
911911

912912
cluster, success = update_worker_group_replicas(
913913
basic_cluster_dict, "nonexistent", max_replicas=5, min_replicas=1, replicas=3
@@ -917,7 +917,8 @@ def test_update_worker_group_replicas_not_found(self, basic_cluster_dict):
917917

918918
def test_update_worker_group_resources_success(self, basic_cluster_dict):
919919
"""Test successfully updating worker group resources."""
920-
from nemo_run.core.execution.kuberay import update_worker_group_resources
920+
from nemo_run.core.execution.kuberay import \
921+
update_worker_group_resources
921922

922923
cluster, success = update_worker_group_resources(
923924
basic_cluster_dict,
@@ -937,7 +938,8 @@ def test_update_worker_group_resources_success(self, basic_cluster_dict):
937938

938939
def test_update_worker_group_resources_all_containers(self, basic_cluster_dict):
939940
"""Test updating resources for all containers in a worker group."""
940-
from nemo_run.core.execution.kuberay import update_worker_group_resources
941+
from nemo_run.core.execution.kuberay import \
942+
update_worker_group_resources
941943

942944
# Add another container to test "all_containers" functionality
943945
basic_cluster_dict["spec"]["workerGroupSpecs"][0]["template"]["spec"]["containers"].append(
@@ -966,7 +968,8 @@ def test_update_worker_group_resources_all_containers(self, basic_cluster_dict):
966968

967969
def test_update_worker_group_resources_specific_container(self, basic_cluster_dict):
968970
"""Test updating resources for a specific container."""
969-
from nemo_run.core.execution.kuberay import update_worker_group_resources
971+
from nemo_run.core.execution.kuberay import \
972+
update_worker_group_resources
970973

971974
# Add another container
972975
basic_cluster_dict["spec"]["workerGroupSpecs"][0]["template"]["spec"]["containers"].append(
@@ -993,7 +996,8 @@ def test_update_worker_group_resources_specific_container(self, basic_cluster_di
993996

994997
def test_update_worker_group_resources_no_containers(self):
995998
"""Test updating resources when worker group has no containers."""
996-
from nemo_run.core.execution.kuberay import update_worker_group_resources
999+
from nemo_run.core.execution.kuberay import \
1000+
update_worker_group_resources
9971001

9981002
cluster = {
9991003
"spec": {
@@ -1063,7 +1067,8 @@ def test_delete_worker_group_not_found(self, basic_cluster_dict):
10631067

10641068
def test_worker_group_with_labels_and_annotations(self):
10651069
"""Test creating worker group with labels and annotations."""
1066-
from nemo_run.core.execution.kuberay import populate_meta, populate_worker_group
1070+
from nemo_run.core.execution.kuberay import (populate_meta,
1071+
populate_worker_group)
10671072

10681073
cluster = populate_meta({}, "test-cluster", "default", {}, "2.43.0")
10691074
cluster["spec"]["workerGroupSpecs"] = []
@@ -2074,3 +2079,170 @@ def test_cluster_create_without_lifecycle_kwargs(self, mock_k8s_clients):
20742079
# Should create lifecycle_kwargs and succeed
20752080
assert hasattr(executor, "lifecycle_kwargs")
20762081
assert mock_api.create_namespaced_custom_object.called
2082+
2083+
2084+
class TestKubeConfigLoading:
2085+
"""Test kube config loading fallback scenarios."""
2086+
2087+
def test_kuberay_cluster_load_kube_config_success(self):
2088+
"""Test successful loading of kube config for KubeRayCluster."""
2089+
with patch("nemo_run.run.ray.kuberay.config.load_kube_config") as mock_load_kube:
2090+
with patch("nemo_run.run.ray.kuberay.client.CustomObjectsApi"):
2091+
with patch("nemo_run.run.ray.kuberay.client.CoreV1Api"):
2092+
with patch("nemo_run.run.ray.kuberay.get_user", return_value="testuser"):
2093+
executor = KubeRayExecutor(namespace="test-namespace")
2094+
cluster = KubeRayCluster(name="test-cluster", executor=executor)
2095+
2096+
# Verify load_kube_config was called and succeeded
2097+
mock_load_kube.assert_called_once()
2098+
2099+
def test_kuberay_cluster_fallback_to_incluster_config(self):
2100+
"""Test fallback to incluster config when kube config fails for KubeRayCluster."""
2101+
with patch(
2102+
"nemo_run.run.ray.kuberay.config.load_kube_config",
2103+
side_effect=Exception("Kube config not found"),
2104+
) as mock_load_kube:
2105+
with patch(
2106+
"nemo_run.run.ray.kuberay.config.load_incluster_config"
2107+
) as mock_load_incluster:
2108+
with patch("nemo_run.run.ray.kuberay.client.CustomObjectsApi"):
2109+
with patch("nemo_run.run.ray.kuberay.client.CoreV1Api"):
2110+
with patch("nemo_run.run.ray.kuberay.get_user", return_value="testuser"):
2111+
executor = KubeRayExecutor(namespace="test-namespace")
2112+
cluster = KubeRayCluster(name="test-cluster", executor=executor)
2113+
2114+
# Verify fallback to incluster config
2115+
mock_load_kube.assert_called_once()
2116+
mock_load_incluster.assert_called_once()
2117+
2118+
def test_kuberay_cluster_both_configs_fail(self):
2119+
"""Test when both kube config and incluster config fail for KubeRayCluster."""
2120+
kube_config_error = Exception("Kube config not found")
2121+
incluster_config_error = Exception("Not running in cluster")
2122+
2123+
with patch(
2124+
"nemo_run.run.ray.kuberay.config.load_kube_config", side_effect=kube_config_error
2125+
):
2126+
with patch(
2127+
"nemo_run.run.ray.kuberay.config.load_incluster_config",
2128+
side_effect=incluster_config_error,
2129+
):
2130+
with pytest.raises(Exception) as exc_info:
2131+
with patch("nemo_run.run.ray.kuberay.get_user", return_value="testuser"):
2132+
executor = KubeRayExecutor(namespace="test-namespace")
2133+
KubeRayCluster(name="test-cluster", executor=executor)
2134+
2135+
# Should raise the original kube config error
2136+
assert exc_info.value == kube_config_error
2137+
2138+
def test_kuberay_job_load_kube_config_success(self):
2139+
"""Test successful loading of kube config for KubeRayJob."""
2140+
with patch("nemo_run.run.ray.kuberay.config.load_kube_config") as mock_load_kube:
2141+
with patch("nemo_run.run.ray.kuberay.client.CustomObjectsApi"):
2142+
with patch("nemo_run.run.ray.kuberay.client.CoreV1Api"):
2143+
with patch("nemo_run.run.ray.kuberay.get_user", return_value="testuser"):
2144+
executor = KubeRayExecutor(namespace="test-namespace")
2145+
job = KubeRayJob(name="test-job", executor=executor)
2146+
2147+
# Verify load_kube_config was called and succeeded
2148+
mock_load_kube.assert_called()
2149+
2150+
def test_kuberay_job_fallback_to_incluster_config(self):
2151+
"""Test fallback to incluster config when kube config fails for KubeRayJob."""
2152+
with patch(
2153+
"nemo_run.run.ray.kuberay.config.load_kube_config",
2154+
side_effect=Exception("Kube config not found"),
2155+
) as mock_load_kube:
2156+
with patch(
2157+
"nemo_run.run.ray.kuberay.config.load_incluster_config"
2158+
) as mock_load_incluster:
2159+
with patch("nemo_run.run.ray.kuberay.client.CustomObjectsApi"):
2160+
with patch("nemo_run.run.ray.kuberay.client.CoreV1Api"):
2161+
with patch("nemo_run.run.ray.kuberay.get_user", return_value="testuser"):
2162+
executor = KubeRayExecutor(namespace="test-namespace")
2163+
job = KubeRayJob(name="test-job", executor=executor)
2164+
2165+
# Verify fallback to incluster config
2166+
# Called twice: once for executor, once for job
2167+
assert mock_load_kube.call_count >= 1
2168+
assert mock_load_incluster.call_count >= 1
2169+
2170+
def test_kuberay_job_both_configs_fail(self):
2171+
"""Test when both kube config and incluster config fail for KubeRayJob."""
2172+
kube_config_error = Exception("Kube config not found")
2173+
incluster_config_error = Exception("Not running in cluster")
2174+
2175+
with patch(
2176+
"nemo_run.run.ray.kuberay.config.load_kube_config", side_effect=kube_config_error
2177+
):
2178+
with patch(
2179+
"nemo_run.run.ray.kuberay.config.load_incluster_config",
2180+
side_effect=incluster_config_error,
2181+
):
2182+
with pytest.raises(Exception) as exc_info:
2183+
with patch("nemo_run.run.ray.kuberay.get_user", return_value="testuser"):
2184+
executor = KubeRayExecutor(namespace="test-namespace")
2185+
KubeRayJob(name="test-job", executor=executor)
2186+
2187+
# Should raise the original kube config error
2188+
assert exc_info.value == kube_config_error
2189+
2190+
def test_executor_load_kube_config_success(self):
2191+
"""Test successful loading of kube config for KubeRayExecutor."""
2192+
with patch(
2193+
"nemo_run.core.execution.kuberay.config.load_kube_config"
2194+
) as mock_load_kube:
2195+
with patch("nemo_run.core.execution.kuberay.client.CustomObjectsApi"):
2196+
with patch("nemo_run.core.execution.kuberay.client.CoreV1Api"):
2197+
executor = KubeRayExecutor(namespace="test-namespace")
2198+
2199+
# Verify load_kube_config was called and succeeded
2200+
mock_load_kube.assert_called_once()
2201+
2202+
def test_executor_fallback_to_incluster_config(self):
2203+
"""Test fallback to incluster config when kube config fails for KubeRayExecutor."""
2204+
with patch(
2205+
"nemo_run.core.execution.kuberay.config.load_kube_config",
2206+
side_effect=Exception("Kube config not found"),
2207+
) as mock_load_kube:
2208+
with patch(
2209+
"nemo_run.core.execution.kuberay.config.load_incluster_config"
2210+
) as mock_load_incluster:
2211+
with patch("nemo_run.core.execution.kuberay.client.CustomObjectsApi"):
2212+
with patch("nemo_run.core.execution.kuberay.client.CoreV1Api"):
2213+
executor = KubeRayExecutor(namespace="test-namespace")
2214+
2215+
# Verify fallback to incluster config
2216+
mock_load_kube.assert_called_once()
2217+
mock_load_incluster.assert_called_once()
2218+
2219+
def test_executor_both_configs_fail(self):
2220+
"""Test when both kube config and incluster config fail for KubeRayExecutor."""
2221+
kube_config_error = Exception("Kube config not found")
2222+
incluster_config_error = Exception("Not running in cluster")
2223+
2224+
with patch(
2225+
"nemo_run.core.execution.kuberay.config.load_kube_config",
2226+
side_effect=kube_config_error,
2227+
):
2228+
with patch(
2229+
"nemo_run.core.execution.kuberay.config.load_incluster_config",
2230+
side_effect=incluster_config_error,
2231+
):
2232+
with pytest.raises(Exception) as exc_info:
2233+
KubeRayExecutor(namespace="test-namespace")
2234+
2235+
# Should raise the original kube config error
2236+
assert exc_info.value == kube_config_error
2237+
):
2238+
with pytest.raises(Exception) as exc_info:
2239+
KubeRayExecutor(namespace="test-namespace")
2240+
2241+
# Should raise the original kube config error
2242+
assert exc_info.value == kube_config_error
2243+
):
2244+
with pytest.raises(Exception) as exc_info:
2245+
KubeRayExecutor(namespace="test-namespace")
2246+
2247+
# Should raise the original kube config error
2248+
assert exc_info.value == kube_config_error

0 commit comments

Comments
 (0)