Skip to content

Commit 01bfc4c

Browse files
authored
Merge pull request #261 from NHSDigital/APM-1873-fix-developer-lookup
APM-1873 Fix developer lookup
2 parents 3512052 + c62008b commit 01bfc4c

2 files changed

Lines changed: 61 additions & 5 deletions

File tree

ansible/collections/ansible_collections/nhsd/apigee/plugins/action/add_jwks_resource_url_to_app.py

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1+
import requests
2+
import json
3+
import bisect
14
import copy
5+
26
from ansible_collections.nhsd.apigee.plugins.module_utils.models.ansible.add_jwks_resource_url import (
37
AddJwksResourceUrlToApp
48
)
@@ -8,10 +12,52 @@
812
from ansible_collections.nhsd.apigee.plugins.module_utils import utils
913
from ansible_collections.nhsd.apigee.plugins.module_utils import constants
1014

11-
1215
ATTRIBUTE_NAME = "jwks-resource-url"
1316

1417

18+
class LazyDeveloperDetails:
19+
"""
20+
Gets a list of all developers for an apigee organization. Lazily
21+
looks up details based on __getitem__ access. Since Apigee
22+
returns the entire list developers sorted by their internal
23+
'developerId' attribute, this allows us to quickly binary search
24+
our way to a developer's details when we only know their
25+
developerId.
26+
"""
27+
28+
def __init__(self, org, token):
29+
self._base_url = (constants.APIGEE_BASE_URL
30+
+ f"organizations/{org}/developers/")
31+
self._token = token
32+
self._session = requests.Session()
33+
34+
self.emails = self._get("")
35+
self.details = [None for email in self.emails]
36+
37+
def _get(self, email: str):
38+
"""
39+
Get developer details from email.
40+
Get all developers if email = ''
41+
42+
Raises a RuntimeError if the request does not return 200.
43+
This allows us to bubble the exception up to an ansible
44+
response.
45+
"""
46+
resp = utils.get(self._base_url + email,
47+
self._token, session=self._session)
48+
if resp.get("failed"):
49+
raise RuntimeError(json.dumps(resp))
50+
return resp["response"]["body"]
51+
52+
def __getitem__(self, i: int):
53+
if self.details[i] is None:
54+
self.details[i] = self._get(self.emails[i])
55+
return self.details[i]["developerId"]
56+
57+
def __len__(self):
58+
return len(self.emails)
59+
60+
1561
class ActionModule(ApigeeAction):
1662
def run(self, tmp=None, task_vars=None):
1763
super(ActionModule, self).run(tmp, task_vars)
@@ -39,15 +85,23 @@ def run(self, tmp=None, task_vars=None):
3985
if diff_mode:
4086
result["diff"] = [{"before": before, "after": after}]
4187

88+
developer_details = LazyDeveloperDetails(args.organization, args.access_token)
89+
try:
90+
i = bisect.bisect_left(developer_details, args._app_data["developerId"])
91+
except RuntimeError as e:
92+
return json.loads(str(e))
93+
developer = developer_details.details[i]
94+
95+
result["developer"] = developer
4296
if check_mode:
4397
return result
4498

45-
developer_email = args._app_data["createdBy"]
4699
app_name = args._app_data["name"]
47100
app_attribute_url = (
48101
constants.APIGEE_BASE_URL
49-
+ f"organizations/{args.organization}/developers/{developer_email}/apps/{app_name}/attributes"
102+
+ f"organizations/{args.organization}/developers/{developer['email']}/apps/{app_name}/attributes"
50103
)
104+
51105
app_data2 = utils.post(app_attribute_url, args.access_token,
52106
json={"attribute": after["attributes"]})
53107
if app_data2.get("failed"):

ansible/collections/ansible_collections/nhsd/apigee/plugins/module_utils/utils.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def delta(before, after, keys_to_ignore=None):
2525
)
2626

2727

28-
def request(method, url, access_token, json=None, headers=None, status_code=None):
28+
def request(method, url, access_token, json=None, headers=None, status_code=None, session=None):
2929
if not status_code:
3030
status_code = [200]
3131

@@ -34,7 +34,9 @@ def request(method, url, access_token, json=None, headers=None, status_code=None
3434

3535
headers["authorization"] = f"Bearer {access_token}"
3636

37-
response = requests.request(method, url, json=json, headers=headers)
37+
if session is None:
38+
session = requests
39+
response = session.request(method, url, json=json, headers=headers)
3840

3941
response_dict = {
4042
"response": {"status_code": response.status_code, "reason": response.reason,},

0 commit comments

Comments
 (0)