async def test_watching_over_namespace(resource, client_mock): apicls_mock = client_mock.CustomObjectsApi cl_list_fn = apicls_mock.return_value.list_cluster_custom_object ns_list_fn = apicls_mock.return_value.list_namespaced_custom_object cl_list_fn.side_effect = PreventedActualCallError() ns_list_fn.side_effect = PreventedActualCallError() itr = streaming_watch( resource=resource, namespace='something', ) assert isinstance(itr, collections.abc.AsyncIterator) assert isinstance(itr, collections.abc.AsyncGenerator) with pytest.raises(PreventedActualCallError): async for _ in itr: pass # fully deplete it assert apicls_mock.called assert apicls_mock.call_count == 1 # The scope-relevant listing function is used, depending on the resource. assert not cl_list_fn.called assert ns_list_fn.called assert ns_list_fn.call_count == 1 assert ns_list_fn.call_args[1]['group'] == resource.group assert ns_list_fn.call_args[1]['version'] == resource.version assert ns_list_fn.call_args[1]['plural'] == resource.plural assert ns_list_fn.call_args[1]['namespace'] == 'something'
async def test_empty_stream_yields_nothing(resource, stream): stream.feed([]) events = [] async for event in streaming_watch(resource=resource, namespace=None): events.append(event) assert len(events) == 0
async def test_exception_escalates(resource, stream): stream.feed(SampleException()) events = [] with pytest.raises(SampleException): async for event in streaming_watch(resource=resource, namespace=None): events.append(event) assert len(events) == 0
async def test_event_stream_yields_everything(resource, stream): stream.feed(STREAM_WITH_NORMAL_EVENTS) events = [] async for event in streaming_watch(resource=resource, namespace=None): events.append(event) assert len(events) == 2 assert events[0]['object']['spec'] == 'a' assert events[1]['object']['spec'] == 'b'
async def test_exception_escalates(resource, stream): stream.side_effect = SampleException() events = [] with pytest.raises(SampleException): async for event in streaming_watch(resource=resource, namespace=None): events.append(event) assert stream.call_count == 1 assert len(events) == 0
async def test_unknown_error_raises_exception(resource, stream): stream.feed(STREAM_WITH_ERROR_CODE) events = [] with pytest.raises(WatchingError) as e: async for event in streaming_watch(resource=resource, namespace=None): events.append(event) assert len(events) == 1 assert events[0]['object']['spec'] == 'a' assert '666' in str(e.value)
async def test_error_410gone_exits_normally(resource, stream, caplog): caplog.set_level(logging.DEBUG) stream.feed(STREAM_WITH_ERROR_410GONE) events = [] async for event in streaming_watch(resource=resource, namespace=None): events.append(event) assert len(events) == 1 assert events[0]['object']['spec'] == 'a' assert "Restarting the watch-stream" in caplog.text
async def test_exception_escalates(resource, stream, namespace, enforced_session, mocker): enforced_session.get = mocker.Mock(side_effect=SampleException()) stream.feed([], namespace=namespace) stream.close(namespace=namespace) events = [] with pytest.raises(SampleException): async for event in streaming_watch(resource=resource, namespace=namespace): events.append(event) assert len(events) == 0
async def test_empty_stream_yields_nothing(settings, resource, stream, namespace): stream.feed([], namespace=namespace) stream.close(namespace=namespace) events = [] async for event in streaming_watch(settings=settings, resource=resource, namespace=namespace): events.append(event) assert len(events) == 0
async def test_unknown_event_type_ignored(resource, stream, caplog): caplog.set_level(logging.DEBUG) stream.feed(STREAM_WITH_UNKNOWN_EVENT) events = [] async for event in streaming_watch(resource=resource, namespace=None): events.append(event) assert len(events) == 2 assert events[0]['object']['spec'] == 'a' assert events[1]['object']['spec'] == 'b' assert "Ignoring an unsupported event type" in caplog.text assert "UNKNOWN" in caplog.text
async def test_watching_over_namespace(resource, req_mock): req_mock.get.side_effect = PreventedActualCallError() itr = streaming_watch( resource=resource, namespace='something', ) assert isinstance(itr, collections.abc.AsyncIterator) assert isinstance(itr, collections.abc.AsyncGenerator) with pytest.raises(PreventedActualCallError): async for _ in itr: pass # fully deplete it assert req_mock.get.called assert req_mock.get.call_count == 1 url = req_mock.get.call_args_list[0][1]['url'] assert 'apis/zalando.org/v1/namespaces/something/kopfexamples' in url
async def test_long_line_parsing( settings, resource, stream, namespace, aresponses): content = [ {'type': 'ADDED', 'object': {'spec': {'field': 'x'}}}, {'type': 'ADDED', 'object': {'spec': {'field': 'y' * (2 * 1024 * 1024)}}}, {'type': 'ADDED', 'object': {'spec': {'field': 'z' * (4 * 1024 * 1024)}}}, ] stream.feed(content, namespace=namespace) stream.close(namespace=namespace) events = [] async for event in streaming_watch(settings=settings, resource=resource, namespace=namespace): events.append(event) assert len(events) == 3 assert len(events[0]['object']['spec']['field']) == 1 assert len(events[1]['object']['spec']['field']) == 2 * 1024 * 1024 assert len(events[2]['object']['spec']['field']) == 4 * 1024 * 1024
async def read_stream(): async for event in streaming_watch(resource=resource, namespace=namespace, freeze_mode=freeze_mode): events.append(event)