async def test_watch_timeout_with_resource_version(self): fake_resp = CoroutineMock() fake_resp.content.readline = CoroutineMock() fake_resp.release = Mock() fake_resp.content.readline.side_effect = [asyncio.TimeoutError(), b""] fake_api = Mock() fake_api.get_namespaces = CoroutineMock(return_value=fake_resp) fake_api.get_namespaces.__doc__ = ':return: V1NamespaceList' watch = kubernetes_asyncio.watch.Watch() async with watch.stream(fake_api.get_namespaces, resource_version='10') as stream: async for e in stream: # noqa pass # all calls use the passed resource version fake_api.get_namespaces.assert_has_calls([ call(_preload_content=False, watch=True, resource_version='10'), call(_preload_content=False, watch=True, resource_version='10') ]) fake_resp.release.assert_called_once_with() self.assertEqual(watch.resource_version, '10')
async def test_watch_timeout(self): fake_resp = CoroutineMock() fake_resp.content.readline = CoroutineMock() mock_event = { "type": "ADDED", "object": { "metadata": { "name": "test1555", "resourceVersion": "1555" }, "spec": {}, "status": {} } } fake_resp.content.readline.side_effect = [ json.dumps(mock_event).encode('utf8'), asyncio.TimeoutError(), b"" ] fake_api = Mock() fake_api.get_namespaces = CoroutineMock(return_value=fake_resp) fake_api.get_namespaces.__doc__ = ':return: V1NamespaceList' watch = kubernetes_asyncio.watch.Watch() async for e in watch.stream(fake_api.get_namespaces): # noqa pass fake_api.get_namespaces.assert_has_calls([ call(_preload_content=False, watch=True), call(_preload_content=False, watch=True, resource_version='1555') ])
async def test_watch_with_exception(self): fake_resp = CoroutineMock() fake_resp.content.readline = CoroutineMock() fake_resp.content.readline.side_effect = KeyError("expected") fake_api = Mock() fake_api.get_namespaces = CoroutineMock(return_value=fake_resp) fake_api.get_namespaces.__doc__ = ':return: V1NamespaceList' with self.assertRaises(KeyError): watch = kubernetes_asyncio.watch.Watch() async for e in watch.stream(fake_api.get_namespaces, timeout_seconds=10): # noqa pass
async def test_watch_with_decode(self): fake_resp = CoroutineMock() fake_resp.content.readline = CoroutineMock() fake_resp.release = Mock() side_effects = [{ "type": "ADDED", "object": { "metadata": { "name": "test{}".format(uid), "resourceVersion": str(uid) }, "spec": {}, "status": {} } } for uid in range(3)] side_effects = [json.dumps(_).encode('utf8') for _ in side_effects] side_effects.extend([AssertionError('Should not have been called')]) fake_resp.content.readline.side_effect = side_effects fake_api = Mock() fake_api.get_namespaces = CoroutineMock(return_value=fake_resp) fake_api.get_namespaces.__doc__ = ':return: V1NamespaceList' watch = kubernetes_asyncio.watch.Watch() count = 0 async with watch: async for e in watch.stream(fake_api.get_namespaces, resource_version='123'): self.assertEqual("ADDED", e['type']) # make sure decoder worked and we got a model with the right name self.assertEqual("test%d" % count, e['object'].metadata.name) # make sure decoder worked and updated Watch.resource_version self.assertEqual(e['object'].metadata.resource_version, str(count)) self.assertEqual(watch.resource_version, str(count)) # Stop the watch. This must not return the next event which would # be an AssertionError exception. count += 1 if count == len(side_effects) - 1: watch.stop() fake_api.get_namespaces.assert_called_once_with(_preload_content=False, watch=True, resource_version='123') fake_resp.release.assert_called_once_with() # last resource_version has to be stored in the object self.assertEqual(watch.resource_version, '2')
async def test_watch_with_exception(self): fake_resp = CoroutineMock() fake_resp.content.readline = CoroutineMock( side_effect=KeyError("expected")) fake_api = Mock() fake_api.get_namespaces = CoroutineMock( return_value=ApiResponse(http=fake_resp, obj=None)) fake_api.get_namespaces.__doc__ = ':return: V1NamespaceList' fake_api.get_namespaces.__self__ = fake_api with self.assertRaises(KeyError): watch = k8s.watch.Watch(fake_api.get_namespaces, timeout_seconds=10) [_ async for _ in watch]
async def test_watch_k8s_empty_response(self): """Stop the iterator when the response is empty. This typically happens when the user supplied timeout expires. """ # Mock the readline return value to first return a valid response # followed by an empty response. fake_resp = CoroutineMock() fake_resp.content.readline = CoroutineMock() side_effects = [ { "type": "ADDED", "object": { "metadata": { "name": "test0" }, "spec": {}, "status": {} } }, { "type": "ADDED", "object": { "metadata": { "name": "test1" }, "spec": {}, "status": {} } }, ] side_effects = [json.dumps(_).encode('utf8') for _ in side_effects] fake_resp.content.readline.side_effect = side_effects + [b''] # Fake the K8s resource object to watch. fake_api = Mock() fake_api.get_namespaces = CoroutineMock( return_value=ApiResponse(http=fake_resp, obj=None)) fake_api.get_namespaces.__doc__ = ':return: V1NamespaceList' fake_api.get_namespaces.__self__ = fake_api # Iteration must cease after all valid responses were received. watch = k8s.watch.Watch(fake_api.get_namespaces) cnt = len([_ async for _ in watch]) self.assertEqual(cnt, len(side_effects))
async def test_watch_with_decode(self): fake_resp = CoroutineMock() fake_resp.content.readline = CoroutineMock() side_effects = [{ "type": "ADDED", "object": { "metadata": { "name": "test{}".format(uid) }, "spec": {}, "status": {} } } for uid in range(3)] side_effects = [json.dumps(_).encode('utf8') for _ in side_effects] side_effects.extend([AssertionError('Should not have been called')]) fake_resp.content.readline.side_effect = side_effects fake_api = Mock() fake_api.get_namespaces = CoroutineMock( return_value=ApiResponse(http=fake_resp, obj=None)) fake_api.get_namespaces.__doc__ = ':return: V1NamespaceList' fake_api.get_namespaces.__self__ = SimpleNamespace( api_client=self.api_client) watch = k8s.watch.Watch(fake_api.get_namespaces, resource_version='123') count = 0 async for e in watch: self.assertEqual("ADDED", e.name) # make sure decoder worked and we got a model with the right name self.assertEqual("test%d" % count, e.obj.metadata.name) # Stop the watch. This must not return the next event which would # be an AssertionError exception. count += 1 if count == len(side_effects) - 1: watch.stop() fake_api.get_namespaces.assert_called_once_with(_preload_content=False, watch=True, resource_version='123')