Skip to content

Commit 77549a2

Browse files
authored
VED-188 Backend & E2E test & Devtools documentation updated (#383)
Documentation improvements to readme files and updated devtools code.
1 parent 1525013 commit 77549a2

File tree

7 files changed

+317
-168
lines changed

7 files changed

+317
-168
lines changed

README.md

Lines changed: 172 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,6 @@
22

33
See `README.specification.md` for details of the API specification's development.
44

5-
## Directories
6-
7-
```
8-
backend - The API code.
9-
terraform - Infrastructure.
10-
tests - Integration tests.
11-
devtools - Helper project for development.
12-
```
13-
14-
See any readmes in those directories for more details.
15-
165
## Spelling
176

187
Refer to the FHIR Immunization resource capitalised and with a "z" as FHIR is U.S. English.
@@ -21,46 +10,181 @@ All other uses are as British English i.e. "immunisation".
2110

2211
See https://nhsd-confluence.digital.nhs.uk/display/APM/Glossary.
2312

24-
## Setup for local dev
25-
26-
`backend` should have its own environment to keep it separate from the infrastructure and integration tests.
27-
28-
### Tools
29-
30-
Install `direnv` and `pyenv`.
31-
https://direnv.net/docs/installation.html
32-
https://github.com/pyenv/pyenv?tab=readme-ov-file#installation
33-
34-
These tools automate the Python version and environment creation and use, and selects them automatically when entering a
35-
directory.
36-
`pyenv` separates Python versions and `direnv` handles the environment.
37-
`direnv` uses `pyenv` to select the version and creates an environment under `.direnv/`.
38-
39-
At this point you'll get a warning when you enter this directory, telling you to run `direnv allow`. This is fine and
40-
the next step will resolve it.
41-
42-
### Install Python versions and environments
43-
44-
This will set up for both the root and `backend`.
13+
## Directories
14+
**Note:** Each Lambda has its own `README.md` file for detailed documentation. For non-Lambda-specific folders, refer to `README.specification.md`.
15+
16+
### Lambdas
17+
18+
| Folder | Description |
19+
|---------------------|-------------|
20+
| `backend` | **Imms API** – Handles CRUD operations for the Immunisation API. |
21+
| `delta_backend` | **Imms Sync** – Lambda function that reacts to events in the Immunisation database. |
22+
| `ack_backend` | **Imms Batch** – Generates the final Business Acknowledgment (BUSACK) file from processed messages and writes it to the designated S3 location. |
23+
| `filenameprocessor` | **Imms Batch** – Processes batch file names. |
24+
| `mesh_processor` | **Imms Batch** – MESH-specific batch processing functionality. |
25+
| `recordprocessor` | **Imms Batch** – Handles batch record processing. |
26+
---
27+
28+
### Pipelines
29+
30+
| Folder | Description |
31+
|---------|-------------|
32+
| `azure` | Pipeline definition and orchestration code. |
33+
34+
---
35+
36+
### Infrastructure
37+
38+
| Folder | Description |
39+
|------------------------|-------------|
40+
| `infra` | Base infrastructure components. |
41+
| `grafana` | Terraform configuration for Grafana, built on top of core infra. |
42+
| `terraform` | Core Terraform infrastructure code. This is run in each PR and sets up lambdas associated with the PR.|
43+
| `terraform_sandbox` | Sandbox environment for testing infrastructure changes. |
44+
| `terraform_aws_backup` | Streamlined backup processing with AWS. |
45+
| `mesh-infra` | Infrastructure setup for Imms batch MESH integration. |
46+
| `proxies` | Apigee API proxy definitions. |
47+
---
48+
49+
### Tests
50+
51+
| Folder | Description |
52+
|---------------|-------------|
53+
| `e2e` | End-to-end tests executed during PR pipelines. |
54+
| `e2e_batch` | E2E tests specifically for batch-related functionality, also run in the PR pipeline. |
55+
| `tests` | Sample e2e test. |
56+
---
57+
58+
### Utilities
59+
60+
| Folder | Description |
61+
|----------------|-------------|
62+
| `devtools` | Helper tools and utilities for local development |
63+
| `scripts` | Standalone or reusable scripts for development and automation |
64+
| `specification` | Specification files to document API and related definitions |
65+
| `sandbox` | Simple sandbox API |
66+
67+
---
68+
69+
## Background: Python Package Management and Virtual Environments
70+
- `pyenv` manages multiple Python versions at the system level, allowing you to install and switch between different Python versions for different projects.
71+
- `direnv` automates the loading of environment variables and can auto-activate virtual environments (.venv) when entering a project directory, making workflows smoother.
72+
- `.venv` (created via python -m venv or poetry) is Python’s built-in tool for isolating dependencies per project, ensuring that packages don’t interfere with global Python packages.
73+
- `Poetry` is an all-in-one dependency and virtual environment manager that automatically creates a virtual environment (.venv), manages package installations, and locks dependencies (poetry.lock) for reproducibility, making it superior to using pip manually and it is used in all the lambda projects.
74+
75+
## Project structure
76+
To support a modular and maintainable architecture, each Lambda function in this project is structured as a self-contained folder with its own dependencies, configuration, and environment.
77+
78+
We use Poetry to manage dependencies and virtual environments, with the virtualenvs.in-project setting enabled to ensure each Lambda has an isolated `.venv` created within its folder.
79+
80+
Additionally, direnv is used alongside `.envrc` and `.env` files to automatically activate the appropriate virtual environment and load environment-specific variables when entering a folder.
81+
82+
Each Lambda folder includes its own `.env` file for Lambda-specific settings, while the project root contains a separate `.env` and `.venv` for managing shared tooling, scripts, or infrastructure-related configurations. This setup promotes clear separation of concerns, reproducibility across environments, and simplifies local development, testing, and packaging for deployment.
83+
84+
## Environment setup
85+
These dependencies are required for running and debugging the Lambda functions and end-to-end (E2E) tests.
86+
87+
### Install dependencies
88+
Steps:
89+
1. Install [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) if running on Windows and install [Docker](https://docs.docker.com/engine/install/).
90+
2. Install the following tools inside WSL. These will be used by the lambda and infrastructure code:
91+
- [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)
92+
- [Terraform](https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli)
93+
94+
3. Open VS Code and click the bottom-left corner (blue section), then select **"Connect to WSL"** and choose your WSL distro (e.g., `Ubuntu-24.04`).
95+
Once connected, you should see the path as something similar to: `/mnt/d/Source/immunisation-fhir-api/backend`.
96+
4. Run the following commands to install dependencies
97+
```
98+
sudo apt update && sudo apt upgrade -y
99+
sudo apt install -y make build-essential libssl-dev zlib1g-dev \
100+
libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \
101+
libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev \
102+
liblzma-dev git libgdbm-dev libgdbm-compat-dev
103+
pip install --upgrade pip
104+
```
105+
106+
5. Configure pyenv.
107+
```
108+
pyenv install --list | grep "3.10"
109+
pyenv install 3.10.16 #current latest
110+
```
111+
112+
6. Install poetry
113+
```
114+
pip install poetry
115+
```
116+
117+
### Setting up a virtual environment with poetry
118+
The steps below must be performed in each Lambda function folder and e2e folder to ensure the environment is correctly configured.
119+
120+
For detailed instructions on running individual Lambdas, refer to the README.md files located inside each respective Lambda folder.
121+
122+
Steps:
123+
1. Set the python version in the folder with the code used by lambda for example `./backend` (see [lambdas](#lambdas)) folder.
124+
```
125+
pyenv local 3.10.16 # Set version in backend (this creates a .python-version file)
126+
```
127+
128+
2. Configure poetry
129+
```
130+
### Point poetry virtual environment to .venv
131+
poetry config virtualenvs.in-project true
132+
poetry env use $(pyenv which python)
133+
poetry env info
134+
```
135+
136+
3. Create an .env file and add environment variables.
137+
```
138+
AWS_PROFILE={your_profile}
139+
IMMUNIZATION_ENV=local
140+
```
141+
142+
4. Configure `direnv` by creating a `.envrc` file in the backend folder. This points direnv to the `.venv` created by poetry and loads env variables specified in the `.env` file
143+
```
144+
export VIRTUAL_ENV=".venv"
145+
PATH_add "$VIRTUAL_ENV/bin"
146+
147+
dotenv
148+
```
149+
150+
5. Restart bash and run `direnv allow`. You should see something similar like:
151+
```
152+
direnv: loading /mnt/d/Source/immunisation-fhir-api/.envrc
153+
direnv: export +AWS_PROFILE +IMMUNIZATION_ENV +VIRTUAL_ENV ~PATH
154+
```
155+
Test if environment variables have been loaded into shell: `echo $IMMUNIZATION_ENV`.
156+
157+
### Setting up the root level environment
158+
The root-level virtual environment is primarily used for linting, as we create separate virtual environments for each folder that contains Lambda functions.
159+
Steps:
160+
1. Follow instructions above to [install dependencies](#install-dependencies) & [set up a virtual environment](#setting-up-a-virtual-environment-with-poetry).
161+
**Note: While this project uses Python 3.10 (e.g. for Lambdas), the NHSDigital/api-management-utils repository — which orchestrates setup and linting — defaults to Python 3.8.
162+
The linting command is executed from within that repo but calls the Makefile in this project, so be aware of potential Python version mismatches when running or debugging locally or in the pipeline.**
163+
2. Run `make lint`. This will:
164+
- Check the linting of the API specification yaml.
165+
- Run Flake8 on all Python files in the repository, excluding files inside .venv and .terraform directories.
166+
167+
## IDE setup
168+
The current team uses VS Code mainly. So this setup is targeted towards VS code. If you use another IDE please add the documentation to set up workspaces here.
169+
170+
### VS Code
45171
46-
Copy `.env.default` to `.env` or merge it with your existing file.
47-
Copy `.envrc.default` to `.envrc` or merge it with your existing file.
172+
The project must be opened as a multi-root workspace for VS Code to know that `backend` has its own environment.
48173
49-
These are kept separate so other tools can use `.env` if wanted.
174+
- Open the workspace `immunisation-fhir-api.code-workspace`.
175+
- Copy `backend/.vscode/settings.json.default` to `backend/.vscode/settings.json`, or merge the contents with
176+
your existing file.
50177
51-
Edit `.env` with your details.
178+
VS Code will automatically use the `backend` environment when you're editing a file under `backend`.
52179
53-
```shell
54-
make setup-python-envs
55-
poetry install --no-root
56-
```
180+
Depending on your existing setup VS Code might automatically choose the wrong virtualenvs. Change it
181+
with `Python: Select Interpreter`.
57182
58-
### IDEs
183+
The root (`immunisation-fhir-api`) should point to `/mnt/d/Source/immunisation-fhir-api/.venv/bin/python`.
59184
60-
The `backend` tests are in a separate module so in order for them to see each other we need to let the IDE know
61-
about the relationship.
185+
`backend` should be pointing at `/mnt/d/Source/immunisation-fhir-api/backend/.venv/bin/python`
62186
63-
#### IntelliJ
187+
### IntelliJ
64188
65189
- Open the root repo directory in IntelliJ.
66190
- In Project Structure add an existing virtualenv SDK for `.direnv/python-x.x.x/bin/python`.
@@ -72,20 +196,8 @@ about the relationship.
72196
- Add the `src` and `tests` directories as sources.
73197
- Add `.direnv` as an exclusion if it's not already.
74198
75-
#### VS Code
76-
77-
The project must be opened as a multi-root workspace for VS Code to know that `backend` has its own environment.
78-
79-
- Open the workspace `immunisation-fhir-api.code-workspace`.
80-
- Copy `backend/.vscode/settings.json.default` to `backend/.vscode/settings.json`, or merge the contents with
81-
your existing file.
82-
83-
VS Code will automatically use the `backend` environment when you're editing a file under `backend`.
84-
85-
Depending on your existing setup VS Code might automatically choose the wrong virtualenvs. Change it
86-
with `Python: Select Interpreter`.
87-
88-
The root (immunisation-fhir-api) should be pointing at `.direnv/python-x.x.x/bin/python.`
89-
90-
`backend` should be pointing at `backend/.direnv/python-x.x.x/bin/python.`
91199
200+
## Verified commits
201+
Please note that this project requires that all commits are verified using a GPG key.
202+
To set up a GPG key please follow the instructions specified here:
203+
https://docs.github.com/en/authentication/managing-commit-signature-verification

backend/README.md

Lines changed: 19 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,25 @@
1-
# immunisation-fhir-api lambda
21

3-
Paths are relative to this directory, `backend`.
2+
# About
3+
This document describes the environment setup for the backend API Lambda.
4+
This Lambda handles incoming CRUD operation requests from APIGEE and interacts with the immunisation events database to store immunisation records. All commands listed below are run in the `./backend` folder.
45

5-
## Install dependencies
6+
## Setting up the backend lambda
7+
Note: Paths are relative to this directory, `backend`.
68

7-
```shell
8-
pip install poetry
9-
poetry install
10-
pip install terraform-local
11-
```
9+
1. Follow the instructions in the root level README.md to setup the [dependencies](../README.md#environment-setup) and create a [virtual environment](../README.md#) for this folder.
1210

11+
2. Replace the `.env` file in the backend folder. Note the variables might change in the future. These environment variables will be loaded automatically when using `direnv`.
12+
```
13+
AWS_PROFILE={your-profile}
14+
DYNAMODB_TABLE_NAME=imms-{environment}-imms-events
15+
IMMUNIZATION_ENV={environment}
16+
SPLUNK_FIREHOSE_NAME=immunisation-fhir-api-{environment}-splunk-firehose
17+
```
1318
14-
## Run locally
19+
3. Run `poetry install --no-root` to install dependencies.
1520
16-
### Start LocalStack
17-
18-
```shell
19-
cd ../devtools
20-
docker compose -f localstack-compose.yml up
21-
```
22-
23-
LocalStack uses port 4566 so make sure it's free.
24-
25-
26-
### Create table
27-
28-
```shell
29-
cd ../terraform
30-
tflocal init
31-
tflocal apply -target=aws_dynamodb_table.events-dynamodb-table
32-
```
33-
34-
### Run endpoint
35-
36-
Copy `.env.default` to `.env` or merge it with your existing file.
37-
Copy `.envrc.default` to `.envrc` or merge it with your existing file. `direnv` will use them automatically in the terminal.
38-
39-
These are kept separate so other tools can use `.env` if wanted.
40-
41-
See `.env` for an explanation of the variables.
42-
43-
To run from the terminal:
44-
```shell
45-
cd src
46-
python get_imms_handler.py 123
47-
```
48-
49-
If not using `.envrc` then:
50-
```shell
51-
cd src
52-
AWS_PROFILE=apim-dev DYNAMODB_TABLE_NAME=imms-default-imms-events IMMUNIZATION_ENV=local python get_imms_handler.py 123
53-
```
54-
55-
You should get a 404 as the resource doesn't exist.
56-
57-
58-
### Running tests
59-
60-
- `make test`
61-
- If you want to run specific test, you can try testing one single class or single function with
62-
`python -m unittest tests.test_fhir_controller.TestSearchImmunizations `
63-
`python -m unittest tests.test_fhir_controller.TestSearchImmunizations.test_search_immunizations`
21+
4. Run `make test` to run unit tests or individual tests by running:
22+
```
23+
python -m unittest tests.test_fhir_controller.TestSearchImmunizations
24+
python -m unittest tests.test_fhir_controller.TestSearchImmunizations.test_search_immunizations
25+
```

devtools/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ seed: delete-table apply gen_data
1515
python seed.py sample_data/$(shell ls -t sample_data | head -n1)
1616

1717
localstack:
18-
docker run --rm -it -p 4566:4566 -p 4510-4559:4510-4559 localstack/localstack:latest
18+
docker run -d --rm -it -p 4566:4566 -p 4510-4559:4510-4559 localstack/localstack:latest
1919

2020
.PHONY: test test-debug localstack apply init

0 commit comments

Comments
 (0)