44
55from kafka .admin import OffsetSpec , KafkaAdminClient
66from kafka .errors import (
7+ InvalidPartitionsError ,
78 NotLeaderForPartitionError ,
89 UnknownTopicOrPartitionError ,
910 IncompatibleBrokerVersion ,
2526
2627
2728class TestAlterPartitionReassignmentsMockBroker :
28- def test_success_returns_dict (self , broker , admin ):
29+ def test_success_returns_per_partition_none (self , broker , admin ):
2930 Topic = AlterPartitionReassignmentsResponse .ReassignableTopicResponse
3031 Partition = Topic .ReassignablePartitionResponse
3132 broker .respond (
@@ -39,6 +40,7 @@ def test_success_returns_dict(self, broker, admin):
3940 name = 'topic-a' ,
4041 partitions = [
4142 Partition (partition_index = 0 , error_code = 0 , error_message = None ),
43+ Partition (partition_index = 1 , error_code = 0 , error_message = None ),
4244 ],
4345 ),
4446 ],
@@ -47,11 +49,13 @@ def test_success_returns_dict(self, broker, admin):
4749
4850 result = admin .alter_partition_reassignments ({
4951 TopicPartition ('topic-a' , 0 ): [1 , 2 , 3 ],
52+ TopicPartition ('topic-a' , 1 ): [4 , 5 , 6 ],
5053 })
5154
52- assert result ['error_code' ] == 0
53- assert result ['responses' ][0 ]['name' ] == 'topic-a'
54- assert result ['responses' ][0 ]['partitions' ][0 ]['error_code' ] == 0
55+ assert result == {
56+ TopicPartition ('topic-a' , 0 ): None ,
57+ TopicPartition ('topic-a' , 1 ): None ,
58+ }
5559
5660 def test_cancel_reassignment_sends_null_replicas (self , broker , admin ):
5761 captured = {}
@@ -66,7 +70,7 @@ def handler(api_key, api_version, correlation_id, request_bytes):
6670 broker .respond_fn (AlterPartitionReassignmentsRequest , handler )
6771
6872 admin .alter_partition_reassignments ({
69- TopicPartition ('topic-a' , 0 ): None , # cancel
73+ TopicPartition ('topic-a' , 0 ): None ,
7074 TopicPartition ('topic-a' , 1 ): [4 , 5 ],
7175 })
7276
@@ -77,7 +81,7 @@ def handler(api_key, api_version, correlation_id, request_bytes):
7781 assert by_index [0 ].replicas is None
7882 assert list (by_index [1 ].replicas ) == [4 , 5 ]
7983
80- def test_partition_level_error_raises (self , broker , admin ):
84+ def test_partition_level_error_returned_in_dict (self , broker , admin ):
8185 Topic = AlterPartitionReassignmentsResponse .ReassignableTopicResponse
8286 Partition = Topic .ReassignablePartitionResponse
8387 broker .respond (
@@ -90,45 +94,69 @@ def test_partition_level_error_raises(self, broker, admin):
9094 Topic (
9195 name = 'topic-a' ,
9296 partitions = [
93- Partition (partition_index = 0 , error_code = 37 , # InvalidPartitionsError
97+ Partition (partition_index = 0 , error_code = 0 , error_message = None ),
98+ Partition (partition_index = 1 , error_code = 37 ,
9499 error_message = 'bad partition' ),
95100 ],
96101 ),
97102 ],
98103 ),
99104 )
100105
106+ result = admin .alter_partition_reassignments ({
107+ TopicPartition ('topic-a' , 0 ): [1 , 2 , 3 ],
108+ TopicPartition ('topic-a' , 1 ): [4 , 5 , 6 ],
109+ })
110+
111+ assert result == {
112+ TopicPartition ('topic-a' , 0 ): None ,
113+ TopicPartition ('topic-a' , 1 ): InvalidPartitionsError ,
114+ }
115+
116+ def test_top_level_error_raises (self , broker , admin ):
117+ broker .respond (
118+ AlterPartitionReassignmentsRequest ,
119+ AlterPartitionReassignmentsResponse (
120+ throttle_time_ms = 0 ,
121+ error_code = 38 , # ClusterAuthorizationFailedError
122+ error_message = 'not authorized' ,
123+ responses = [],
124+ ),
125+ )
126+
101127 with pytest .raises (Exception ):
102128 admin .alter_partition_reassignments ({
103129 TopicPartition ('topic-a' , 0 ): [1 , 2 , 3 ],
104130 })
105131
106- def test_partition_error_suppressed_with_raise_errors_false (self , broker , admin ):
107- Topic = AlterPartitionReassignmentsResponse .ReassignableTopicResponse
108- Partition = Topic .ReassignablePartitionResponse
132+ def test_empty_replica_list_rejected (self , broker , admin ):
133+ with pytest .raises (ValueError , match = 'non-empty' ):
134+ admin .alter_partition_reassignments ({
135+ TopicPartition ('topic-a' , 0 ): [],
136+ })
137+
138+ def test_non_int_replica_rejected (self , broker , admin ):
139+ with pytest .raises (ValueError , match = 'int broker_ids' ):
140+ admin .alter_partition_reassignments ({
141+ TopicPartition ('topic-a' , 0 ): ['1' , '2' , '3' ],
142+ })
143+
144+ def test_missing_partition_response_is_absent (self , broker , admin ):
109145 broker .respond (
110146 AlterPartitionReassignmentsRequest ,
111147 AlterPartitionReassignmentsResponse (
112148 throttle_time_ms = 0 ,
113149 error_code = 0 ,
114150 error_message = None ,
115- responses = [
116- Topic (
117- name = 'topic-a' ,
118- partitions = [
119- Partition (partition_index = 0 , error_code = 37 , error_message = 'bad' ),
120- ],
121- ),
122- ],
151+ responses = [],
123152 ),
124153 )
125154
126- result = admin .alter_partition_reassignments (
127- {TopicPartition ('topic-a' , 0 ): [1 , 2 , 3 ]},
128- raise_errors = False ,
129- )
155+ result = admin .alter_partition_reassignments ({
156+ TopicPartition ('topic-a' , 0 ): [1 , 2 , 3 ],
157+ })
130158
131- assert result [ 'responses' ][ 0 ][ 'partitions' ][ 0 ][ 'error_code' ] == 37
159+ assert result == {}
132160
133161
134162# ---------------------------------------------------------------------------
@@ -242,15 +270,59 @@ def test_top_level_error_raises(self, broker, admin):
242270 ListPartitionReassignmentsRequest ,
243271 ListPartitionReassignmentsResponse (
244272 throttle_time_ms = 0 ,
245- error_code = 41 , # NotControllerError
246- error_message = 'not controller ' ,
273+ error_code = 29 , # TopicAuthorizationFailedError
274+ error_message = 'not authorized ' ,
247275 topics = [],
248276 ),
249277 )
250278
251279 with pytest .raises (Exception ) as exc_info :
252280 admin .list_partition_reassignments ()
253- assert 'not controller' in str (exc_info .value )
281+ assert 'not authorized' in str (exc_info .value )
282+
283+ def test_not_controller_retries (self , broker , admin ):
284+ Topic = ListPartitionReassignmentsResponse .OngoingTopicReassignment
285+ Partition = Topic .OngoingPartitionReassignment
286+ # First response: NotControllerError. After controller refresh, success.
287+ broker .respond (
288+ ListPartitionReassignmentsRequest ,
289+ ListPartitionReassignmentsResponse (
290+ throttle_time_ms = 0 ,
291+ error_code = 41 , # NotControllerError
292+ error_message = 'not controller' ,
293+ topics = [],
294+ ),
295+ )
296+ broker .respond (
297+ ListPartitionReassignmentsRequest ,
298+ ListPartitionReassignmentsResponse (
299+ throttle_time_ms = 0 ,
300+ error_code = 0 ,
301+ error_message = None ,
302+ topics = [
303+ Topic (
304+ name = 'topic-a' ,
305+ partitions = [
306+ Partition (
307+ partition_index = 0 ,
308+ replicas = [1 , 2 , 3 ],
309+ adding_replicas = [4 ],
310+ removing_replicas = [1 ],
311+ ),
312+ ],
313+ ),
314+ ],
315+ ),
316+ )
317+
318+ result = admin .list_partition_reassignments ()
319+ assert result == {
320+ TopicPartition ('topic-a' , 0 ): {
321+ 'replicas' : [1 , 2 , 3 ],
322+ 'adding_replicas' : [4 ],
323+ 'removing_replicas' : [1 ],
324+ },
325+ }
254326
255327
256328# ---------------------------------------------------------------------------
0 commit comments