Skip to content

Commit b981b0c

Browse files
author
Laurence Joseph Pakenham-Smith
authored
Merge pull request #274 from NHSDigital/master
Master -> Edge update
2 parents 343d61e + 13a9337 commit b981b0c

10 files changed

Lines changed: 286 additions & 205 deletions

File tree

.github/workflows/tests.yaml

Lines changed: 0 additions & 38 deletions
This file was deleted.

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

Lines changed: 0 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -14,100 +14,6 @@
1414
"nhsd-prod": ["dev", "int", "sandbox", "prod"],
1515
}
1616

17-
# Maps unique API IDS to API names and Spec guids. One day this will
18-
# be a proper microservice. But for now, this will do.
19-
REGISTERED_META = [
20-
{
21-
"guid": "96836235-09a5-4064-9220-0812765ebdd7",
22-
"name": "canary-api",
23-
"spec_guids": ["0af08cfb-6835-47b5-867c-95d41ef849b5"],
24-
},
25-
{
26-
"guid": "b3d5c83f-98f2-429c-ba1d-646dccd139a3",
27-
"name": "hello-world",
28-
"spec_guids": ["e8663c19-725f-4883-b272-a9da868d5541"],
29-
},
30-
{
31-
"guid": "a3213966-9b13-400c-8fdd-e239e56a2742",
32-
"name": "mesh-api-specification",
33-
"spec_guids": ["73a3d6dd-912b-4793-bf4c-bf80c4bc34d1"],
34-
},
35-
{
36-
"guid": "eef32850-52ae-46da-9dbd-d9f3df818846",
37-
"name": "personal-demographics",
38-
"spec_guids": ["a343a204-f2d2-4287-a2e5-b5cb367e35bb"],
39-
},
40-
{
41-
"guid": "9c644a26-c926-4fae-9564-5a9c49ab332d",
42-
"name": "electronic-prescription-service-api",
43-
"spec_guids": ["5ead5713-9d2b-46eb-8626-def5fd2a2350"],
44-
},
45-
{
46-
"guid": "13cfc3dd-38c3-4692-9cfb-50d540e8cfe3",
47-
"name": "reasonable-adjustment-flag",
48-
"spec_guids": ["9f2d5659-ef7d-4815-ac25-d11f4ce75c25"],
49-
},
50-
{
51-
"guid": "090e12f4-6f3c-4ea7-b7eb-d70687d22cea",
52-
"name": "ambulance-analytics",
53-
"spec_guids": ["538699e8-d039-4473-9e35-e3b79eb92d1e"],
54-
},
55-
{
56-
"guid": "fa1c780f-6fb6-4c8e-a73c-eb2c306ca4f1",
57-
"name": "spine-directory-service",
58-
"spec_guids": ["88a3ec29-7ab1-4ac4-ae32-e367767b3ed8"],
59-
},
60-
{
61-
"guid": "7541eb6b-3416-4aee-bd66-8766c1f90cfb",
62-
"name": "nhs-app",
63-
"spec_guids": ["f5b9779e-d343-4a0a-8410-6dcae48bc55e"],
64-
},
65-
{
66-
"guid": "b26b0249-488d-44f9-93ed-9d2f08f3859c",
67-
"name": "signing-service",
68-
"spec_guids": ["a062e39c-b843-4833-8d24-8fc1434900a0",],
69-
},
70-
{
71-
"guid": "3ef873d7-18d3-4c51-b1f4-d36a3749c857",
72-
"name": "summary-care-record",
73-
"spec_guids": ["bec2d100-b515-4fa6-8a2f-617d73182b83"],
74-
},
75-
{
76-
"guid": "343026de-b0f5-4c45-a53e-3a1b687bab9d",
77-
"name": "e-referrals-service-api",
78-
"spec_guids": ["2ff6fce6-8b51-4d88-a528-4fd1edd18541"],
79-
},
80-
{
81-
"guid": "d5a3f4fc-e61f-41f3-ab72-16aa5ef3ff2b",
82-
"name": "identity-service",
83-
"spec_guids": [],
84-
},
85-
{
86-
"guid": "f61f73c1-2c9f-4f0c-b047-ab1464f867fc",
87-
"name": "async-slowapp",
88-
"spec_guids": [],
89-
},
90-
{
91-
"guid": "5d47b3a7-711e-4a2f-9db8-0e9dd06df24f",
92-
"name": "sync-wrap",
93-
"spec_guids": [],
94-
},
95-
{
96-
"guid": "d85314fc-9951-491c-95b1-debd819c9f3f",
97-
"name": "monitoring-service-discovery",
98-
"spec_guids": [],
99-
},
100-
{
101-
"guid": "9f11c568-4447-4a27-ad02-d67a846b8d59",
102-
"name": "risk-stratification",
103-
"spec_guids": ["36823b1f-bcba-4335-8fd6-f3e06a21f3db"],
104-
},
105-
{
106-
"guid": "7c2bcb03-c552-43d3-b5d7-757387453103",
107-
"name": "slackbot",
108-
"spec_guids": [],
109-
},
110-
]
11117

11218
def portal_uri(org: typing.Literal["nhsd-nonprod", "nhsd-prod"]) -> str:
11319
portal_ids = {

ansible/collections/ansible_collections/nhsd/apigee/plugins/module_utils/models/manifest/meta.py

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,20 @@
22
import typing
33

44

5-
from ansible_collections.nhsd.apigee.plugins.module_utils import constants
5+
from ansible_collections.nhsd.apigee.plugins.module_utils.paas import api_registry
66

77
SCHEMA_VERSION = "1.1.0"
88

9+
_REGISTRY_DATA = {}
10+
911

1012

1113
class ManifestMetaApi(pydantic.BaseModel):
1214
name: pydantic.constr(regex=r"^[a-z]+(-[a-z]+)*$")
1315
id: typing.Optional[pydantic.UUID4] = pydantic.Field(
1416
None, description="This field is deprecated, use guid instead."
1517
)
16-
guid: pydantic.UUID4 = None
18+
guid: typing.Optional[pydantic.UUID4] = None
1719
spec_guids: typing.Optional[typing.Set[pydantic.UUID4]] = None
1820

1921
def dict(self, **kwargs):
@@ -33,43 +35,52 @@ def dict(self, **kwargs):
3335

3436
@pydantic.validator("guid", pre=True, always=True)
3537
def id_to_guid(cls, guid, values):
38+
"""
39+
If using an old version of the manifest, this sets the 'guid'
40+
attribute from the now deprecated 'id' attribute.
41+
"""
3642
_id = values.get("id")
3743
if _id and not guid:
3844
return _id
3945
return guid
4046

41-
@pydantic.root_validator
42-
def validate_meta_api(cls, values):
43-
supplied_guid = str(values.get("guid"))
44-
45-
try:
46-
registered_meta = next(
47-
filter(lambda meta: meta["guid"] == supplied_guid, constants.REGISTERED_META)
48-
)
49-
except StopIteration:
50-
raise ValueError(
51-
f"Supplied meta.api.guid: '{supplied_guid}' does not match any registered API guid."
52-
)
53-
54-
registered_name = registered_meta["name"]
55-
supplied_name = values.get("name")
56-
if supplied_name != registered_name:
57-
raise ValueError(
58-
f"Supplied meta.api.name '{supplied_name}' does not match registered name {registered_name} for API guid {supplied_guid}."
59-
)
47+
@pydantic.validator("name")
48+
def set_global_name(cls, name):
49+
_REGISTRY_DATA[name] = api_registry.get(name)
50+
return name
51+
52+
@pydantic.validator("guid")
53+
def validate_guid(cls, guid, values):
54+
name = values.get("name")
55+
if name not in _REGISTRY_DATA:
56+
return # Other problems.
57+
if guid is None:
58+
guid = _REGISTRY_DATA[name]["guid"]
59+
registered_guid = _REGISTRY_DATA[name]["guid"]
60+
if str(guid) != registered_guid:
61+
raise ValueError(f"Supplied guid {guid} does not match registered guid {registered_guid}")
62+
return guid
6063

61-
supplied_spec_guids = values.get("spec_guids")
62-
if supplied_spec_guids is None: # For backwards compatibility
63-
return values
64+
@pydantic.validator("spec_guids")
65+
def validate_spec_guids(cls, spec_guids, values):
66+
# In theory these could be added over time, so for backwards
67+
# compatibility we just assert that the presented spec guids
68+
# are present
69+
name = values.get("name")
70+
if name not in _REGISTRY_DATA:
71+
return # Other problems.
72+
if spec_guids is None:
73+
spec_guids = _REGISTRY_DATA[name]["spec_guids"]
74+
registered_spec_guids = _REGISTRY_DATA[name]["spec_guids"]
6475

65-
registered_spec_guids = registered_meta["spec_guids"]
66-
for supplied_spec_guid in supplied_spec_guids:
67-
if str(supplied_spec_guid) not in registered_spec_guids:
68-
raise ValueError(
69-
f"Supplied meta.api.spec_guids entry '{supplied_spec_guid}' is not in list of registered spec_guids {registered_spec_guids} for API guid '{supplied_guid}'"
70-
)
76+
invalid = []
77+
for spec_guid in spec_guids:
78+
if str(spec_guid) not in registered_spec_guids:
79+
invalid.append(str(spec_guid))
80+
if len(invalid) > 0:
81+
raise ValueError(f"Supplied spec_guids {invalid} do not match registered spec_guids {registered_spec_guids}")
82+
return spec_guids
7183

72-
return values
7384

7485

7586
class ManifestMeta(pydantic.BaseModel):
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import requests
2+
import json
3+
4+
5+
from ansible_collections.nhsd.apigee.plugins.module_utils.paas import urls
6+
7+
8+
def get(name: str):
9+
url = urls.api_registry() + f"/api/{name}"
10+
resp = requests.get(url)
11+
12+
if resp.status_code != 200:
13+
try:
14+
detail = resp.json()["detail"]
15+
except json.decoder.JSONDecodeError:
16+
detail = resp.content.decode()
17+
raise ValueError(detail)
18+
return resp.json()
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import os
2+
3+
4+
def _localstack() -> bool:
5+
"""
6+
Returns True if environment variable APIM_INFRA_LOCALSTACK is set
7+
to something truthy.
8+
"""
9+
return bool(os.environ.get("APIM_INFRA_LOCALSTACK"))
10+
11+
12+
def api_registry() -> str:
13+
if _localstack():
14+
return "http://localhost:9000"
15+
return "https://api-registry.prod.api.platform.nhs.uk:9000"

ansible/collections/ansible_collections/nhsd/apigee/roles/template_manifest/tasks/main.yml

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,6 @@
1616
set_fact:
1717
manifest: "{{ lookup('template', manifest_template) | from_yaml_all | list | last }}"
1818

19-
- name: validate templated manifest
20-
nhsd.apigee.validate_manifest:
21-
manifest: "{{ manifest }}"
22-
service_name: "{{ SERVICE_NAME }}"
23-
dist_dir: "{{ DIST_DIR }}"
24-
2519
- name: write template to file
2620
copy:
2721
content: "{{ manifest | to_nice_yaml(indent=2) }}"
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import pytest
2+
3+
CANARY_API = {
4+
"guid": "96836235-09a5-4064-9220-0812765ebdd7",
5+
"name": "canary-api",
6+
"spec_guids": ["0af08cfb-6835-47b5-867c-95d41ef849b5"],
7+
}
8+
9+
10+
@pytest.fixture()
11+
def canary_guid():
12+
yield CANARY_API["guid"]
13+
14+
15+
@pytest.fixture()
16+
def canary_spec_guids():
17+
yield CANARY_API["spec_guids"]
18+
19+
20+
@pytest.fixture()
21+
def invalid_guid():
22+
"""A guid that's not in the (mock) registry."""
23+
yield "e1650537-76a0-4d30-83ab-947577ed88fd"
24+
25+
26+
@pytest.fixture(autouse=True)
27+
def mock_api_registry(monkeypatch):
28+
def _mock_api_registry_get(name: str):
29+
if name == CANARY_API["name"]:
30+
print("HELLO")
31+
return CANARY_API
32+
else:
33+
raise ValueError(f"No API named {name} found.")
34+
35+
monkeypatch.setattr(
36+
"ansible_collections.nhsd.apigee.plugins.module_utils.paas.api_registry.get",
37+
_mock_api_registry_get,
38+
)

0 commit comments

Comments
 (0)