Skip to content

Commit 43cfa39

Browse files
author
frickjack
committed
fix(PR): helpful review comments
1 parent 043dc99 commit 43cfa39

File tree

9 files changed

+71
-67
lines changed

9 files changed

+71
-67
lines changed

gen3/auth.py

Lines changed: 31 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,6 @@
1313
class Gen3AuthError(Exception):
1414
pass
1515

16-
class Gen3CurlError(Exception):
17-
""" Custom exception for capturing backoff and retry"""
18-
pass
19-
20-
class Gen3CurlStatusError(Gen3CurlError):
21-
""" Custom exception for status > 399"""
22-
pass
2316

2417
def decode_token(token_str):
2518
"""
@@ -35,7 +28,7 @@ def decode_token(token_str):
3528

3629
def endpoint_from_token(token_str):
3730
"""
38-
Extract the endpoint from a JWT issuer - ex:
31+
Extract the endpoint from a JWT issue ("iss" property)
3932
"""
4033
info = decode_token(token_str)
4134
urlparts = urlparse(info["iss"])
@@ -75,8 +68,7 @@ def get_wts_endpoint(namespace=os.getenv("NAMESPACE", "default")):
7568

7669
def get_wts_idps(namespace=os.getenv("NAMESPACE", "default")):
7770
resp = requests.get(get_wts_endpoint(namespace) + "/external_oidc")
78-
if resp.status_code != 200:
79-
raise Exception("non-200 status {} - {}".format(resp.status_code, resp.text))
71+
resp.raise_for_status()
8072
return resp.json()
8173

8274
def get_access_token_from_wts(namespace=os.getenv("NAMESPACE", "default"), idp="local"):
@@ -91,11 +83,6 @@ def get_access_token_from_wts(namespace=os.getenv("NAMESPACE", "default"), idp="
9183
resp = requests.get(auth_url)
9284
return _handle_access_token_response(resp, "token")
9385

94-
def check_curl_status(res):
95-
"""Raise Gen3CurlError if status is not < 400"""
96-
if res.status_code > 399:
97-
raise Gen3CurlStatusError("Got status: " + str(res.status_code))
98-
9986

10087
def token_cache_file(key):
10188
"""Compute the path to the access-token cache file"""
@@ -198,6 +185,7 @@ def __init__(self, endpoint=None, refresh_file=None, refresh_token=None, idp=Non
198185
with open(refresh_file) as f:
199186
file_data = f.read()
200187
self._refresh_token = json.loads(file_data)
188+
assert "api_key" in self._refresh_token
201189
except Exception as e:
202190
raise ValueError(
203191
"Couldn't load your refresh token file: {}\n{}".format(
@@ -301,27 +289,31 @@ def _get_auth_value(self):
301289

302290

303291
def curl(self, path, request=None, data=None):
304-
"""Curl the given endpoint - ex: gen3 curl /user/user"""
305-
try:
306-
if not request:
307-
request = "GET"
308-
if data:
309-
request = "POST"
310-
json_data = data
311-
output = None
312-
if data and data[0] == "@":
313-
with open(data[1:]) as f:
314-
json_data = f.read()
315-
if request == "GET":
316-
output = requests.get(self.endpoint + "/" + path, auth=self)
317-
elif request == "POST":
318-
output = requests.post(self.endpoint + "/" + path, json=json_data, auth=self)
319-
elif request == "PUT":
320-
output = requests.put(self.endpoint + "/" + path, json=json_data, auth=self)
321-
elif request == "DELETE":
322-
output = requests.delete(self.endpoint + "/" + path, auth=self)
323-
else:
324-
raise Exception("Invalid request type: " + request)
325-
return output
326-
except Exception as ex:
327-
raise Gen3CurlError from ex
292+
"""
293+
Curl the given endpoint - ex: gen3 curl /user/user. Return requests.Response
294+
295+
Args:
296+
path (str): path under the commons to curl (/user/user, /index/index, /authz/mapping, ...)
297+
request (str in GET|POST|PUT|DELETE): default to GET if data is not set, else default to POST
298+
data (str): json string or "@filename" of a json file
299+
"""
300+
if not request:
301+
request = "GET"
302+
if data:
303+
request = "POST"
304+
json_data = data
305+
output = None
306+
if data and data[0] == "@":
307+
with open(data[1:]) as f:
308+
json_data = f.read()
309+
if request == "GET":
310+
output = requests.get(self.endpoint + "/" + path, auth=self)
311+
elif request == "POST":
312+
output = requests.post(self.endpoint + "/" + path, json=json_data, auth=self)
313+
elif request == "PUT":
314+
output = requests.put(self.endpoint + "/" + path, json=json_data, auth=self)
315+
elif request == "DELETE":
316+
output = requests.delete(self.endpoint + "/" + path, auth=self)
317+
else:
318+
raise Exception("Invalid request type: " + request)
319+
return output

gen3/cli/__main__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,13 @@ def get(self):
2020

2121

2222
@click.group()
23-
@click.option("--auth", 'auth_config', default=os.getenv("GEN3_API_KEY", None), help="path to api key, or shorthand for key in ~/.gen3/, or idp: identifier if in workspace")
23+
@click.option("--auth", 'auth_config', default=os.getenv("GEN3_API_KEY", None),
24+
help="""authentication source:
25+
"idp://wts/<idp>" is an identity provider in a Gen3 workspace,
26+
"accesstoken:///<token>" is an access token,
27+
otherwise a path to an api key or basename of key under ~/.gen3/;
28+
default value is "credentials" if ~/.gen3/credentials.json exists, otherwise "idp://wts/local"
29+
""")
2430
@click.option("--endpoint", 'endpoint', default=os.getenv("GEN3_ENDPOINT", "default"), help="commons hostname - optional if API Key given")
2531
@click.pass_context
2632
def main(ctx=None, auth_config=None, endpoint=None):

gen3/cli/auth.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,6 @@ def wts_list():
5656
"""list the idp's available from the wts in a Gen3 workspace environment """
5757
print(json.dumps(auth_tool.get_wts_idps(), indent=2))
5858

59-
@click.command()
60-
@click.pass_context
61-
def info(ctx):
62-
"""Info about the current authentication mechanism"""
63-
print(ctx.obj["auth_factory"].get().get_access_token())
64-
6559
@click.group()
6660
def auth():
6761
"""Gen3 sdk auth commands"""

gen3/index.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,18 +16,23 @@ class Gen3Index:
1616
A class for interacting with the Gen3 Index services.
1717
1818
Args:
19+
endpoint (str): public endpoint for reading/querying indexd - only necessary if auth_provider not provided
1920
auth_provider (Gen3Auth): A Gen3Auth class instance or indexd basic creds tuple
2021
2122
Examples:
2223
This generates the Gen3Index class pointed at the sandbox commons while
2324
using the credentials.json downloaded from the commons profile page.
2425
2526
>>> auth = Gen3Auth(refresh_file="credentials.json")
26-
... sub = Gen3Submission(auth.endpoint, auth)
27+
... sub = Gen3Submission(auth)
2728
2829
"""
2930

3031
def __init__(self, endpoint=None, auth_provider=None, service_location="index"):
32+
# legacy interface required endpoint as 1st arg
33+
if endpoint and isinstance(endpoint,Gen3Auth):
34+
auth_provider = endpoint
35+
endpoint = None
3136
if auth_provider and isinstance(auth_provider,Gen3Auth):
3237
endpoint = auth_provider.endpoint
3338
endpoint = endpoint.strip("/")

gen3/jobs.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ def __init__(self, endpoint=None, auth_provider=None, service_location="job"):
4343
service_location (str, optional): deployment location relative to the
4444
endpoint provided
4545
"""
46+
# auth_provider legacy interface required endpoint as 1st arg
4647
auth_provider = auth_provider or endpoint
4748
endpoint = auth_provider.endpoint.strip("/")
4849
# if running locally, mds is deployed by itself without a location relative

gen3/metadata.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import sys
1010

1111
from gen3.utils import append_query_params, DEFAULT_BACKOFF_SETTINGS
12+
from gen3.auth import Gen3Auth
1213

1314

1415
class Gen3Metadata:
@@ -19,17 +20,17 @@ class Gen3Metadata:
1920
This generates the Gen3Metadata class pointed at the sandbox commons while
2021
using the credentials.json downloaded from the commons profile page.
2122
22-
>>> auth = Gen3Auth(endpoint, refresh_file="credentials.json")
23-
... sub = Gen3Metadata(auth.endpoint, auth)
23+
>>> auth = Gen3Auth(refresh_file="credentials.json")
24+
... sub = Gen3Metadata(auth)
2425
2526
Attributes:
26-
admin_endpoint (str): endpoint for admin functionality (Create/Update/Delete)
27-
endpoint (str): public endpoint for reading/querying metadata
27+
endpoint (str): public endpoint for reading/querying metadata - only necessary if auth_provider not provided
28+
auth_provider (Gen3Auth): auth manager
2829
"""
2930

3031
def __init__(
3132
self,
32-
endpoint,
33+
endpoint=None,
3334
auth_provider=None,
3435
service_location="mds",
3536
admin_endpoint_suffix="-admin",
@@ -44,6 +45,12 @@ def __init__(
4445
service_location (str, optional): deployment location relative to the
4546
endpoint provided
4647
"""
48+
# legacy interface required endpoint as 1st arg
49+
if endpoint and isinstance(endpoint,Gen3Auth):
50+
auth_provider = endpoint
51+
endpoint = None
52+
if auth_provider and isinstance(auth_provider,Gen3Auth):
53+
endpoint = auth_provider.endpoint
4754
endpoint = endpoint.strip("/")
4855
# if running locally, mds is deployed by itself without a location relative
4956
# to the commons

gen3/submission.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class Gen3Submission:
3737
"""
3838

3939
def __init__(self, endpoint=None, auth_provider=None):
40+
# auth_provider legacy interface required endpoint as 1st arg
4041
self._auth_provider = auth_provider or endpoint
4142
self._endpoint = self._auth_provider.endpoint
4243

gen3/wss.py

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
from urllib.parse import urlparse
77

88
from gen3.utils import append_query_params, DEFAULT_BACKOFF_SETTINGS
9-
from gen3.auth import Gen3CurlError, check_curl_status
109

1110

1211
def wsurl_to_tokens(ws_urlstr):
@@ -20,23 +19,23 @@ def wsurl_to_tokens(ws_urlstr):
2019
raise Exception("invalid path {}".format(ws_urlstr))
2120
return (pathparts[0], "/".join(pathparts[1:]))
2221

23-
@backoff.on_exception(backoff.expo, Gen3CurlError, **DEFAULT_BACKOFF_SETTINGS)
22+
@backoff.on_exception(backoff.expo, requests.HTTPError, **DEFAULT_BACKOFF_SETTINGS)
2423
def get_url(urlstr, dest_path):
2524
"""Simple url fetch to dest_path with backoff"""
2625
res = requests.get(urlstr)
27-
check_curl_status(res)
26+
res.raise_for_status()
2827
if dest_path == "-":
2928
sys.stdout.write(res.text)
3029
else:
3130
with open(dest_path, 'wb') as f:
3231
f.write(res.content)
3332

34-
@backoff.on_exception(backoff.expo, Gen3CurlError, **DEFAULT_BACKOFF_SETTINGS)
33+
@backoff.on_exception(backoff.expo, requests.HTTPError, **DEFAULT_BACKOFF_SETTINGS)
3534
def put_url(urlstr, src_path):
3635
"""Simple put src_path to url with backoff"""
3736
with open(src_path, 'rb') as f:
3837
res = requests.put(urlstr, data=f)
39-
check_curl_status(res)
38+
res.raise_for_status()
4039

4140

4241
class Gen3WsStorage:
@@ -63,7 +62,7 @@ def __init__(
6362
"""
6463
self._auth_provider = auth_provider
6564

66-
@backoff.on_exception(backoff.expo, Gen3CurlError, **DEFAULT_BACKOFF_SETTINGS)
65+
@backoff.on_exception(backoff.expo, requests.HTTPError, **DEFAULT_BACKOFF_SETTINGS)
6766
def upload_url(self, ws, wskey):
6867
"""
6968
Get a upload url for the given workspace key
@@ -74,19 +73,19 @@ def upload_url(self, ws, wskey):
7473
"""
7574
wskey = wskey.lstrip("/")
7675
res = self._auth_provider.curl("/ws-storage/upload/{}/{}".format(ws, wskey))
77-
check_curl_status(res)
76+
res.raise_for_status()
7877
return res.json()
7978

8079

81-
@backoff.on_exception(backoff.expo, Gen3CurlError, **DEFAULT_BACKOFF_SETTINGS)
80+
@backoff.on_exception(backoff.expo, requests.HTTPError, **DEFAULT_BACKOFF_SETTINGS)
8281
def upload(self, src_path, dest_ws, dest_wskey):
8382
"""
8483
Upload a local file to the specified workspace path
8584
"""
8685
url = self.upload_url(dest_ws, dest_wskey)["Data"]
8786
put_url(url, src_path)
8887

89-
@backoff.on_exception(backoff.expo, Gen3CurlError, **DEFAULT_BACKOFF_SETTINGS)
88+
@backoff.on_exception(backoff.expo, requests.HTTPError, **DEFAULT_BACKOFF_SETTINGS)
9089
def download_url(self, ws, wskey):
9190
"""
9291
Get a download url for the given workspace key
@@ -97,7 +96,7 @@ def download_url(self, ws, wskey):
9796
"""
9897
wskey = wskey.lstrip("/")
9998
res = self._auth_provider.curl("/ws-storage/download/{}/{}".format(ws, wskey))
100-
check_curl_status(res)
99+
res.raise_for_status()
101100
return res.json()
102101

103102

@@ -128,7 +127,7 @@ def copy(self, src_urlstr, dest_urlstr):
128127
return self.upload(src_urlstr, pathparts[0], pathparts[1])
129128
raise Exception("source and destination may not both be local")
130129

131-
@backoff.on_exception(backoff.expo, Gen3CurlError, **DEFAULT_BACKOFF_SETTINGS)
130+
@backoff.on_exception(backoff.expo, requests.HTTPError, **DEFAULT_BACKOFF_SETTINGS)
132131
def ls(self, ws, wskey):
133132
"""
134133
List the contents under the given workspace path
@@ -139,7 +138,7 @@ def ls(self, ws, wskey):
139138
"""
140139
wskey = wskey.lstrip("/")
141140
res = self._auth_provider.curl("/ws-storage/list/{}/{}".format(ws, wskey))
142-
check_curl_status(res)
141+
res.raise_for_status()
143142
return res.json()
144143

145144

@@ -155,7 +154,7 @@ def ls_path(self, ws_urlstr):
155154
pathparts = wsurl_to_tokens(ws_urlstr)
156155
return self.ls(pathparts[0], pathparts[1])
157156

158-
@backoff.on_exception(backoff.expo, Gen3CurlError, **DEFAULT_BACKOFF_SETTINGS)
157+
@backoff.on_exception(backoff.expo, requests.HTTPError, **DEFAULT_BACKOFF_SETTINGS)
159158
def rm(self, ws, wskey):
160159
"""
161160
Remove the given workspace key
@@ -166,7 +165,7 @@ def rm(self, ws, wskey):
166165
"""
167166
wskey = wskey.lstrip("/")
168167
res = self._auth_provider.curl("/ws-storage/list/{}/{}".format(ws, wskey), request="DELETE")
169-
check_curl_status(res)
168+
res.raise_for_status()
170169
return res.json()
171170

172171
def rm_path(self, ws_urlstr):

tests/test_auth.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ def _mock_request(url, **kwargs):
5959
mocked_response.json.return_value = {
6060
"token": access_token
6161
}
62-
#mocked_response.raise_for_status.side_effect = lambda *args: None
6362
return mocked_response
6463

6564
with patch("gen3.auth.requests") as mock_request:

0 commit comments

Comments
 (0)