Acceptance tests using different clients concurrently. Environment deployed from packages.
Build: #2346 failed
Job: Archive privileges failed
user of client removing cannot remove archive after getting invite token without remove archives privilege from user of client inviting[1oz 1op 1oc-RESt-web GUi]: Test case result
The below summarizes the result of the test " user of client removing cannot remove archive after getting invite token without remove archives privilege from user of client inviting[1oz 1op 1oc-RESt-web GUi]" in build 2,346 of Onedata Products - mixed acceptance pkg - Chrome archive privileges.
- Description
- user of client removing cannot remove archive after getting invite token without remove archives privilege from user of client inviting[1oz 1op 1oc-RESt-web GUi]
- Test class
- mixed.scenarios.test_archive_privileges
- Method
- test_user_of_client_removing_cannot_remove_archive_after_getting_invite_token_without_remove_archives_privilege_from_user_of_client_inviting[1oz_1op_1oc-REST-web GUI]
- Duration
- 3 mins
- Status
- Failed (New Failure)
Error Log
oneprovider_client.rest.ApiException: (None) Reason: None user = 'user2' users = {'admin': <tests.utils.user_utils.AdminUser object at 0x7f8ad4c18278>, 'onepanel': <tests.utils.user_utils.AdminUser o...tests.utils.user_utils.User object at 0x7f8ad4c87cc0>, 'user2': <tests.utils.user_utils.User object at 0x7f8ad4c87da0>} hosts = {'oneclient-1': {'container-id': '5c6041e1baa4b46fd90cb9931565d722e50d12baeb6cbfce5528dc49f4494074', 'ip': '172.17.0.9...f5dd19d39922f61', 'hostname': 'dev-onezone.default.svc.cluster.local', 'ip': '172.17.0.8', 'name': 'dev-onezone', ...}} host = 'oneprovider-1', description = 'first archive' tmp_memory = defaultdict(<class 'dict'>, {'user1': {'shares': {}, 'spaces': {}, 'groups': {}, 'mailbox': {}, 'oz': {}, 'window': {'...GuMQrTDI5Oym401Ugo'}, 'oz': {}, 'window': {'modal': None}}, 'first archive': '8c2b3854f499422f6dac405a97edbb03ch3fa3'}) option = 'fails' def remove_archive_in_op_rest(user, users, hosts, host, description, tmp_memory, option): client = login_to_provider(user, users, hosts[host]['hostname']) archive_id = tmp_memory[description] archive_api = ArchiveApi(client) if option == 'succeeds': archive_api.purge_archive(archive_id) elif option == 'fails': try: > archive_api.purge_archive(archive_id) tests/mixed/steps/rest/oneprovider/archives.py:111: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <tests.mixed.oneprovider_client.api.archive_api.ArchiveApi object at 0x7f8ad4c779b0> aid = '8c2b3854f499422f6dac405a97edbb03ch3fa3' kwargs = {'_return_http_data_only': True} def purge_archive(self, aid, **kwargs): # noqa: E501 """Purge archive # noqa: E501 Initializes process of purging an archive. First, the archived data is purged from the storage, then all the information concerning the archive is deleted. The process may be time consuming therefore it is possible to pass callback URL on which the POST request will be performed to notify that the process has finished. The callback request will include JSON `{\"archiveId\": $ARCHIVE_ID}` as a body to determine which archive has been purged. This operation requires `space_manage_datasets` and `space_remove_archives` privileges. ***Example cURL requests*** **Purge archive** ```bash curl -H \"X-Auth-Token: $TOKEN\" -X POST \"https://$PROVIDER_HOST/api/v3/oneprovider/archives/$ARCHIVE_ID/purge\" \\ -H \"Content-Type: application/json\" -d '{ \"purgedCallback\": \"https://example.org/purged_archives\" }' ``` # noqa: E501 This method makes a synchronous HTTP request by default. To make an asynchronous HTTP request, please pass async_req=True >>> thread = api.purge_archive(aid, async_req=True) >>> result = thread.get() :param async_req bool :param str aid: Id of a specific archive to be purged. (required) :param ArchivePurgeRequest data: Parameters for initializing purging of an archive. :return: None If the method is called asynchronously, returns the request thread. """ kwargs['_return_http_data_only'] = True if kwargs.get('async_req'): return self.purge_archive_with_http_info(aid, **kwargs) # noqa: E501 else: > (data) = self.purge_archive_with_http_info(aid, **kwargs) # noqa: E501 tests/mixed/oneprovider_client/api/archive_api.py:551: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <tests.mixed.oneprovider_client.api.archive_api.ArchiveApi object at 0x7f8ad4c779b0> aid = '8c2b3854f499422f6dac405a97edbb03ch3fa3' kwargs = {'_return_http_data_only': True} all_params = ['aid', 'data', 'async_req', '_return_http_data_only', '_preload_content', '_request_timeout'] params = {'_return_http_data_only': True, 'aid': '8c2b3854f499422f6dac405a97edbb03ch3fa3', 'all_params': ['aid', 'data', 'async_req', '_return_http_data_only', '_preload_content', '_request_timeout'], 'auth_settings': ['api_key1', 'api_key2'], ...} key = '_return_http_data_only', val = True, collection_formats = {} path_params = {'aid': '8c2b3854f499422f6dac405a97edbb03ch3fa3'} query_params = [] def purge_archive_with_http_info(self, aid, **kwargs): # noqa: E501 """Purge archive # noqa: E501 Initializes process of purging an archive. First, the archived data is purged from the storage, then all the information concerning the archive is deleted. The process may be time consuming therefore it is possible to pass callback URL on which the POST request will be performed to notify that the process has finished. The callback request will include JSON `{\"archiveId\": $ARCHIVE_ID}` as a body to determine which archive has been purged. This operation requires `space_manage_datasets` and `space_remove_archives` privileges. ***Example cURL requests*** **Purge archive** ```bash curl -H \"X-Auth-Token: $TOKEN\" -X POST \"https://$PROVIDER_HOST/api/v3/oneprovider/archives/$ARCHIVE_ID/purge\" \\ -H \"Content-Type: application/json\" -d '{ \"purgedCallback\": \"https://example.org/purged_archives\" }' ``` # noqa: E501 This method makes a synchronous HTTP request by default. To make an asynchronous HTTP request, please pass async_req=True >>> thread = api.purge_archive_with_http_info(aid, async_req=True) >>> result = thread.get() :param async_req bool :param str aid: Id of a specific archive to be purged. (required) :param ArchivePurgeRequest data: Parameters for initializing purging of an archive. :return: None If the method is called asynchronously, returns the request thread. """ all_params = ['aid', 'data'] # noqa: E501 all_params.append('async_req') all_params.append('_return_http_data_only') all_params.append('_preload_content') all_params.append('_request_timeout') params = locals() for key, val in six.iteritems(params['kwargs']): if key not in all_params: raise TypeError( "Got an unexpected keyword argument '%s'" " to method purge_archive" % key ) params[key] = val del params['kwargs'] # verify the required parameter 'aid' is set if self.api_client.client_side_validation and ('aid' not in params or params['aid'] is None): # noqa: E501 raise ValueError("Missing the required parameter `aid` when calling `purge_archive`") # noqa: E501 collection_formats = {} path_params = {} if 'aid' in params: path_params['aid'] = params['aid'] # noqa: E501 query_params = [] header_params = {} form_params = [] local_var_files = {} body_params = None if 'data' in params: body_params = params['data'] # HTTP header `Content-Type` header_params['Content-Type'] = self.api_client.select_header_content_type( # noqa: E501 ['application/json']) # noqa: E501 # Authentication setting auth_settings = ['api_key1', 'api_key2'] # noqa: E501 return self.api_client.call_api( '/archives/{aid}/purge', 'POST', path_params, query_params, header_params, body=body_params, post_params=form_params, files=local_var_files, response_type=None, # noqa: E501 auth_settings=auth_settings, async_req=params.get('async_req'), _return_http_data_only=params.get('_return_http_data_only'), _preload_content=params.get('_preload_content', True), _request_timeout=params.get('_request_timeout'), > collection_formats=collection_formats) tests/mixed/oneprovider_client/api/archive_api.py:628: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <oneprovider_client.api_client.ApiClient object at 0x7f8ad4c772e8> resource_path = '/archives/{aid}/purge', method = 'POST' path_params = {'aid': '8c2b3854f499422f6dac405a97edbb03ch3fa3'} query_params = [] header_params = {'Content-Type': 'application/json', 'User-Agent': 'Swagger-Codegen/21.02.0-alpha25/python', 'X-Auth-Token': 'MDAzM2xv...yN2NlM2Q1Y2NoN2JhNgowMDFhY2lkIHRpbWUgPCAxNjg1MTI5NzA1CjAwMmZzaWduYXR1cmUgPDD6Yhnwpx4vkdE4RREEB82kIBBnGZJ7nyD7oTjaiGEK'} body = None, post_params = [], files = {}, response_type = None auth_settings = ['api_key1', 'api_key2'], async_req = None _return_http_data_only = True, collection_formats = {}, _preload_content = True _request_timeout = None def call_api(self, resource_path, method, path_params=None, query_params=None, header_params=None, body=None, post_params=None, files=None, response_type=None, auth_settings=None, async_req=None, _return_http_data_only=None, collection_formats=None, _preload_content=True, _request_timeout=None): """Makes the HTTP request (synchronous) and returns deserialized data. To make an async request, set the async_req parameter. :param resource_path: Path to method endpoint. :param method: Method to call. :param path_params: Path parameters in the url. :param query_params: Query parameters in the url. :param header_params: Header parameters to be placed in the request header. :param body: Request body. :param post_params dict: Request post form parameters, for `application/x-www-form-urlencoded`, `multipart/form-data`. :param auth_settings list: Auth Settings names for the request. :param response: Response data type. :param files dict: key -> filename, value -> filepath, for `multipart/form-data`. :param async_req bool: execute request asynchronously :param _return_http_data_only: response data without head status code and headers :param collection_formats: dict of collection formats for path, query, header, and post parameters. :param _preload_content: if False, the urllib3.HTTPResponse object will be returned without reading/decoding response data. Default is True. :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of (connection, read) timeouts. :return: If async_req parameter is True, the request will be called asynchronously. The method will return the request thread. If parameter async_req is False or missing, then the method will return the response directly. """ if not async_req: return self.__call_api(resource_path, method, path_params, query_params, header_params, body, post_params, files, response_type, auth_settings, _return_http_data_only, collection_formats, > _preload_content, _request_timeout) tests/mixed/oneprovider_client/api_client.py:331: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <oneprovider_client.api_client.ApiClient object at 0x7f8ad4c772e8> resource_path = '/archives/8c2b3854f499422f6dac405a97edbb03ch3fa3/purge' method = 'POST' path_params = [('aid', '8c2b3854f499422f6dac405a97edbb03ch3fa3')] query_params = [] header_params = {'Content-Type': 'application/json', 'User-Agent': 'Swagger-Codegen/21.02.0-alpha25/python', 'X-Auth-Token': 'MDAzM2xv...yN2NlM2Q1Y2NoN2JhNgowMDFhY2lkIHRpbWUgPCAxNjg1MTI5NzA1CjAwMmZzaWduYXR1cmUgPDD6Yhnwpx4vkdE4RREEB82kIBBnGZJ7nyD7oTjaiGEK'} body = None, post_params = [], files = {}, response_type = None auth_settings = ['api_key1', 'api_key2'], _return_http_data_only = True collection_formats = {}, _preload_content = True, _request_timeout = None def __call_api( self, resource_path, method, path_params=None, query_params=None, header_params=None, body=None, post_params=None, files=None, response_type=None, auth_settings=None, _return_http_data_only=None, collection_formats=None, _preload_content=True, _request_timeout=None): config = self.configuration # header parameters header_params = header_params or {} header_params.update(self.default_headers) if self.cookie: header_params['Cookie'] = self.cookie if header_params: header_params = self.sanitize_for_serialization(header_params) header_params = dict(self.parameters_to_tuples(header_params, collection_formats)) # path parameters if path_params: path_params = self.sanitize_for_serialization(path_params) path_params = self.parameters_to_tuples(path_params, collection_formats) for k, v in path_params: # specified safe chars, encode everything resource_path = resource_path.replace( '{%s}' % k, quote(str(v), safe=config.safe_chars_for_path_param) ) # query parameters if query_params: query_params = self.sanitize_for_serialization(query_params) query_params = self.parameters_to_tuples(query_params, collection_formats) # post parameters if post_params or files: post_params = self.prepare_post_parameters(post_params, files) post_params = self.sanitize_for_serialization(post_params) post_params = self.parameters_to_tuples(post_params, collection_formats) # auth setting self.update_params_for_auth(header_params, query_params, auth_settings) # body if body: body = self.sanitize_for_serialization(body) # request url url = self.configuration.host + resource_path # perform request and return response response_data = self.request( method, url, query_params=query_params, headers=header_params, post_params=post_params, body=body, _preload_content=_preload_content, > _request_timeout=_request_timeout) tests/mixed/oneprovider_client/api_client.py:162: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <oneprovider_client.api_client.ApiClient object at 0x7f8ad4c772e8> method = 'POST' url = 'https://dev-oneprovider-krakow.default.svc.cluster.local:443/api/v3/oneprovider/archives/8c2b3854f499422f6dac405a97edbb03ch3fa3/purge' query_params = [] headers = {'Content-Type': 'application/json', 'User-Agent': 'Swagger-Codegen/21.02.0-alpha25/python', 'X-Auth-Token': 'MDAzM2xv...yN2NlM2Q1Y2NoN2JhNgowMDFhY2lkIHRpbWUgPCAxNjg1MTI5NzA1CjAwMmZzaWduYXR1cmUgPDD6Yhnwpx4vkdE4RREEB82kIBBnGZJ7nyD7oTjaiGEK'} post_params = [], body = None, _preload_content = True, _request_timeout = None def request(self, method, url, query_params=None, headers=None, post_params=None, body=None, _preload_content=True, _request_timeout=None): """Makes the HTTP request using RESTClient.""" if method == "GET": return self.rest_client.GET(url, query_params=query_params, _preload_content=_preload_content, _request_timeout=_request_timeout, headers=headers) elif method == "HEAD": return self.rest_client.HEAD(url, query_params=query_params, _preload_content=_preload_content, _request_timeout=_request_timeout, headers=headers) elif method == "OPTIONS": return self.rest_client.OPTIONS(url, query_params=query_params, headers=headers, post_params=post_params, _preload_content=_preload_content, _request_timeout=_request_timeout, body=body) elif method == "POST": return self.rest_client.POST(url, query_params=query_params, headers=headers, post_params=post_params, _preload_content=_preload_content, _request_timeout=_request_timeout, > body=body) tests/mixed/oneprovider_client/api_client.py:374: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <oneprovider_client.rest.RESTClientObject object at 0x7f8ad4c77400> url = 'https://dev-oneprovider-krakow.default.svc.cluster.local:443/api/v3/oneprovider/archives/8c2b3854f499422f6dac405a97edbb03ch3fa3/purge' headers = {'Content-Type': 'application/json', 'User-Agent': 'Swagger-Codegen/21.02.0-alpha25/python', 'X-Auth-Token': 'MDAzM2xv...yN2NlM2Q1Y2NoN2JhNgowMDFhY2lkIHRpbWUgPCAxNjg1MTI5NzA1CjAwMmZzaWduYXR1cmUgPDD6Yhnwpx4vkdE4RREEB82kIBBnGZJ7nyD7oTjaiGEK'} query_params = [], post_params = [], body = None, _preload_content = True _request_timeout = None def POST(self, url, headers=None, query_params=None, post_params=None, body=None, _preload_content=True, _request_timeout=None): return self.request("POST", url, headers=headers, query_params=query_params, post_params=post_params, _preload_content=_preload_content, _request_timeout=_request_timeout, > body=body) tests/mixed/oneprovider_client/rest.py:275: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <oneprovider_client.rest.RESTClientObject object at 0x7f8ad4c77400> method = 'POST' url = 'https://dev-oneprovider-krakow.default.svc.cluster.local:443/api/v3/oneprovider/archives/8c2b3854f499422f6dac405a97edbb03ch3fa3/purge' query_params = [] headers = {'Content-Type': 'application/json', 'User-Agent': 'Swagger-Codegen/21.02.0-alpha25/python', 'X-Auth-Token': 'MDAzM2xv...yN2NlM2Q1Y2NoN2JhNgowMDFhY2lkIHRpbWUgPCAxNjg1MTI5NzA1CjAwMmZzaWduYXR1cmUgPDD6Yhnwpx4vkdE4RREEB82kIBBnGZJ7nyD7oTjaiGEK'} body = None, post_params = {}, _preload_content = True, _request_timeout = None def request(self, method, url, query_params=None, headers=None, body=None, post_params=None, _preload_content=True, _request_timeout=None): """Perform requests. :param method: http request method :param url: http request url :param query_params: query parameters in the url :param headers: http request headers :param body: request json body, for `application/json` :param post_params: request post parameters, `application/x-www-form-urlencoded` and `multipart/form-data` :param _preload_content: if False, the urllib3.HTTPResponse object will be returned without reading/decoding response data. Default is True. :param _request_timeout: timeout setting for this request. If one number provided, it will be total request timeout. It can also be a pair (tuple) of (connection, read) timeouts. """ method = method.upper() assert method in ['GET', 'HEAD', 'DELETE', 'POST', 'PUT', 'PATCH', 'OPTIONS'] if post_params and body: raise ValueError( "body parameter cannot be used with post_params parameter." ) post_params = post_params or {} headers = headers or {} timeout = None if _request_timeout: if isinstance(_request_timeout, (int, ) if six.PY3 else (int, long)): # noqa: E501,F821 timeout = urllib3.Timeout(total=_request_timeout) elif (isinstance(_request_timeout, tuple) and len(_request_timeout) == 2): timeout = urllib3.Timeout( connect=_request_timeout[0], read=_request_timeout[1]) if 'Content-Type' not in headers: headers['Content-Type'] = 'application/json' try: # For `POST`, `PUT`, `PATCH`, `OPTIONS`, `DELETE` if method in ['POST', 'PUT', 'PATCH', 'OPTIONS', 'DELETE']: if query_params: url += '?' + urlencode(query_params) if re.search('json', headers['Content-Type'], re.IGNORECASE): request_body = '{}' if body is not None: request_body = json.dumps(body) r = self.pool_manager.request( method, url, body=request_body, preload_content=_preload_content, timeout=timeout, headers=headers) elif headers['Content-Type'] == 'application/x-www-form-urlencoded': # noqa: E501 r = self.pool_manager.request( method, url, fields=post_params, encode_multipart=False, preload_content=_preload_content, timeout=timeout, headers=headers) elif headers['Content-Type'] == 'multipart/form-data': # must del headers['Content-Type'], or the correct # Content-Type which generated by urllib3 will be # overwritten. del headers['Content-Type'] r = self.pool_manager.request( method, url, fields=post_params, encode_multipart=True, preload_content=_preload_content, timeout=timeout, headers=headers) # Pass a `string` parameter directly in the body to support # other content types than Json when `body` argument is # provided in serialized form elif isinstance(body, str): request_body = body r = self.pool_manager.request( method, url, body=request_body, preload_content=_preload_content, timeout=timeout, headers=headers) else: # Cannot generate the request from given parameters msg = """Cannot prepare a request message for provided arguments. Please check that your arguments match declared content type.""" raise ApiException(status=0, reason=msg) # For `GET`, `HEAD` else: r = self.pool_manager.request(method, url, fields=query_params, preload_content=_preload_content, timeout=timeout, headers=headers) except urllib3.exceptions.SSLError as e: msg = "{0}\n{1}".format(type(e).__name__, str(e)) raise ApiException(status=0, reason=msg) if _preload_content: r = RESTResponse(r) # In the python 3, the response.data is bytes. # we need to decode it to string. if six.PY3: r.data = r.data.decode('utf8') # log response body logger.debug("response body: %s", r.data) if not 200 <= r.status <= 299: > raise ApiException(http_resp=r) E oneprovider_client.rest.ApiException: (404) E Reason: Not Found E HTTP response headers: HTTPHeaderDict({'content-length': '0', 'date': 'Thu, 26 May 2022 19:35:09 GMT', 'server': 'Cowboy'}) tests/mixed/oneprovider_client/rest.py:228: ApiException During handling of the above exception, another exception occurred: request = <FixtureRequest for <Function 'test_user_of_client_removing_cannot_remove_archive_after_getting_invite_token_without_remove_archives_privilege_from_user_of_client_inviting[1oz_1op_1oc-REST-web GUI]'>> @pytest.mark.usefixtures(*function_args) def scenario_wrapper(request): > _execute_scenario(feature, scenario, request, encoding) /usr/local/lib/python3.6/dist-packages/pytest_bdd/scenario.py:227: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ /usr/local/lib/python3.6/dist-packages/pytest_bdd/scenario.py:189: in _execute_scenario _execute_step_function(request, scenario, step, step_func) /usr/local/lib/python3.6/dist-packages/pytest_bdd/scenario.py:130: in _execute_step_function step_func(**kwargs) tests/utils/bdd_utils.py:78: in wrapper return fun(*ba.args, **ba.kwargs) <decorator-gen-1007>:2: in remove_archive_in_op ??? tests/utils/utils.py:95: in wrapper return fun(*args, **kwargs) tests/mixed/steps/archive.py:76: in remove_archive_in_op description, tmp_memory, option) _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ user = 'user2' users = {'admin': <tests.utils.user_utils.AdminUser object at 0x7f8ad4c18278>, 'onepanel': <tests.utils.user_utils.AdminUser o...tests.utils.user_utils.User object at 0x7f8ad4c87cc0>, 'user2': <tests.utils.user_utils.User object at 0x7f8ad4c87da0>} hosts = {'oneclient-1': {'container-id': '5c6041e1baa4b46fd90cb9931565d722e50d12baeb6cbfce5528dc49f4494074', 'ip': '172.17.0.9...f5dd19d39922f61', 'hostname': 'dev-onezone.default.svc.cluster.local', 'ip': '172.17.0.8', 'name': 'dev-onezone', ...}} host = 'oneprovider-1', description = 'first archive' tmp_memory = defaultdict(<class 'dict'>, {'user1': {'shares': {}, 'spaces': {}, 'groups': {}, 'mailbox': {}, 'oz': {}, 'window': {'...GuMQrTDI5Oym401Ugo'}, 'oz': {}, 'window': {'modal': None}}, 'first archive': '8c2b3854f499422f6dac405a97edbb03ch3fa3'}) option = 'fails' def remove_archive_in_op_rest(user, users, hosts, host, description, tmp_memory, option): client = login_to_provider(user, users, hosts[host]['hostname']) archive_id = tmp_memory[description] archive_api = ArchiveApi(client) if option == 'succeeds': archive_api.purge_archive(archive_id) elif option == 'fails': try: archive_api.purge_archive(archive_id) raise Exception( 'removing archive worked but it should not') except OPException as err: if err.status == 400: pass else: > raise OPException E oneprovider_client.rest.ApiException: (None) E Reason: None tests/mixed/steps/rest/oneprovider/archives.py:118: ApiException