|
| 1 | +import requests |
| 2 | +import json |
| 3 | +import bisect |
1 | 4 | import copy |
| 5 | + |
2 | 6 | from ansible_collections.nhsd.apigee.plugins.module_utils.models.ansible.add_jwks_resource_url import ( |
3 | 7 | AddJwksResourceUrlToApp |
4 | 8 | ) |
|
8 | 12 | from ansible_collections.nhsd.apigee.plugins.module_utils import utils |
9 | 13 | from ansible_collections.nhsd.apigee.plugins.module_utils import constants |
10 | 14 |
|
11 | | - |
12 | 15 | ATTRIBUTE_NAME = "jwks-resource-url" |
13 | 16 |
|
14 | 17 |
|
| 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 | + |
15 | 61 | class ActionModule(ApigeeAction): |
16 | 62 | def run(self, tmp=None, task_vars=None): |
17 | 63 | super(ActionModule, self).run(tmp, task_vars) |
@@ -39,15 +85,23 @@ def run(self, tmp=None, task_vars=None): |
39 | 85 | if diff_mode: |
40 | 86 | result["diff"] = [{"before": before, "after": after}] |
41 | 87 |
|
| 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 |
42 | 96 | if check_mode: |
43 | 97 | return result |
44 | 98 |
|
45 | | - developer_email = args._app_data["createdBy"] |
46 | 99 | app_name = args._app_data["name"] |
47 | 100 | app_attribute_url = ( |
48 | 101 | 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" |
50 | 103 | ) |
| 104 | + |
51 | 105 | app_data2 = utils.post(app_attribute_url, args.access_token, |
52 | 106 | json={"attribute": after["attributes"]}) |
53 | 107 | if app_data2.get("failed"): |
|
0 commit comments