def test_raises_api_error(req_mock, resource, namespace, status): response = requests.Response() response.status_code = status error = requests.exceptions.HTTPError("boo!", response=response) req_mock.get.side_effect = error with pytest.raises(requests.exceptions.HTTPError) as e: list_objs(resource=resource, namespace=namespace) assert e.value.response.status_code == status
def test_raises_api_error(client_mock, resource, namespace, status): error = kubernetes.client.rest.ApiException(status=status) apicls_mock = client_mock.CustomObjectsApi apicls_mock.return_value.list_cluster_custom_object.side_effect = error apicls_mock.return_value.list_namespaced_custom_object.side_effect = error with pytest.raises(kubernetes.client.rest.ApiException) as e: list_objs(resource=resource, namespace=namespace) assert e.value.status == status
def test_when_successful_namespaced(req_mock, resource): result = {'items': []} req_mock.get.return_value.json.return_value = result lst = list_objs(resource=resource, namespace='ns1') assert lst is result 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/ns1/kopfexamples' in url
async def streaming_watch( resource: registries.Resource, namespace: Union[None, str], ): """ Stream the watch-events from one single API watch-call. """ # First, list the resources regularly, and get the list's resource version. # Simulate the events with type "None" event - used in detection of causes. rsp = fetching.list_objs(resource=resource, namespace=namespace) resource_version = rsp['metadata']['resourceVersion'] for item in rsp['items']: # FIXME: fix in pykube to inject the missing item's fields from the list's metainfo. item.setdefault('kind', rsp['kind'][:-4] if rsp['kind'][-4:] == 'List' else rsp['kind']) item.setdefault('apiVersion', rsp['apiVersion']) yield {'type': None, 'object': item} # Then, watch the resources starting from the list's resource version. kwargs = {} kwargs.update(dict(resource_version=resource_version) if resource_version else {}) kwargs.update(dict(timeout_seconds=config.WatchersConfig.default_stream_timeout) if config.WatchersConfig.default_stream_timeout else {}) loop = asyncio.get_event_loop() stream = fetching.watch_objs(resource=resource, namespace=namespace, timeout=config.WatchersConfig.default_stream_timeout, since=resource_version) async for event in streaming_aiter(stream, loop=loop): # "410 Gone" is for the "resource version too old" error, we must restart watching. # The resource versions are lost by k8s after few minutes (as per the official doc). # The error occurs when there is nothing happening for few minutes. This is normal. if event['type'] == 'ERROR' and event['object']['code'] == 410: logger.debug("Restarting the watch-stream for %r", resource) break # out of for-cycle, to the while-true-cycle. # Other watch errors should be fatal for the operator. if event['type'] == 'ERROR': raise WatchingError(f"Error in the watch-stream: {event['object']}") # Ensure that the event is something we understand and can handle. if event['type'] not in ['ADDED', 'MODIFIED', 'DELETED']: logger.warning("Ignoring an unsupported event type: %r", event) continue # Yield normal events to the consumer. yield event
def test_when_successful_clustered(client_mock, resource): result = object() apicls_mock = client_mock.CustomObjectsApi apicls_mock.return_value.list_cluster_custom_object.return_value = result apicls_mock.return_value.list_namespaced_custom_object.return_value = result sidefn_mock = apicls_mock.return_value.list_namespaced_custom_object mainfn_mock = apicls_mock.return_value.list_cluster_custom_object lst = list_objs(resource=resource, namespace=None) assert lst is result assert not sidefn_mock.called assert mainfn_mock.call_count == 1 assert mainfn_mock.call_args_list == [ call( group=resource.group, version=resource.version, plural=resource.plural, ) ]