Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions .env.template
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Your github Personal Access Token (PAT)
PR_NUMBER=prxx # remove if needs to run against main
GITHUB_TOKEN=

# Apigee proxy name to be used for test execution
Expand Down
43 changes: 43 additions & 0 deletions .github/actions/acceptance-tests-component/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Acceptance tests - component
description: "Run component acceptance tests for this repo"

inputs:
testType:
description: Type of test to run
required: true

targetEnvironment:
description: Name of the environment under test
required: true

targetComponent:
description: Name of the component under test
required: true

runs:
using: "composite"

steps:

- name: Repo setup
uses: ./.github/actions/node-install
with:
GITHUB_TOKEN: ${{ env.GITHUB_TOKEN }}

- name: Fetch terraform output
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5
with:
name: terraform-output-${{ inputs.targetComponent }}

- name: Get Node version
id: nodejs_version
shell: bash
run: |
echo "nodejs_version=$(grep "^nodejs\s" .tool-versions | cut -f2 -d' ')" >> $GITHUB_OUTPUT

- name: Run test - ${{ inputs.testType }}
shell: bash
env:
TARGET_ENVIRONMENT: ${{ inputs.targetEnvironment }}
run: |
make test-${{ inputs.testType }}
1 change: 0 additions & 1 deletion .github/workflows/stage-3-build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,6 @@ jobs:
--terraformAction "apply" \
--overrideProjectName "nhs" \
--overrideRoleName "nhs-main-acct-supplier-api-github-deploy"

populate-config:
name: "Populate Supplier Config"
runs-on: ubuntu-latest
Expand Down
3 changes: 3 additions & 0 deletions infrastructure/terraform/components/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ No requirements.
| <a name="input_enable_event_anomaly_detection"></a> [enable\_event\_anomaly\_detection](#input\_enable\_event\_anomaly\_detection) | Enable CloudWatch anomaly detection alarm for SNS message Detects abnormal drops or spikes in event publishing volume. | `bool` | `true` | no |
| <a name="input_enable_event_cache"></a> [enable\_event\_cache](#input\_enable\_event\_cache) | Enable caching of events to an S3 bucket | `bool` | `true` | no |
| <a name="input_enable_sns_delivery_logging"></a> [enable\_sns\_delivery\_logging](#input\_enable\_sns\_delivery\_logging) | Enable SNS Delivery Failure Notifications | `bool` | `true` | no |
| <a name="input_enable_supplier_mock_scheduler"></a> [enable\_supplier\_mock\_scheduler](#input\_enable\_supplier\_mock\_scheduler) | Enable EventBridge Scheduler trigger for supplier mock lambda | `bool` | `false` | no |
| <a name="input_environment"></a> [environment](#input\_environment) | The name of the tfscaffold environment | `string` | n/a | yes |
| <a name="input_event_anomaly_band_width"></a> [event\_anomaly\_band\_width](#input\_event\_anomaly\_band\_width) | The width of the anomaly detection band. Higher values (e.g. 4-6) reduce sensitivity and noise, lower values (e.g. 2-3) increase sensitivity. Recommended: 2-4. | `number` | `4` | no |
| <a name="input_event_anomaly_evaluation_periods"></a> [event\_anomaly\_evaluation\_periods](#input\_event\_anomaly\_evaluation\_periods) | Number of evaluation periods for the anomaly alarm. Each period is defined by event\_anomaly\_period. | `number` | `3` | no |
Expand All @@ -51,6 +52,7 @@ No requirements.
| <a name="input_region"></a> [region](#input\_region) | The AWS Region | `string` | n/a | yes |
| <a name="input_shared_infra_account_id"></a> [shared\_infra\_account\_id](#input\_shared\_infra\_account\_id) | The AWS Account ID of the shared infrastructure account | `string` | `"000000000000"` | no |
| <a name="input_sns_success_logging_sample_percent"></a> [sns\_success\_logging\_sample\_percent](#input\_sns\_success\_logging\_sample\_percent) | Enable SNS Delivery Successful Sample Percentage | `number` | `0` | no |
| <a name="input_supplier_mock_schedule_expression"></a> [supplier\_mock\_schedule\_expression](#input\_supplier\_mock\_schedule\_expression) | Schedule expression for supplier mock scheduler | `string` | `"rate(1 minute)"` | no |
## Modules

| Name | Source | Version |
Expand Down Expand Up @@ -83,6 +85,7 @@ No requirements.
| <a name="module_sqs_letter_updates"></a> [sqs\_letter\_updates](#module\_sqs\_letter\_updates) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/3.1.5/terraform-sqs.zip | n/a |
| <a name="module_sqs_supplier_allocator"></a> [sqs\_supplier\_allocator](#module\_sqs\_supplier\_allocator) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/3.1.5/terraform-sqs.zip | n/a |
| <a name="module_supplier_allocator"></a> [supplier\_allocator](#module\_supplier\_allocator) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/4.0.2/terraform-lambda.zip | n/a |
| <a name="module_supplier_mock"></a> [supplier\_mock](#module\_supplier\_mock) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip | n/a |
| <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 |
| <a name="module_update_letter_queue"></a> [update\_letter\_queue](#module\_update\_letter\_queue) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/4.0.2/terraform-lambda.zip | n/a |
| <a name="module_upsert_letter"></a> [upsert\_letter](#module\_upsert\_letter) | https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/4.0.2/terraform-lambda.zip | n/a |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
module "supplier_mock" {
source = "https://github.com/NHSDigital/nhs-notify-shared-modules/releases/download/v2.0.29/terraform-lambda.zip"

function_name = "supplier_mock"
description = "Mock the behaviour of a supplier"

aws_account_id = var.aws_account_id
component = var.component
environment = var.environment
project = var.project
region = var.region
group = var.group

log_retention_in_days = var.log_retention_in_days
kms_key_arn = module.kms.key_arn

iam_policy_document = {
body = data.aws_iam_policy_document.supplier_mock_lambda.json
}

function_s3_bucket = local.acct.s3_buckets["lambda_function_artefacts"]["id"]
function_code_base_path = local.aws_lambda_functions_dir_path
function_code_dir = "supplier-mock/dist"
function_include_common = true
handler_function_name = "supplierMockHandler"
runtime = "nodejs22.x"
memory = 512
timeout = 29
log_level = var.log_level

force_lambda_code_deploy = var.force_lambda_code_deploy
enable_lambda_insights = false

log_destination_arn = local.destination_arn
log_subscription_role_arn = local.acct.log_subscription_role_arn

lambda_env_vars = merge(local.common_lambda_env_vars, {
ENVIRONMENT = var.environment
GET_LETTERS_FUNCTION_NAME = module.get_letters.function_name
PATCH_LETTER_FUNCTION_NAME = module.patch_letter.function_name
SUPPLIER_MOCK_GET_LETTERS_LIMIT_PARAM_NAME = aws_ssm_parameter.supplier_mock_get_letters_limit.name
SUPPLIER_MOCK_SUPPLIER_ID = aws_ssm_parameter.supplier_mock_supplier_id.name
})
}

resource "aws_ssm_parameter" "supplier_mock_get_letters_limit" {
name = format("/nhs/supapi/supplier-mock/%s/get-letters-limit", var.environment)
description = "Default get_letters limit for supplier mock lambda"
type = "String"
value = "100"

lifecycle {
ignore_changes = [value]
}
}

resource "aws_ssm_parameter" "supplier_mock_supplier_id" {
name = format("/nhs/supapi/supplier-mock/%s/supplier-id", var.environment)
description = "Supplier ID to be used by the supplier mock lambda"
type = "String"
value = "TestSupplier1"

lifecycle {
ignore_changes = [value]
}
}

data "aws_iam_policy_document" "supplier_mock_lambda" {
statement {
sid = "KMSPermissions"
effect = "Allow"

actions = [
"kms:Decrypt",
"kms:GenerateDataKey",
]

resources = [
module.kms.key_arn, ## Requires shared kms module
]
}

statement {
sid = "AllowInvokeLambda"
effect = "Allow"

actions = [
"lambda:InvokeFunction",
]

resources = [
module.get_letters.function_arn,
module.patch_letter.function_arn
]
}

statement {
sid = "AllowReadSupplierMockLimitParameter"
effect = "Allow"

actions = [
"ssm:GetParameter",
]

resources = [
aws_ssm_parameter.supplier_mock_get_letters_limit.arn,
aws_ssm_parameter.supplier_mock_supplier_id.arn
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
data "aws_iam_policy_document" "supplier_mock_scheduler_trust_policy" {
statement {
sid = "AllowSchedulerAssumeRole"
effect = "Allow"

actions = [
"sts:AssumeRole",
]

principals {
type = "Service"

identifiers = [
"scheduler.amazonaws.com",
]
}
}
}

resource "aws_iam_role" "supplier_mock_scheduler" {
name = "${local.csi}-supplier-mock-scheduler"
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the scheduler get created for all branches or just main?

description = "Allows EventBridge Scheduler to invoke supplier mock lambda"
assume_role_policy = data.aws_iam_policy_document.supplier_mock_scheduler_trust_policy.json
}

data "aws_iam_policy_document" "supplier_mock_scheduler_invoke_policy" {
statement {
sid = "AllowInvokeSupplierMockLambda"
effect = "Allow"

actions = [
"lambda:InvokeFunction",
]

resources = [
module.supplier_mock.function_arn,
]
}
}

resource "aws_iam_policy" "supplier_mock_scheduler_invoke_policy" {
name = "${local.csi}-supplier-mock-scheduler-invoke"
policy = data.aws_iam_policy_document.supplier_mock_scheduler_invoke_policy.json
}

resource "aws_iam_role_policy_attachment" "supplier_mock_scheduler_invoke_policy" {
role = aws_iam_role.supplier_mock_scheduler.name
policy_arn = aws_iam_policy.supplier_mock_scheduler_invoke_policy.arn
}

resource "aws_scheduler_schedule" "supplier_mock" {
name = "${local.csi}-supplier-mock"
description = "Scheduled trigger for supplier mock lambda"
state = var.enable_supplier_mock_scheduler ? "ENABLED" : "DISABLED"

flexible_time_window {
mode = "OFF"
}

schedule_expression = var.supplier_mock_schedule_expression

target {
arn = module.supplier_mock.function_arn
role_arn = aws_iam_role.supplier_mock_scheduler.arn
input = jsonencode({
source = "eventbridge-scheduler"
})
}
}
12 changes: 12 additions & 0 deletions infrastructure/terraform/components/api/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,18 @@ variable "enable_alarms" {
default = true
}

variable "enable_supplier_mock_scheduler" {
type = bool
description = "Enable EventBridge Scheduler trigger for supplier mock lambda"
default = false
}

variable "supplier_mock_schedule_expression" {
type = string
description = "Schedule expression for supplier mock scheduler"
default = "rate(1 minute)"
}

variable "enable_event_anomaly_detection" {
type = bool
description = "Enable CloudWatch anomaly detection alarm for SNS message Detects abnormal drops or spikes in event publishing volume."
Expand Down
5 changes: 5 additions & 0 deletions lambdas/supplier-mock/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
coverage
node_modules
dist
.reports
.aws-sam
69 changes: 69 additions & 0 deletions lambdas/supplier-mock/jest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
export const baseJestConfig = {
preset: "ts-jest",
extensionsToTreatAsEsm: [".ts"],
transform: {
"^.+\\.ts$": [
"ts-jest",
{
useESM: true,
},
],
},
transformIgnorePatterns: [
"node_modules/(?!(@nhsdigital/nhs-notify-event-schemas-supplier-config)/)",
],

// Automatically clear mock calls, instances, contexts and results before every test
clearMocks: true,

// Indicates whether the coverage information should be collected while executing the test
collectCoverage: true,

// The directory where Jest should output its coverage files
coverageDirectory: "./.reports/unit/coverage",

// Indicates which provider should be used to instrument code for coverage
coverageProvider: "babel",

coverageThreshold: {
global: {
branches: 100,
functions: 100,
lines: 100,
statements: -10,
},
},

coveragePathIgnorePatterns: ["/__tests__/"],
testPathIgnorePatterns: [".build"],
testMatch: ["**/?(*.)+(spec|test).[jt]s?(x)"],

// Use this configuration option to add custom reporters to Jest
reporters: [
"default",
[
"jest-html-reporter",
{
pageTitle: "Test Report",
outputPath: "./.reports/unit/test-report.html",
includeFailureMsg: true,
},
],
],

// The test environment that will be used for testing
testEnvironment: "jsdom",
};

const utilsJestConfig = {
...baseJestConfig,

testEnvironment: "node",

coveragePathIgnorePatterns: [
...(baseJestConfig.coveragePathIgnorePatterns ?? []),
"zod-validators.ts",
],
};

export default utilsJestConfig;
22 changes: 22 additions & 0 deletions lambdas/supplier-mock/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"dependencies": {
"@aws-sdk/client-api-gateway": "^3.1030.0",
"@aws-sdk/client-lambda": "^3.1030.0",
"@aws-sdk/client-ssm": "^3.1054.0",
"@internal/helpers": "^0.1.0",
"aws-embedded-metrics": "^4.2.1",
"aws-lambda": "^1.0.7",
"pino": "^10.3.1",
"zod": "^4.3.6"
},
"name": "nhs-notify-supplier-api-supplier-mock",
"private": true,
"scripts": {
"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",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"test:unit": "jest",
"typecheck": "tsc --noEmit"
},
"version": "0.0.1"
}
Loading
Loading