Skip to content

Commit 38502db

Browse files
authored
Merge pull request #690 from FlorentinD/check-aura-api-expiry
Warn about aura api endpoint expiration
2 parents fafa2e5 + 4dd1cc8 commit 38502db

File tree

2 files changed

+49
-20
lines changed

2 files changed

+49
-20
lines changed

graphdatascience/session/aura_api.py

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import logging
44
import os
55
import time
6+
import warnings
67
from typing import Any, Dict, List, Optional, Tuple
78
from urllib.parse import urlparse
89

@@ -65,7 +66,7 @@ def create_session(self, name: str, dbid: str, pwd: str, memory: SessionMemoryVa
6566
json={"name": name, "instance_id": dbid, "password": pwd, "memory": memory.value},
6667
)
6768

68-
self._check_code(response)
69+
self._check_resp(response)
6970

7071
return SessionDetails.fromJson(response.json())
7172

@@ -77,7 +78,7 @@ def list_session(self, session_id: str, dbid: str) -> Optional[SessionDetails]:
7778
if response.status_code == 404:
7879
return None
7980

80-
self._check_code(response)
81+
self._check_resp(response)
8182

8283
return SessionDetails.fromJson(response.json())
8384

@@ -86,7 +87,7 @@ def list_sessions(self, dbid: str) -> List[SessionDetails]:
8687
f"{self._base_uri}/v1beta5/data-science/sessions?instanceId={dbid}",
8788
)
8889

89-
self._check_code(response)
90+
self._check_resp(response)
9091

9192
return [SessionDetails.fromJson(s) for s in response.json()]
9293

@@ -125,12 +126,13 @@ def delete_session(self, session_id: str, dbid: str) -> bool:
125126
json={"instance_id": dbid},
126127
)
127128

129+
self._check_endpoint_expiry(response)
130+
128131
if response.status_code == 404:
129132
return False
130133
elif response.status_code == 202:
131134
return True
132-
133-
self._check_code(response)
135+
self._check_endpoint_expiry(response)
134136

135137
return False
136138

@@ -151,7 +153,7 @@ def create_instance(
151153

152154
response = self._request_session.post(f"{self._base_uri}/v1/instances", json=data)
153155

154-
self._check_code(response)
156+
self._check_resp(response)
155157

156158
return InstanceCreateDetails.from_json(response.json()["data"])
157159

@@ -161,14 +163,14 @@ def delete_instance(self, instance_id: str) -> Optional[InstanceSpecificDetails]
161163
if response.status_code == 404:
162164
return None
163165

164-
self._check_code(response)
166+
self._check_resp(response)
165167

166168
return InstanceSpecificDetails.fromJson(response.json()["data"])
167169

168170
def list_instances(self) -> List[InstanceDetails]:
169171
response = self._request_session.get(f"{self._base_uri}/v1/instances", params={"tenantId": self._tenant_id})
170172

171-
self._check_code(response)
173+
self._check_resp(response)
172174

173175
raw_data = response.json()["data"]
174176

@@ -180,7 +182,7 @@ def list_instance(self, instance_id: str) -> Optional[InstanceSpecificDetails]:
180182
if response.status_code == 404:
181183
return None
182184

183-
self._check_code(response)
185+
self._check_resp(response)
184186

185187
raw_data = response.json()["data"]
186188

@@ -221,13 +223,13 @@ def estimate_size(
221223
}
222224

223225
response = self._request_session.post(f"{self._base_uri}/v1/instances/sizing", json=data)
224-
self._check_code(response)
226+
self._check_resp(response)
225227

226228
return EstimationDetails.from_json(response.json()["data"])
227229

228230
def _get_tenant_id(self) -> str:
229231
response = self._request_session.get(f"{self._base_uri}/v1/tenants")
230-
self._check_code(response)
232+
self._check_resp(response)
231233

232234
raw_data = response.json()["data"]
233235

@@ -242,17 +244,30 @@ def _get_tenant_id(self) -> str:
242244
def tenant_details(self) -> TenantDetails:
243245
if not self._tenant_details:
244246
response = self._request_session.get(f"{self._base_uri}/v1/tenants/{self._tenant_id}")
245-
self._check_code(response)
247+
self._check_resp(response)
246248
self._tenant_details = TenantDetails.from_json(response.json()["data"])
247249
return self._tenant_details
248250

249-
def _check_code(self, resp: requests.Response) -> None:
251+
def _check_resp(self, resp: requests.Response) -> None:
252+
self._check_status_code(resp)
253+
self._check_endpoint_expiry(resp)
254+
255+
def _check_status_code(self, resp: requests.Response) -> None:
250256
if resp.status_code >= 400:
251257
raise AuraApiError(
252258
f"Request for {resp.url} failed with status code {resp.status_code} - {resp.reason}: {resp.text}",
253259
status_code=resp.status_code,
254260
)
255261

262+
def _check_endpoint_expiry(self, resp: requests.Response) -> None:
263+
expiry_date = resp.headers.get("X-Tyk-Api-Expires")
264+
if expiry_date:
265+
warnings.warn(
266+
f"The endpoint is deprecated and will be removed on {expiry_date}."
267+
" Please update to a newer version of this client.",
268+
DeprecationWarning,
269+
)
270+
256271
def _instance_type(self) -> str:
257272
return "enterprise-ds" if not self._dev_env else "professional-ds"
258273

graphdatascience/tests/unit/test_aura_api.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@
2020
from graphdatascience.session.session_sizes import SESSION_MEMORY_VALUE_UNKNOWN
2121

2222

23+
def mock_auth_token(requests_mock: Mocker) -> None:
24+
requests_mock.post(
25+
"https://api.neo4j.io/oauth/token",
26+
json={"access_token": "very_short_token", "expires_in": 500, "token_type": "Bearer"},
27+
)
28+
29+
2330
def test_create_session(requests_mock: Mocker) -> None:
2431
api = AuraApi(client_id="", client_secret="", tenant_id="some-tenant")
2532

@@ -366,6 +373,20 @@ def test_create_instance(requests_mock: Mocker) -> None:
366373
assert requested_data["region"] == "leipzig-1"
367374

368375

376+
def test_warn_about_expirying_endpoint(requests_mock: Mocker) -> None:
377+
api = AuraApi(client_id="", client_secret="", tenant_id="some-tenant")
378+
379+
mock_auth_token(requests_mock)
380+
requests_mock.delete(
381+
"https://api.neo4j.io/v1beta5/data-science/sessions/id0",
382+
status_code=202,
383+
headers={"X-Tyk-Api-Expires": "Mon, 03 Mar 2025 00:00:00 UTC"},
384+
)
385+
386+
with pytest.warns(DeprecationWarning):
387+
api.delete_session("id0", "dbid-1")
388+
389+
369390
def test_auth_token(requests_mock: Mocker) -> None:
370391
api = AuraApi(client_id="", client_secret="", tenant_id="some-tenant")
371392

@@ -508,13 +529,6 @@ def test_list_missing_instance(requests_mock: Mocker) -> None:
508529
assert api.list_instance("id0") is None
509530

510531

511-
def mock_auth_token(requests_mock: Mocker) -> None:
512-
requests_mock.post(
513-
"https://api.neo4j.io/oauth/token",
514-
json={"access_token": "very_short_token", "expires_in": 500, "token_type": "Bearer"},
515-
)
516-
517-
518532
def test_dont_wait_forever(requests_mock: Mocker, caplog: LogCaptureFixture) -> None:
519533
mock_auth_token(requests_mock)
520534
requests_mock.get(

0 commit comments

Comments
 (0)