Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 29 additions & 30 deletions infrastructure/instance/.terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions infrastructure/instance/mns_publisher.tf
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module "mns_publisher" {
imms_base_path = strcontains(var.sub_environment, "pr-") ? "immunisation-fhir-api/FHIR/R4-${var.sub_environment}" : "immunisation-fhir-api/FHIR/R4"
lambda_kms_encryption_key_arn = data.aws_kms_key.existing_lambda_encryption_key.arn
mns_publisher_resource_name_prefix = "${local.resource_scope}-mns-outbound-events"
mns_test_notifcation_name_prefix = "${local.resource_scope}-mns-test-notification"
secrets_manager_policy_path = "${local.policy_path}/secret_manager.json"
account_id = data.aws_caller_identity.current.account_id
pds_environment = var.pds_environment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ resource "aws_lambda_function" "mns_publisher_lambda" {
environment {
variables = {
SPLUNK_FIREHOSE_NAME = var.splunk_firehose_stream_name
MNS_TEST_QUEUE_URL = aws_sqs_queue.mns_test_notification.url
IMMUNIZATION_ENV = var.resource_scope,
IMMUNIZATION_BASE_PATH = var.imms_base_path
PDS_ENV = var.pds_environment
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Main queue for MNS notification testing
resource "aws_sqs_queue" "mns_test_notification" {
Comment thread
dlzhry2nhs marked this conversation as resolved.
name = "${var.mns_test_notifcation_name_prefix}-queue"
Comment thread
dlzhry2nhs marked this conversation as resolved.
Outdated
fifo_queue = false
kms_master_key_id = aws_kms_key.mns_outbound_events.arn
visibility_timeout_seconds = 300
}


data "aws_iam_policy_document" "mns_test_notification_sqs_policy" {
statement {
sid = "mns-test-notification-allow-lambda-access"
effect = "Allow"

principals {
type = "AWS"
identifiers = [aws_iam_role.mns_publisher_lambda_exec_role.arn]
Comment thread
dlzhry2nhs marked this conversation as resolved.
}

actions = [
"sqs:SendMessage",
]

resources = [
aws_sqs_queue.mns_test_notification.arn
]
}
}

resource "aws_sqs_queue_policy" "mns_test_notification_sqs" {
queue_url = aws_sqs_queue.mns_test_notification.id
policy = data.aws_iam_policy_document.mns_test_notification_sqs_policy.json
}
5 changes: 5 additions & 0 deletions infrastructure/instance/modules/mns_publisher/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,9 @@ variable "account_id" {
variable "secrets_manager_policy_path" {
type = string
description = "Path to the IAM policy JSON template for Secrets Manager access (e.g., ./policies/secret_manager.json)."
}

variable "mns_test_notifcation_name_prefix" {
type = string
description = "The prefix for the name of resources for testing mns notification"
}
29 changes: 29 additions & 0 deletions lambdas/mns_publisher/src/mns_test_queue.py
Comment thread
edhall-nhs marked this conversation as resolved.
Outdated
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import json
import os

import boto3

from common.clients import logger

MNS_TEST_QUEUE_URL = os.getenv("MNS_TEST_QUEUE_URL")
sqs_client = boto3.client("sqs", region_name="eu-west-2")


def send_notification_to_test_queue(mns_payload: dict) -> None:
"""
Send MNS notification payload to test SQS queue as fallback.
Args: payload: MNS notification payload
"""
if not MNS_TEST_QUEUE_URL:
logger.error("MNS_TEST_QUEUE_URL environment variable is not set")
return

try:
response = sqs_client.send_message(
QueueUrl=MNS_TEST_QUEUE_URL,
MessageBody=json.dumps(mns_payload),
MessageAttributes={"source": {"StringValue": "mns-publisher-lambda", "DataType": "String"}},
)
logger.info("Successfully sent notification to test queue", extra={"message_id": response["MessageId"]})
except Exception:
logger.exception("Failed to send to test SQS queue")
11 changes: 7 additions & 4 deletions lambdas/mns_publisher/src/process_records.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from common.api_clients.mns_setup import get_mns_service
from common.clients import logger
from create_notification import create_mns_notification
from mns_test_queue import send_notification_to_test_queue

mns_env = os.getenv("MNS_ENV", "int")

Expand Down Expand Up @@ -62,10 +63,12 @@ def process_record(record: SQSMessage, mns_service: MnsService) -> None:
},
)

mns_service.publish_notification(mns_notification_payload)
logger.info("Successfully created MNS notification", extra={"mns_notification_id": notification_id})

return None
try:
mns_service.publish_notification(mns_notification_payload)
logger.info("Successfully created MNS notification", extra={"mns_notification_id": notification_id})
except Exception:
Comment thread
Akol125 marked this conversation as resolved.
Outdated
send_notification_to_test_queue(mns_notification_payload)
Comment thread
edhall-nhs marked this conversation as resolved.
Outdated
Comment thread
dlzhry2nhs marked this conversation as resolved.
Outdated
raise


def extract_trace_ids(record: SQSMessage) -> Tuple[str, str | None]:
Expand Down
59 changes: 59 additions & 0 deletions lambdas/mns_publisher/tests/test_mns_test_queue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import json
import unittest
from unittest.mock import patch

import boto3
from moto import mock_aws

from mns_test_queue import send_notification_to_test_queue


@mock_aws
class TestMnsSqsQueue(unittest.TestCase):
Comment thread
Akol125 marked this conversation as resolved.
Outdated
def setUp(self):
self.sqs = boto3.client("sqs", region_name="eu-west-2")
response = self.sqs.create_queue(QueueName="mns-test-notifications-int")
self.queue_url = response["QueueUrl"]

self.mns_payload = {
"specversion": "1.0",
"id": "236a1d4a-5d69-4fa9-9c7f-e72bf505aa5b",
"source": "https://int.api.service.nhs.uk/immunisation-fhir-api",
"type": "imms-vaccinations-2",
"time": "20260212T174437+00:00",
"subject": "9481152782",
"dataref": "https://int.api.service.nhs.uk/immunisation-fhir-api/Immunization/d058014c-b0fd-4471-8db9-3316175eb825",
"filtering": {
"generalpractitioner": "Y12345",
"sourceorganisation": "B0C4P",
"sourceapplication": "TPP",
"subjectage": 21,
"immunisationtype": "HIB",
"action": "CREATE",
},
}

def test_send_notification_to_queue_success(self):
"""Test successful send to SQS queue with complete payload."""
with patch("mns_test_queue.MNS_TEST_QUEUE_URL", self.queue_url):
send_notification_to_test_queue(self.mns_payload)

messages = self.sqs.receive_message(
QueueUrl=self.queue_url, MaxNumberOfMessages=1, MessageAttributeNames=["All"]
)

self.assertIn("Messages", messages)
self.assertEqual(len(messages["Messages"]), 1)

# Verify message body
mns_payload = json.loads(messages["Messages"][0]["Body"])
attributes = messages["Messages"][0]["MessageAttributes"]
self.assertEqual(attributes["source"]["StringValue"], "mns-publisher-lambda")

self.assertEqual(mns_payload["subject"], "9481152782")
self.assertEqual(mns_payload["filtering"]["generalpractitioner"], "Y12345")
self.assertEqual(mns_payload["filtering"]["sourceorganisation"], "B0C4P")
self.assertEqual(mns_payload["filtering"]["sourceapplication"], "TPP")
self.assertEqual(mns_payload["filtering"]["immunisationtype"], "HIB")
self.assertEqual(mns_payload["filtering"]["action"], "CREATE")
self.assertEqual(mns_payload["filtering"]["subjectage"], 21)
Loading