@@ -76,11 +76,87 @@ def test_get_graph_deployment_from_name(k8s_api, mock_custom_api):
7676 )
7777
7878
79- def test_update_graph_replicas (k8s_api , mock_custom_api ):
79+ def test_update_service_replicas_uses_dgdsa_scale (k8s_api , mock_custom_api ):
80+ """Test that update_service_replicas uses DGDSA Scale API when available"""
81+ mock_custom_api .patch_namespaced_custom_object_scale .return_value = None
82+
83+ k8s_api .update_service_replicas ("test-deployment" , "Frontend" , 3 )
84+
85+ # Should use Scale subresource with lowercase adapter name
86+ mock_custom_api .patch_namespaced_custom_object_scale .assert_called_once_with (
87+ group = "nvidia.com" ,
88+ version = "v1alpha1" ,
89+ namespace = k8s_api .current_namespace ,
90+ plural = "dynamographdeploymentscalingadapters" ,
91+ name = "test-deployment-frontend" , # lowercase service name
92+ body = {"spec" : {"replicas" : 3 }},
93+ )
94+ # Should NOT fall back to DGD patch
95+ mock_custom_api .patch_namespaced_custom_object .assert_not_called ()
96+
97+
98+ def test_update_service_replicas_fallback_to_dgd (k8s_api , mock_custom_api ):
99+ """Test that update_service_replicas falls back to DGD when DGDSA not found"""
100+ # DGDSA doesn't exist (404)
101+ mock_custom_api .patch_namespaced_custom_object_scale .side_effect = (
102+ client .ApiException (status = 404 )
103+ )
80104 mock_custom_api .patch_namespaced_custom_object .return_value = None
81105
106+ k8s_api .update_service_replicas ("test-deployment" , "test-component" , 1 )
107+
108+ # Should have tried DGDSA first
109+ mock_custom_api .patch_namespaced_custom_object_scale .assert_called_once ()
110+
111+ # Should fall back to DGD patch
112+ mock_custom_api .patch_namespaced_custom_object .assert_called_once_with (
113+ group = "nvidia.com" ,
114+ version = "v1alpha1" ,
115+ namespace = k8s_api .current_namespace ,
116+ plural = "dynamographdeployments" ,
117+ name = "test-deployment" ,
118+ body = {"spec" : {"services" : {"test-component" : {"replicas" : 1 }}}},
119+ )
120+
121+
122+ def test_update_service_replicas_propagates_other_errors (k8s_api , mock_custom_api ):
123+ """Test that update_service_replicas propagates non-404 errors"""
124+ mock_custom_api .patch_namespaced_custom_object_scale .side_effect = (
125+ client .ApiException (status = 500 , reason = "Internal Server Error" )
126+ )
127+
128+ with pytest .raises (client .ApiException ) as exc_info :
129+ k8s_api .update_service_replicas ("test-deployment" , "test-component" , 1 )
130+
131+ assert exc_info .value .status == 500
132+ # Should NOT fall back to DGD
133+ mock_custom_api .patch_namespaced_custom_object .assert_not_called ()
134+
135+
136+ def test_update_graph_replicas_calls_update_service_replicas (k8s_api , mock_custom_api ):
137+ """Test that deprecated update_graph_replicas calls update_service_replicas"""
138+ mock_custom_api .patch_namespaced_custom_object_scale .return_value = None
139+
140+ # Use the deprecated method
82141 k8s_api .update_graph_replicas ("test-deployment" , "test-component" , 1 )
83142
143+ # Should delegate to update_service_replicas which uses Scale API
144+ mock_custom_api .patch_namespaced_custom_object_scale .assert_called_once_with (
145+ group = "nvidia.com" ,
146+ version = "v1alpha1" ,
147+ namespace = k8s_api .current_namespace ,
148+ plural = "dynamographdeploymentscalingadapters" ,
149+ name = "test-deployment-test-component" ,
150+ body = {"spec" : {"replicas" : 1 }},
151+ )
152+
153+
154+ def test_update_dgd_replicas_directly (k8s_api , mock_custom_api ):
155+ """Test the internal _update_dgd_replicas method"""
156+ mock_custom_api .patch_namespaced_custom_object .return_value = None
157+
158+ k8s_api ._update_dgd_replicas ("test-deployment" , "test-component" , 1 )
159+
84160 mock_custom_api .patch_namespaced_custom_object .assert_called_once_with (
85161 group = "nvidia.com" ,
86162 version = "v1alpha1" ,
0 commit comments