Skip to content

Commit 3288163

Browse files
CCM-13399 supplier allocation on 12950 (#408)
* CCM-13399 Allocated letters queue * create allocate lambda * allocate lambda * Unit tests * axios vulnerability * lint fix * remove variant map after merge conflict * More unit test fixes * logging * rename allocate-letter to supplier-allocator * separate allocate and update queues * package lock again! * permissions * extra logging * queue permissions * more logging * type checking up front * logging * rationalise schemas * review changes * Review fixes * rebuild package lock * Fix to error if the VARIANT map does not contain the letter variant * revert package files to main
1 parent 4308b0e commit 3288163

23 files changed

Lines changed: 1364 additions & 310 deletions

infrastructure/terraform/components/api/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ No requirements.
6363
| <a name="module_post_mi"></a> [post\_mi](#module\_post\_mi) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip | n/a |
6464
| <a name="module_s3bucket_test_letters"></a> [s3bucket\_test\_letters](#module\_s3bucket\_test\_letters) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.26/terraform-s3bucket.zip | n/a |
6565
| <a name="module_sqs_letter_updates"></a> [sqs\_letter\_updates](#module\_sqs\_letter\_updates) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.26/terraform-sqs.zip | n/a |
66+
| <a name="module_sqs_supplier_allocator"></a> [sqs\_supplier\_allocator](#module\_sqs\_supplier\_allocator) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.26/terraform-sqs.zip | n/a |
67+
| <a name="module_supplier_allocator"></a> [supplier\_allocator](#module\_supplier\_allocator) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip | n/a |
6668
| <a name="module_supplier_ssl"></a> [supplier\_ssl](#module\_supplier\_ssl) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.26/terraform-ssl.zip | n/a |
6769
| <a name="module_upsert_letter"></a> [upsert\_letter](#module\_upsert\_letter) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip | n/a |
6870
## Outputs
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
resource "aws_lambda_event_source_mapping" "supplier_allocator" {
2+
event_source_arn = module.sqs_supplier_allocator.sqs_queue_arn
3+
function_name = module.supplier_allocator.function_name
4+
batch_size = 10
5+
maximum_batching_window_in_seconds = 5
6+
function_response_types = [
7+
"ReportBatchItemFailures"
8+
]
9+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
module "supplier_allocator" {
2+
source = "https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip"
3+
4+
function_name = "supplier-allocator"
5+
description = "Allocate a letter to a supplier"
6+
7+
aws_account_id = var.aws_account_id
8+
component = var.component
9+
environment = var.environment
10+
project = var.project
11+
region = var.region
12+
group = var.group
13+
14+
log_retention_in_days = var.log_retention_in_days
15+
kms_key_arn = module.kms.key_arn
16+
17+
iam_policy_document = {
18+
body = data.aws_iam_policy_document.supplier_allocator_lambda.json
19+
}
20+
21+
function_s3_bucket = local.acct.s3_buckets["lambda_function_artefacts"]["id"]
22+
function_code_base_path = local.aws_lambda_functions_dir_path
23+
function_code_dir = "supplier-allocator/dist"
24+
function_include_common = true
25+
handler_function_name = "supplierAllocatorHandler"
26+
runtime = "nodejs22.x"
27+
memory = 512
28+
timeout = 29
29+
log_level = var.log_level
30+
31+
force_lambda_code_deploy = var.force_lambda_code_deploy
32+
enable_lambda_insights = false
33+
34+
log_destination_arn = local.destination_arn
35+
log_subscription_role_arn = local.acct.log_subscription_role_arn
36+
37+
lambda_env_vars = merge(local.common_lambda_env_vars, {
38+
VARIANT_MAP = jsonencode(var.letter_variant_map)
39+
UPSERT_LETTERS_QUEUE_URL = module.sqs_letter_updates.sqs_queue_url
40+
})
41+
}
42+
43+
data "aws_iam_policy_document" "supplier_allocator_lambda" {
44+
statement {
45+
sid = "KMSPermissions"
46+
effect = "Allow"
47+
48+
actions = [
49+
"kms:Decrypt",
50+
"kms:GenerateDataKey",
51+
]
52+
53+
resources = [
54+
module.kms.key_arn,
55+
]
56+
}
57+
58+
statement {
59+
sid = "AllowSQSRead"
60+
effect = "Allow"
61+
62+
actions = [
63+
"sqs:ReceiveMessage",
64+
"sqs:DeleteMessage",
65+
"sqs:GetQueueAttributes"
66+
]
67+
68+
resources = [
69+
module.sqs_supplier_allocator.sqs_queue_arn
70+
]
71+
}
72+
73+
statement {
74+
sid = "AllowSQSWrite"
75+
effect = "Allow"
76+
77+
actions = [
78+
"sqs:SendMessage"
79+
]
80+
81+
resources = [
82+
module.sqs_letter_updates.sqs_queue_arn
83+
]
84+
}
85+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
module "sqs_supplier_allocator" {
2+
source = "https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.26/terraform-sqs.zip"
3+
4+
aws_account_id = var.aws_account_id
5+
component = var.component
6+
environment = var.environment
7+
project = var.project
8+
region = var.region
9+
name = "supplier-allocator"
10+
11+
sqs_kms_key_arn = module.kms.key_arn
12+
13+
visibility_timeout_seconds = 60
14+
15+
create_dlq = true
16+
sqs_policy_overload = data.aws_iam_policy_document.supplier_allocator_queue_policy.json
17+
}
18+
19+
data "aws_iam_policy_document" "supplier_allocator_queue_policy" {
20+
version = "2012-10-17"
21+
22+
statement {
23+
sid = "AllowSNSPermissions"
24+
effect = "Allow"
25+
26+
principals {
27+
type = "Service"
28+
identifiers = ["sns.amazonaws.com"]
29+
}
30+
31+
actions = [
32+
"sqs:SendMessage",
33+
"sqs:ListQueueTags",
34+
"sqs:GetQueueUrl",
35+
"sqs:GetQueueAttributes",
36+
]
37+
38+
resources = [
39+
"arn:aws:sqs:${var.region}:${var.aws_account_id}:${var.project}-${var.environment}-${var.component}-supplier-allocator-queue"
40+
]
41+
42+
condition {
43+
test = "ArnEquals"
44+
variable = "aws:SourceArn"
45+
values = [module.eventsub.sns_topic.arn]
46+
}
47+
}
48+
}
Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
resource "aws_sns_topic_subscription" "eventsub_sqs_letter_updates" {
2-
topic_arn = module.eventsub.sns_topic.arn
3-
protocol = "sqs"
4-
endpoint = module.sqs_letter_updates.sqs_queue_arn
2+
topic_arn = module.eventsub.sns_topic.arn
3+
protocol = "sqs"
4+
endpoint = module.sqs_letter_updates.sqs_queue_arn
5+
raw_message_delivery = true
6+
7+
filter_policy_scope = "MessageBody"
8+
filter_policy = jsonencode({
9+
type = [{ prefix = "uk.nhs.notify.supplier-api.letter" }]
10+
})
511
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
resource "aws_sns_topic_subscription" "eventsub_sqs_supplier_allocator" {
2+
topic_arn = module.eventsub.sns_topic.arn
3+
protocol = "sqs"
4+
endpoint = module.sqs_supplier_allocator.sqs_queue_arn
5+
raw_message_delivery = true
6+
7+
filter_policy_scope = "MessageBody"
8+
filter_policy = jsonencode({
9+
type = [{ prefix = "uk.nhs.notify.letter-rendering.letter-request.prepared" }]
10+
})
11+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dist
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
coverage
2+
node_modules
3+
dist
4+
.reports
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
export const baseJestConfig = {
2+
preset: "ts-jest",
3+
extensionsToTreatAsEsm: [".ts"],
4+
transform: {
5+
"^.+\\.ts$": [
6+
"ts-jest",
7+
{
8+
useESM: true,
9+
},
10+
],
11+
},
12+
13+
// Automatically clear mock calls, instances, contexts and results before every test
14+
clearMocks: true,
15+
16+
// Indicates whether the coverage information should be collected while executing the test
17+
collectCoverage: true,
18+
19+
// The directory where Jest should output its coverage files
20+
coverageDirectory: "./.reports/unit/coverage",
21+
22+
// Indicates which provider should be used to instrument code for coverage
23+
coverageProvider: "babel",
24+
25+
coverageThreshold: {
26+
global: {
27+
branches: 100,
28+
functions: 100,
29+
lines: 100,
30+
statements: -10,
31+
},
32+
},
33+
34+
coveragePathIgnorePatterns: ["/__tests__/"],
35+
testPathIgnorePatterns: [".build"],
36+
testMatch: ["**/?(*.)+(spec|test).[jt]s?(x)"],
37+
38+
// Use this configuration option to add custom reporters to Jest
39+
reporters: [
40+
"default",
41+
[
42+
"jest-html-reporter",
43+
{
44+
pageTitle: "Test Report",
45+
outputPath: "./.reports/unit/test-report.html",
46+
includeFailureMsg: true,
47+
},
48+
],
49+
],
50+
51+
// The test environment that will be used for testing
52+
testEnvironment: "jsdom",
53+
};
54+
55+
const utilsJestConfig = {
56+
...baseJestConfig,
57+
58+
testEnvironment: "node",
59+
60+
coveragePathIgnorePatterns: [
61+
...(baseJestConfig.coveragePathIgnorePatterns ?? []),
62+
"zod-validators.ts",
63+
],
64+
};
65+
66+
export default utilsJestConfig;
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"dependencies": {
3+
"@aws-sdk/client-dynamodb": "^3.858.0",
4+
"@aws-sdk/client-sqs": "^3.984.0",
5+
"@aws-sdk/lib-dynamodb": "^3.858.0",
6+
"@internal/datastore": "*",
7+
"@internal/helpers": "^0.1.0",
8+
"@nhsdigital/nhs-notify-event-schemas-letter-rendering": "^2.0.1",
9+
"@nhsdigital/nhs-notify-event-schemas-letter-rendering-v1": "npm:@nhsdigital/nhs-notify-event-schemas-letter-rendering@^1.1.5",
10+
"@nhsdigital/nhs-notify-event-schemas-supplier-api": "^1.0.8",
11+
"@types/aws-lambda": "^8.10.148",
12+
"aws-lambda": "^1.0.7",
13+
"esbuild": "^0.27.2",
14+
"pino": "^9.7.0",
15+
"zod": "^4.1.11"
16+
},
17+
"devDependencies": {
18+
"@tsconfig/node22": "^22.0.2",
19+
"@types/aws-lambda": "^8.10.148",
20+
"@types/jest": "^30.0.0",
21+
"jest": "^30.2.0",
22+
"jest-mock-extended": "^4.0.0",
23+
"ts-jest": "^29.4.0",
24+
"typescript": "^5.8.3"
25+
},
26+
"name": "nhs-notify-supplier-api-allocate-letter",
27+
"private": true,
28+
"scripts": {
29+
"lambda-build": "rm -rf dist && npx esbuild --bundle --minify --sourcemap --target=es2020 --platform=node --loader:.node=file --entry-names=[name] --outdir=dist src/index.ts",
30+
"lint": "eslint .",
31+
"lint:fix": "eslint . --fix",
32+
"test:unit": "jest",
33+
"typecheck": "tsc --noEmit"
34+
},
35+
"version": "0.0.1"
36+
}

0 commit comments

Comments
 (0)