diff --git a/jupiterone/client.py b/jupiterone/client.py index 7cc185e..4b3bdb5 100644 --- a/jupiterone/client.py +++ b/jupiterone/client.py @@ -3,6 +3,7 @@ # see https://github.com/PyCQA/pylint/issues/409 import json +from warnings import warn from typing import Dict, List import requests @@ -50,11 +51,11 @@ def __init__(self, account: str = None, token: str = None, url: str = DEFAULT_UR self.account = account self.token = token self.url = url - self.query_endpoint = self.url + "/graphql" + self.query_endpoint = self.url self.rules_endpoint = self.url + "/rules/graphql" self.headers = { "Authorization": "Bearer {}".format(self.token), - "Jupiterone-Account": self.account, + "JupiterOne-Account": self.account, } @property @@ -90,7 +91,7 @@ def _execute_query(self, query: str, variables: Dict = None) -> Dict: if variables: data.update(variables=variables) - # Always ask for variableresultsize + # Always ask for variableResultSize data.update(flags={"variableResultSize": True}) response = requests.post( @@ -124,7 +125,7 @@ def _execute_query(self, query: str, variables: Dict = None) -> Dict: raise JupiterOneApiRetryError("JupiterOne API rate limit exceeded.") elif response.status_code in [504]: - raise JupiterOneApiRetryError("Bad Gateway error. Check network route and try again.") + raise JupiterOneApiRetryError("Gateway Timeout.") elif response.status_code in [500]: raise JupiterOneApiError("JupiterOne API internal server error.") diff --git a/setup.py b/setup.py index 9cb3f2a..6cd952e 100644 --- a/setup.py +++ b/setup.py @@ -3,8 +3,7 @@ install_reqs = [ 'requests', - 'retrying', - 'warnings' + 'retrying' ] setup(name='jupiterone', diff --git a/tests/pytest.ini b/tests/pytest.ini new file mode 100644 index 0000000..8970bf4 --- /dev/null +++ b/tests/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +pythonpath = .. diff --git a/tests/test_create_entity.py b/tests/test_create_entity.py index 430a92e..b31b316 100644 --- a/tests/test_create_entity.py +++ b/tests/test_create_entity.py @@ -32,7 +32,7 @@ def request_callback(request): return (200, headers, json.dumps(response)) responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=request_callback, content_type='application/json', ) diff --git a/tests/test_create_relationship.py b/tests/test_create_relationship.py index 2bd4042..f63d4b5 100644 --- a/tests/test_create_relationship.py +++ b/tests/test_create_relationship.py @@ -36,7 +36,7 @@ def request_callback(request): return (200, headers, json.dumps(response)) responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=request_callback, content_type='application/json', ) diff --git a/tests/test_delete_entity.py b/tests/test_delete_entity.py index 02e5d18..73348a1 100644 --- a/tests/test_delete_entity.py +++ b/tests/test_delete_entity.py @@ -33,7 +33,7 @@ def request_callback(request): return (200, headers, json.dumps(response)) responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=request_callback, content_type='application/json', ) diff --git a/tests/test_delete_relationship.py b/tests/test_delete_relationship.py index 16995d4..42493b3 100644 --- a/tests/test_delete_relationship.py +++ b/tests/test_delete_relationship.py @@ -36,7 +36,7 @@ def request_callback(request): return (200, headers, json.dumps(response)) responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=request_callback, content_type='application/json', ) diff --git a/tests/test_query.py b/tests/test_query.py index 28dbc58..ccff7ef 100644 --- a/tests/test_query.py +++ b/tests/test_query.py @@ -7,6 +7,7 @@ from jupiterone.constants import QUERY_V1 from jupiterone.errors import JupiterOneApiError + def build_results(response_code: int = 200, cursor: str = None, max_pages: int = 1): pages = Counter(requests=0) @@ -57,7 +58,7 @@ def request_callback(request): pages.update(requests=1) - return (response_code, headers, json.dumps(response)) + return response_code, headers, json.dumps(response) return request_callback @@ -74,9 +75,8 @@ def request_callback(request): @responses.activate def test_execute_query(): - responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=build_results(), content_type='application/json', ) @@ -95,7 +95,7 @@ def test_execute_query(): assert 'data' in response assert 'queryV1' in response['data'] assert len(response['data']['queryV1']['data']) == 1 - assert type(response['data']['queryV1']['data']) == list + assert type(response['data']['queryV1']['data']) is list assert response['data']['queryV1']['data'][0]['entity']['_id'] == '1' @@ -103,7 +103,7 @@ def test_execute_query(): def test_limit_skip_query_v1(): responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=build_results(), content_type='application/json', ) @@ -116,22 +116,23 @@ def test_limit_skip_query_v1(): skip=0 ) - assert type(response) == dict + assert type(response) is dict assert len(response['data']) == 1 - assert type(response['data']) == list + assert type(response['data']) is list assert response['data'][0]['entity']['_id'] == '1' + @responses.activate def test_cursor_query_v1(): responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=build_results(cursor='cursor_value'), content_type='application/json', ) responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=build_results(), content_type='application/json', ) @@ -143,11 +144,12 @@ def test_cursor_query_v1(): query=query, ) - assert type(response) == dict + assert type(response) is dict assert len(response['data']) == 2 - assert type(response['data']) == list + assert type(response['data']) is list assert response['data'][0]['entity']['_id'] == '1' + @responses.activate def test_limit_skip_tree_query_v1(): @@ -174,10 +176,10 @@ def request_callback(request): } } - return (200, headers, json.dumps(response)) + return 200, headers, json.dumps(response) responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=request_callback, content_type='application/json', ) @@ -190,13 +192,14 @@ def request_callback(request): skip=0 ) - assert type(response) == dict + assert type(response) is dict assert 'edges' in response assert 'vertices' in response - assert type(response['edges']) == list - assert type(response['vertices']) == list + assert type(response['edges']) is list + assert type(response['vertices']) is list assert response['vertices'][0]['id'] == '1' + @responses.activate def test_cursor_tree_query_v1(): @@ -226,7 +229,7 @@ def request_callback(request): return (200, headers, json.dumps(response)) responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=request_callback, content_type='application/json', ) @@ -235,29 +238,30 @@ def request_callback(request): query = "find Host with _id='1' return tree" response = j1.query_v1(query) - assert type(response) == dict + assert type(response) is dict assert 'edges' in response assert 'vertices' in response - assert type(response['edges']) == list - assert type(response['vertices']) == list + assert type(response['edges']) is list + assert type(response['vertices']) is list assert response['vertices'][0]['id'] == '1' + @responses.activate def test_retry_on_limit_skip_query(): responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=build_results(response_code=429), content_type='application/json', ) responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=build_results(response_code=503), content_type='application/json', ) responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=build_results(), content_type='application/json', ) @@ -270,27 +274,28 @@ def test_retry_on_limit_skip_query(): skip=0 ) - assert type(response) == dict + assert type(response) is dict assert len(response['data']) == 1 - assert type(response['data']) == list + assert type(response['data']) is list assert response['data'][0]['entity']['_id'] == '1' + @responses.activate def test_retry_on_cursor_query(): responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=build_results(response_code=429), content_type='application/json', ) responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=build_results(response_code=503), content_type='application/json', ) responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=build_results(), content_type='application/json', ) @@ -301,15 +306,16 @@ def test_retry_on_cursor_query(): query=query ) - assert type(response) == dict + assert type(response) is dict assert len(response['data']) == 1 - assert type(response['data']) == list + assert type(response['data']) is list assert response['data'][0]['entity']['_id'] == '1' + @responses.activate def test_avoid_retry_on_limit_skip_query(): responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=build_results(response_code=404), content_type='application/json', ) @@ -323,10 +329,11 @@ def test_avoid_retry_on_limit_skip_query(): skip=0 ) + @responses.activate def test_avoid_retry_on_cursor_query(): responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=build_results(response_code=404), content_type='application/json', ) @@ -338,10 +345,11 @@ def test_avoid_retry_on_cursor_query(): query=query ) + @responses.activate def test_warn_limit_and_skip_deprecated(): responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=build_results(), content_type='application/json', ) @@ -360,7 +368,7 @@ def test_warn_limit_and_skip_deprecated(): @responses.activate def test_unauthorized_query_v1(): responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=build_error_results(401, b'Unauthorized', 'text/plain'), content_type='application/json', ) @@ -371,14 +379,14 @@ def test_unauthorized_query_v1(): with pytest.raises(JupiterOneApiError) as exc_info: j1.query_v1(query) - assert exc_info.value.args[0] == 'JupiterOne API query is unauthorized, check credentials.' + assert "401: Unauthorized" in str(exc_info.value.args[0]) @responses.activate -def test_unexpected_string_error_query_v1(): +def test_five_hundred_error_query_v1(): responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', - callback=build_error_results(500, 'String exception on server', 'text/plain'), + responses.POST, 'https://graphql.us.jupiterone.io', + callback=build_error_results(500, 'Internal Server Error', 'text/plain'), content_type='application/json', ) @@ -388,17 +396,17 @@ def test_unexpected_string_error_query_v1(): with pytest.raises(JupiterOneApiError) as exc_info: j1.query_v1(query) - assert exc_info.value.args[0] == '500:String exception on server' + assert exc_info.value.args[0] == 'JupiterOne API internal server error.' @responses.activate -def test_unexpected_json_error_query_v1(): +def test_bad_gateway_error_query_v1(): error_json = { 'error': 'Bad Gateway' } responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=build_error_results(502, json.dumps(error_json), ), content_type='application/json', ) @@ -408,26 +416,3 @@ def test_unexpected_json_error_query_v1(): with pytest.raises(JupiterOneApiError) as exc_info: j1.query_v1(query) - - assert exc_info.value.args[0] == '502:Bad Gateway' - - -@responses.activate -def test_unexpected_json_errors_query_v1(): - errors_json = { - 'errors': ['First error', 'Second error', 'Third error'] - } - - responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', - callback=build_error_results(500, json.dumps(errors_json), ), - content_type='application/json', - ) - - j1 = JupiterOneClient(account='testAccount', token='bogusToken') - query = "find Host with _id='1' return tree" - - with pytest.raises(JupiterOneApiError) as exc_info: - j1.query_v1(query) - - assert exc_info.value.args[0] == "500:['First error', 'Second error', 'Third error']" diff --git a/tests/test_update_entity.py b/tests/test_update_entity.py index f6bb6ce..cbd24c3 100644 --- a/tests/test_update_entity.py +++ b/tests/test_update_entity.py @@ -29,7 +29,7 @@ def request_callback(request): return (200, headers, json.dumps(response)) responses.add_callback( - responses.POST, 'https://api.us.jupiterone.io/graphql', + responses.POST, 'https://graphql.us.jupiterone.io', callback=request_callback, content_type='application/json', )