Skip to content

Commit

Permalink
[NRLF-187] deploy to sandbox env (#18)
Browse files Browse the repository at this point in the history
Co-authored-by: Joel Klinger <[email protected]>
  • Loading branch information
jaklinger and jaklinger authored Jan 6, 2023
1 parent 00bf71f commit 9c8cf75
Show file tree
Hide file tree
Showing 11 changed files with 173 additions and 32 deletions.
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,8 @@ release: clean publish build-proxy

#Command to run end-to-end smoktests post-deployment to verify the environment is working
smoketest:
poetry run pytest -v --junitxml=smoketest-report.xml -s --proxy-name=${PROXY_NAME} --api-name=${API_NAME}
@if [[ "${PROXY_NAME}" == *sandbox ]]; then\
poetry run pytest -v --junitxml=smoketest-report.xml -s --proxy-name=${PROXY_NAME} --api-name=${API_NAME} -m "not smoketest";\
else\
poetry run pytest -v --junitxml=smoketest-report.xml -s --proxy-name=${PROXY_NAME} --api-name=${API_NAME} -m "not sandbox";\
fi;
24 changes: 17 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ The `project.yml` file needs to be populated with your service names to make the

This folder contains files relating to your Apigee API proxy.

There are 2 folders `/live` and `/sandbox` allowing you to define a different proxy for sandbox use. By default, this sandbox proxy is implemented to route to the sandbox target server (code for this sandbox is found under /sandbox of this template repo)
There are 2 folders `/live` and `/sandbox` allowing you to define a different proxy for sandbox use. By default, this sandbox proxy is implemented to route to the sandbox target server.

Within the `live/apiproxy` and `sandbox/apiproxy` folders are:

Expand All @@ -140,10 +140,6 @@ Contains useful scripts that are used throughout the project, for example in Mak

Create an OpenAPI Specification to document your API. For more information about developing specifications see the [API Producer Zone confluence](https://nhsd-confluence.digital.nhs.uk/display/APM/Documenting+your+API).

#### `/tests`:

End to End tests. These tests are written in Python and use the PyTest test runner. Before running these tests you will need to set environment variables. The `test_endpoint.py` file provides a template of how to set up tests which test your api endpoints. For more information about testing your API see the [API Producer Zone confluence](https://nhsd-confluence.digital.nhs.uk/display/APM/Testing+your+API ).

#### `Makefile`:
Useful make targets to get started including: installing dependencies and running smoke tests.

Expand All @@ -167,7 +163,7 @@ This template uses poetry for python dependency management, and uses these files

Node dependencies of this template project and some npm scripts are listed in: package.json, package-lock.json.

## PLEASE UPDATE ME - how to run the tests
## How to run the tests

Before you can run any tests you need to setup your Apigee token, this can be done as shown:

Expand All @@ -187,4 +183,18 @@ Example using for the current product deployed to `internal-dev`:

Example using the product deployed for GitHub pull request 15:

`pytest tests/api_tests.py::test_smoke --proxy-name="nrl-producer-api-pr-15" --api-name=nrl-producer-api`
`pytest tests/api_tests.py::test_smoke --proxy-name="nrl-producer-api-pr-15" --api-name=nrl-producer-api`


## Sandbox data

The public sandbox ("Try this API") endpoints come with:

* Pre-loaded data: see [cron/seed_sandbox/data/document-pointer.json](https://github.com/NHSDigital/NRLF/blob/main/cron/seed_sandbox/data/document-pointer.json)
* Pre-configured organization permissions: [ConnectionMetadata.SetRequestHeaders.js](proxies/sandbox/apiproxy/resources/jsc/ConnectionMetadata.SetRequestHeaders.js)

Developers should make sure that these align according to any user journeys that they envisage.

Additionally, and less importantly, there are:

* Fixed organization details: see [ClientRPDetailsHeader.SetRequestHeaders.js](proxies/sandbox/apiproxy/resources/jsc/ClientRPDetailsHeader.SetRequestHeaders.js)
8 changes: 4 additions & 4 deletions azure/azure-pr-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ extends:
- environment: internal-dev
post_deploy:
- template: ./templates/run-smoke-tests.yml
# - environment: internal-dev-sandbox
# proxy_path: sandbox
# post_deploy:
# - template: ./templates/run-smoke-tests.yml
- environment: internal-dev-sandbox
proxy_path: sandbox
post_deploy:
- template: ./templates/run-smoke-tests.yml
20 changes: 10 additions & 10 deletions azure/azure-release-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,23 +34,23 @@ extends:
- environment: internal-dev
post_deploy:
- template: ./templates/run-smoke-tests.yml
# - environment: internal-dev-sandbox
# proxy_path: sandbox
# post_deploy:
# - template: ./templates/run-smoke-tests.yml
- environment: internal-dev-sandbox
proxy_path: sandbox
post_deploy:
- template: ./templates/run-smoke-tests.yml
# - environment: internal-qa
# post_deploy:
# - template: ./templates/run-smoke-tests.yml
# - environment: internal-qa-sandbox
# proxy_path: sandbox
# post_deploy:
# - template: ./templates/run-smoke-tests.yml
# - environment: ref
# depends_on:
# - internal_qa
# - internal_qa_sandbox
# post_deploy:
# - template: ./templates/run-smoke-tests.yml
- environment: ref
depends_on:
- internal-dev # default was: internal_qa
- internal-dev-sandbox # default was: internal_qa_sandbox
post_deploy:
- template: ./templates/run-smoke-tests.yml
# - environment: sandbox
# proxy_path: sandbox
# post_deploy:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* This script is used to set the NHSD-Client-RP-Details header, which is passed
* to the API.
*
* this contains:
*
* developer.app.id - The APIGEE ID associated with the APIGEE App connecting
* developer.app.name - The name of the APIGEE App
* developer.app.nhs-login-minimum-proofing-level - The P0/P5/P9 requirement when using User Based Authentication
* client.ip - The client's IP address
*
*/

var clientIP = context.getVariable("client.ip");

var clientRpDetailsHeader = {
"developer.app.name": "sandbox-app-not-a-real-app",
"developer.app.id": "sandbox-id-not-a-real-app",
"developer.app.nhs-login-minimum-proofing-level": "not-a-real-proofing-level",
"client.ip": clientIP,
};

context.targetRequest.headers["NHSD-Client-RP-Details"] = clientRpDetailsHeader;
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* This script reads a mocked (hard-coded, thanks APIGEE...) Custom Attribute which
* in the non-sandbox environments comes from an APIGEE app. These are sent to the API
* as the `NHSD-Connection-Metadata` header.
*
* The Http Header 'NHSD-End-User-Organisation-ODS' is expected.
*/

//---- CHANGE AVAILABLE POINTER TYPES FOR EACH ORGANISATION HERE ----//
const nrlPointers = {
RJ11: [
"https://snomed.info/ict|736253001",
"https://snomed.info/ict|736253002",
],
XYZ: ["https://snomed.info/ict|123", "https://snomed.info/ict|456"],
};
//-------------------------------------------------------------------//

(function () {
var odsCode = context.getVariable(
"request.header.NHSD-End-User-Organisation-ODS"
);
if (!odsCode || odsCode.trim().length === 0) {
context.setVariable("badRequest", true);
return;
}

var nrlPointerTypes = nrlPointers[odsCode];
if (!nrlPointerTypes) {
context.setVariable("badRequest", true);
return;
}

var connectionMetadata = {
"nrl.ods-code": odsCode,
"nrl.pointer-types": nrlPointerTypes,
};
context.targetRequest.headers["NHSD-Connection-Metadata"] =
connectionMetadata;
})();
21 changes: 21 additions & 0 deletions proxies/sandbox/apiproxy/resources/jsc/WritePathToVariable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* This JS has been added to rewrite the path
* from /FHIR/R4/xxx
* to /production/xxx
*
* We are required to do this because we are using the AWS Auto Generated
* hostnames for AWS API Gateway and the resulting URL then contains the stage
* name (e.g. "production"), which must be removed.
*
* We do this by calculating a new path and writing it to the `target_path`
* variable. This variable is then used in the TargetEndpoint
* (proxies/live/targets/default.xml) under the HTTPTargetConnection/Path
*/

proxyPathsuffix = context.getVariable("proxy.pathsuffix"); // -> /FHIR/R4/DocumentReference
targetPathsuffix = proxyPathsuffix.replace("/FHIR/R4", "/production"); // -> /production/DocumentReference

// If we don't set this then it will add the "/FHIR/R4/DocumentReference"
context.setVariable("target.copy.pathsuffix", false);
// Write the new path into the variable 'target_path'
context.setVariable("target_path", targetPathsuffix);
4 changes: 2 additions & 2 deletions pytest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ python_files = *_tests.py test_*.py
norecursedirs = .venv .eggs build dist utils
addopts = --strict-markers
markers =
e2e: end to end tests
smoketest: suitable to run against all environments even production
smoketest: suitable to run against all environments even production, except *sandbox
sandbox: suitable to run against all sandbox environments
9 changes: 9 additions & 0 deletions tests/common_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import requests
import json


def test_ping_endpoint(nhsd_apim_proxy_url):
resp = requests.get(nhsd_apim_proxy_url + "/_ping")
assert resp.status_code == 200
ping_data = json.loads(resp.text)
assert "version" in ping_data
40 changes: 40 additions & 0 deletions tests/sandbox_smoke_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from uuid import uuid4

import pytest
import requests

import urllib.parse


@pytest.mark.sandbox
@pytest.mark.parametrize(
["ods_code", "expected"],
[
[
"RJ11",
200,
],
[
"",
400,
],
[
"VALID_ODS_CODE_BUT_NOT_GRANTED",
403,
],
],
)
def test_smoke(ods_code: str, expected: int, nhsd_apim_proxy_url):

headers = {
"accept": "application/json; version=1.0",
"x-correlation-id": f"SMOKE:{uuid4()}-odsCode_{ods_code}-expected_{expected}",
"x-request-id": f"{uuid4()}",
"NHSD-End-User-Organisation-ODS": ods_code,
"Authorization": "letmein",
}

patient_id = urllib.parse.quote("https://fhir.nhs.uk/Id/nhs-number|9278693472")
url = f"{nhsd_apim_proxy_url}/FHIR/R4/DocumentReference?subject={patient_id}"
response = requests.get(url, headers=headers)
assert response.status_code == expected, response.text
10 changes: 2 additions & 8 deletions tests/api_tests.py → tests/smoke_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,11 @@

import pytest
import requests
import json

import urllib.parse


def test_ping_endpoint(nhsd_apim_proxy_url):
resp = requests.get(nhsd_apim_proxy_url + "/_ping")
assert resp.status_code == 200
ping_data = json.loads(resp.text)
assert "version" in ping_data


@pytest.mark.smoketest
def test_status_endpoint(nhsd_apim_proxy_url, status_endpoint_auth_headers):
resp = requests.get(
nhsd_apim_proxy_url + "/_status", headers=status_endpoint_auth_headers
Expand All @@ -26,6 +19,7 @@ def test_status_endpoint(nhsd_apim_proxy_url, status_endpoint_auth_headers):
assert status_json["checks"]['healthcheck']["outcome"] == {"message": "OK"}


@pytest.mark.smoketest
@pytest.mark.nhsd_apim_authorization({"access": "application", "level": "level3"})
@pytest.mark.parametrize(
["ods_code", "expected"],
Expand Down

0 comments on commit 9c8cf75

Please sign in to comment.