@@ -227,7 +227,7 @@ async def test_watch_with_exception(self):
227
227
async for e in watch .stream (fake_api .get_namespaces , timeout_seconds = 10 ): # noqa
228
228
pass
229
229
230
- async def test_watch_timeout (self ):
230
+ async def test_watch_retry_timeout (self ):
231
231
fake_resp = AsyncMock ()
232
232
fake_resp .content .readline = AsyncMock ()
233
233
fake_resp .release = Mock ()
@@ -256,6 +256,108 @@ async def test_watch_timeout(self):
256
256
call (_preload_content = False , watch = True , resource_version = '1555' )])
257
257
fake_resp .release .assert_called_once_with ()
258
258
259
+ async def test_watch_retry_410 (self ):
260
+ fake_resp = AsyncMock ()
261
+ fake_resp .content .readline = AsyncMock ()
262
+ fake_resp .release = Mock ()
263
+
264
+ mock_event1 = {
265
+ "type" : "ADDED" ,
266
+ "object" : {
267
+ "metadata" :
268
+ {
269
+ "name" : "test1555" ,
270
+ "resourceVersion" : "1555"
271
+ },
272
+ "spec" : {},
273
+ "status" : {}
274
+ }
275
+ }
276
+
277
+ mock_event2 = {
278
+ "type" : "ADDED" ,
279
+ "object" : {
280
+ "metadata" :
281
+ {
282
+ "name" : "test1555" ,
283
+ "resourceVersion" : "1555"
284
+ },
285
+ "spec" : {},
286
+ "status" : {}
287
+ }
288
+ }
289
+
290
+ mock_410 = {
291
+ 'type' : 'ERROR' ,
292
+ 'object' : {
293
+ 'kind' : 'Status' ,
294
+ 'apiVersion' : 'v1' ,
295
+ 'metadata' : {},
296
+ 'status' : 'Failure' ,
297
+ 'message' : 'too old resource version: 1 (8146471)' ,
298
+ 'reason' : 'Gone' ,
299
+ 'code' : 410
300
+ }
301
+ }
302
+
303
+ # retry 410
304
+ fake_resp .content .readline .side_effect = [json .dumps (mock_event1 ).encode ('utf8' ),
305
+ json .dumps (mock_410 ).encode ('utf8' ),
306
+ json .dumps (mock_event2 ).encode ('utf8' ),
307
+ json .dumps (mock_410 ).encode ('utf8' ),
308
+ b"" ]
309
+
310
+ fake_api = Mock ()
311
+ fake_api .get_namespaces = AsyncMock (return_value = fake_resp )
312
+ fake_api .get_namespaces .__doc__ = ':rtype: V1NamespaceList'
313
+
314
+ watch = kubernetes_asyncio .watch .Watch ()
315
+ async with watch .stream (fake_api .get_namespaces ) as stream :
316
+ async for e in stream : # noqa
317
+ pass
318
+
319
+ fake_api .get_namespaces .assert_has_calls (
320
+ [call (_preload_content = False , watch = True ),
321
+ call (_preload_content = False , watch = True , resource_version = '1555' )])
322
+ fake_resp .release .assert_called_once_with ()
323
+
324
+ # retry 410 only once
325
+ fake_resp .content .readline .side_effect = [json .dumps (mock_event1 ).encode ('utf8' ),
326
+ json .dumps (mock_410 ).encode ('utf8' ),
327
+ json .dumps (mock_event2 ).encode ('utf8' ),
328
+ json .dumps (mock_410 ).encode ('utf8' ),
329
+ json .dumps (mock_410 ).encode ('utf8' ),
330
+ b"" ]
331
+
332
+ fake_api = Mock ()
333
+ fake_api .get_namespaces = AsyncMock (return_value = fake_resp )
334
+ fake_api .get_namespaces .__doc__ = ':rtype: V1NamespaceList'
335
+
336
+ with self .assertRaisesRegex (
337
+ kubernetes_asyncio .client .exceptions .ApiException ,
338
+ r'\(410\)\nReason: Gone: too old resource version: 1 \(8146471\)' ):
339
+ watch = kubernetes_asyncio .watch .Watch ()
340
+ async with watch .stream (fake_api .get_namespaces ) as stream :
341
+ async for e in stream : # noqa
342
+ pass
343
+
344
+ # no retry 410 if timeout is passed
345
+ fake_resp .content .readline .side_effect = [json .dumps (mock_event1 ).encode ('utf8' ),
346
+ json .dumps (mock_410 ).encode ('utf8' ),
347
+ b"" ]
348
+
349
+ fake_api = Mock ()
350
+ fake_api .get_namespaces = AsyncMock (return_value = fake_resp )
351
+ fake_api .get_namespaces .__doc__ = ':rtype: V1NamespaceList'
352
+
353
+ with self .assertRaisesRegex (
354
+ kubernetes_asyncio .client .exceptions .ApiException ,
355
+ r'\(410\)\nReason: Gone: too old resource version: 1 \(8146471\)' ):
356
+ watch = kubernetes_asyncio .watch .Watch ()
357
+ async with watch .stream (fake_api .get_namespaces , timeout_seconds = 10 ) as stream :
358
+ async for e in stream : # noqa
359
+ pass
360
+
259
361
async def test_watch_timeout_with_resource_version (self ):
260
362
fake_resp = AsyncMock ()
261
363
fake_resp .content .readline = AsyncMock ()
0 commit comments