Skip to content

Commit 81bc02c

Browse files
VED-1238: Refactor all remaining lambdas deployment to a dedicated pipeline stage (#1414)
* Refactor Lambda infrastructure by removing ECR repository and lifecycle policy configurations - Deleted ECR repository configurations for record processor, batch processor filter, delta, filename processor, id sync, forwarder, redis sync, and mesh processor Lambdas. - Removed associated ECR lifecycle policies for the above Lambdas. - Updated Lambda functions to use image URIs directly from variables instead of modules. - Added new variables for backend, batch processor filter, delta, filename processor, id sync, mesh processor, MNS publisher, record forwarder, and redis sync Lambda image URIs to ensure CI/CD integration. - Cleaned up shared Lambda configurations and removed unused local variables. * Update ECR repository names in CI/CD workflows and Terraform configuration - Changed ECR repository names for various Lambda functions in the deploy-backend.yml and pr-teardown.yml workflows to reflect updated naming conventions. - Updated the lambda_ecr_repos.tf file to align with the new ECR repository names for backend, delta, filename processor, and record forwarder Lambdas, ensuring consistency across the infrastructure configuration. * Refactor Lambda image handling in workflows to use a unified repository format * Refactor Lambda deployment workflows to streamline ECR repository configurations - Updated the deploy-backend.yml workflow to use lambda_dir as the tf_var_suffix for improved clarity and consistency. - Simplified the lambda_ecr_repos.tf file by removing redundant local variables and directly defining the lifecycle policy for the recordprocessor repository. - Enhanced the ECR repository policy to maintain image retrieval actions in a more structured manner. * Add lambda ECR repository resource to Terraform configuration * Refactor ECR repository references in Terraform configuration by removing array indexing for lambda repositories, simplifying the code structure. --------- Co-authored-by: Akinola Olutola <akinola.olutola1@nhs.net>
1 parent 8eb452a commit 81bc02c

21 files changed

Lines changed: 467 additions & 817 deletions

.github/workflows/deploy-backend.yml

Lines changed: 39 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ on:
99
lambda_build_flags:
1010
description: >
1111
JSON map of lambda_name -> force-build flag.
12-
e.g. {"recordprocessor":true,"ack-backend":false}
12+
e.g. {"backend":true,"recordprocessor":true,"ack-backend":false}
1313
required: false
1414
type: string
1515
default: "{}"
@@ -73,14 +73,14 @@ on:
7373
lambda_build_flags:
7474
description: >
7575
JSON map of lambda_name -> force-build flag.
76-
e.g. {"recordprocessor":true,"ack-backend":false}
76+
e.g. {"backend":true,"recordprocessor":true,"ack-backend":false}
7777
required: false
7878
type: string
7979
default: "{}"
8080
lambda_image_overrides:
8181
description: >
8282
JSON map of lambda_name -> immutable image selector for reuse mode.
83-
e.g. {"recordprocessor":"internal-dev-git-abc123","ack-backend":"123456789012.dkr.ecr.eu-west-2.amazonaws.com/imms-ackbackend-repo@sha256:..."}
83+
e.g. {"backend":"internal-dev-git-abc123","ack-backend":"123456789012.dkr.ecr.eu-west-2.amazonaws.com/imms-ackbackend-repo@sha256:..."}
8484
required: false
8585
type: string
8686
default: "{}"
@@ -118,34 +118,54 @@ jobs:
118118
fail-fast: false
119119
matrix:
120120
include:
121+
- lambda_name: backend
122+
ecr_repository: imms-backend-repo
123+
lambda_dir: backend
124+
- lambda_name: batch_processor_filter
125+
ecr_repository: imms-batch-processor-filter-repo
126+
lambda_dir: batch_processor_filter
127+
- lambda_name: delta_backend
128+
ecr_repository: imms-delta-backend-repo
129+
lambda_dir: delta_backend
130+
- lambda_name: filenameprocessor
131+
ecr_repository: imms-filenameprocessor-repo
132+
lambda_dir: filenameprocessor
133+
- lambda_name: id_sync
134+
ecr_repository: imms-id-sync-repo
135+
lambda_dir: id_sync
136+
- lambda_name: mesh_processor
137+
ecr_repository: imms-mesh-processor-repo
138+
lambda_dir: mesh_processor
139+
- lambda_name: mns_publisher
140+
ecr_repository: imms-mns-publisher-repo
141+
lambda_dir: mns_publisher
142+
- lambda_name: recordforwarder
143+
ecr_repository: imms-recordforwarder-repo
144+
lambda_dir: recordforwarder
145+
- lambda_name: redis_sync
146+
ecr_repository: imms-redis-sync-repo
147+
lambda_dir: redis_sync
121148
- lambda_name: recordprocessor
122-
tf_var_suffix: recordprocessor
123149
ecr_repository: imms-recordprocessor-repo
124-
dockerfile_path: lambdas/recordprocessor/Dockerfile
125-
lambda_paths: |
126-
lambdas/recordprocessor/
150+
lambda_dir: recordprocessor
127151
- lambda_name: ack-backend
128-
tf_var_suffix: ack_backend
129152
ecr_repository: imms-ackbackend-repo
130-
dockerfile_path: lambdas/ack_backend/Dockerfile
131-
lambda_paths: |
132-
lambdas/ack_backend/
153+
lambda_dir: ack_backend
133154
uses: ./.github/workflows/deploy-lambda-artifact.yml
134155
with:
135156
lambda_name: ${{ matrix.lambda_name }}
136-
tf_var_suffix: ${{ matrix.tf_var_suffix }}
157+
tf_var_suffix: ${{ matrix.lambda_dir }}
137158
environment: ${{ inputs.environment }}
138159
sub_environment: ${{ inputs.sub_environment }}
139160
build_image: ${{ fromJson(inputs.lambda_build_flags)[matrix.lambda_name] || false }}
140161
image_version: ${{ fromJson(inputs.lambda_image_overrides)[matrix.lambda_name] || '' }}
141162
run_diff_check: ${{ inputs.run_diff_check }}
142163
diff_base_sha: ${{ inputs.diff_base_sha }}
143164
diff_head_sha: ${{ inputs.diff_head_sha }}
144-
lambda_paths: ${{ matrix.lambda_paths }}
145-
shared_paths: |
146-
lambdas/shared/src/common/
165+
lambda_paths: lambdas/${{ matrix.lambda_dir }}/
166+
shared_paths: lambdas/shared/src/common/
147167
docker_context_path: lambdas
148-
dockerfile_path: ${{ matrix.dockerfile_path }}
168+
dockerfile_path: lambdas/${{ matrix.lambda_dir }}/Dockerfile
149169
ecr_repository: ${{ matrix.ecr_repository }}
150170
image_tag_prefix: ${{ inputs.sub_environment }}-
151171
allow_implicit_tag_prefix_reuse: ${{ inputs.sub_environment == 'internal-dev' || startsWith(inputs.sub_environment, 'pr-') }}
@@ -159,7 +179,6 @@ jobs:
159179
if: ${{ !cancelled() && needs.deploy-lambda-images.result == 'success' }}
160180
outputs:
161181
image_uris_json: ${{ steps.lambda-images.outputs.image_uris_json }}
162-
terraform_image_uris_json: ${{ steps.lambda-images.outputs.terraform_image_uris_json }}
163182
runs-on: ubuntu-latest
164183
environment:
165184
name: ${{ inputs.environment }}
@@ -218,17 +237,11 @@ jobs:
218237
"${manifest_files[@]}"
219238
)"
220239
221-
terraform_image_uris_json="$(
222-
jq -cs 'map(select(.tf_var_suffix != null and .tf_var_suffix != "" and .image_uri != null) | {(.tf_var_suffix): .image_uri}) | add' \
223-
"${manifest_files[@]}"
224-
)"
225-
226240
echo "image_uris_json=${image_uris_json}" >> "$GITHUB_OUTPUT"
227-
echo "terraform_image_uris_json=${terraform_image_uris_json}" >> "$GITHUB_OUTPUT"
228241
jq -er '
229-
to_entries[]
230-
| "TF_VAR_\(.key)_image_uri=\(.value)"
231-
' <<< "${terraform_image_uris_json}" >> "$GITHUB_ENV"
242+
select(.tf_var_suffix != null and .tf_var_suffix != "" and .image_uri != null)
243+
| "TF_VAR_\(.tf_var_suffix)_image_uri=\(.image_uri)"
244+
' "${manifest_files[@]}" >> "$GITHUB_ENV"
232245
233246
- name: Terraform Init
234247
working-directory: infrastructure/instance
@@ -270,22 +283,6 @@ jobs:
270283
with:
271284
terraform_version: "1.12.2"
272285

273-
- name: Restore lambda image Terraform vars
274-
env:
275-
TERRAFORM_IMAGE_URIS_JSON: ${{ needs.terraform-plan.outputs.terraform_image_uris_json }}
276-
run: |
277-
set -euo pipefail
278-
279-
if [ -z "${TERRAFORM_IMAGE_URIS_JSON}" ] || [ "${TERRAFORM_IMAGE_URIS_JSON}" = "null" ]; then
280-
echo "terraform-plan did not emit terraform_image_uris_json."
281-
exit 1
282-
fi
283-
284-
jq -er '
285-
to_entries[]
286-
| "TF_VAR_\(.key)_image_uri=\(.value)"
287-
' <<< "${TERRAFORM_IMAGE_URIS_JSON}" >> "$GITHUB_ENV"
288-
289286
- name: Retrieve Terraform Plan
290287
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
291288
with:

.github/workflows/pr-deploy-and-test.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,6 @@ jobs:
2020
uses: ./.github/workflows/deploy-backend.yml
2121
with:
2222
apigee_environment: internal-dev
23-
lambda_build_flags: >-
24-
${{ (github.event.action == 'opened' || github.event.action == 'reopened')
25-
&& '{"recordprocessor":true,"ack-backend":true}'
26-
|| '{}' }}
2723
diff_base_sha: ${{ github.event.action == 'synchronize' && github.event.before || github.event.pull_request.base.sha }}
2824
diff_head_sha: ${{ github.event.pull_request.head.sha }}
2925
run_diff_check: ${{ github.event.action == 'synchronize' }}

.github/workflows/pr-teardown.yml

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,18 @@ jobs:
2020
APIGEE_ENVIRONMENT: internal-dev
2121
BACKEND_ENVIRONMENT: dev
2222
BACKEND_SUB_ENVIRONMENT: pr-${{ github.event_name == 'pull_request' && github.event.pull_request.number || inputs.pr_number }}
23+
LAMBDA_IMAGE_REPOSITORIES: |
24+
backend:imms-backend-repo
25+
batch_processor_filter:imms-batch-processor-filter-repo
26+
delta_backend:imms-delta-backend-repo
27+
filenameprocessor:imms-filenameprocessor-repo
28+
id_sync:imms-id-sync-repo
29+
mesh_processor:imms-mesh-processor-repo
30+
mns_publisher:imms-mns-publisher-repo
31+
recordprocessor:imms-recordprocessor-repo
32+
recordforwarder:imms-recordforwarder-repo
33+
ack_backend:imms-ackbackend-repo
34+
redis_sync:imms-redis-sync-repo
2335
permissions:
2436
id-token: write
2537
contents: read
@@ -53,8 +65,10 @@ jobs:
5365
local uri="$(make -s output "name=$1" 2>/dev/null || true)"
5466
echo "${uri:-placeholder.dkr.ecr.eu-west-2.amazonaws.com/$2@sha256:0000000000000000000000000000000000000000000000000000000000000000}"
5567
}
56-
echo "TF_VAR_recordprocessor_image_uri=$(resolve_or_placeholder recordprocessor_image_uri imms-recordprocessor-repo)" >> $GITHUB_ENV
57-
echo "TF_VAR_ack_backend_image_uri=$(resolve_or_placeholder ack_backend_image_uri imms-ackbackend-repo)" >> $GITHUB_ENV
68+
while IFS=: read -r lambda_name repository_name; do
69+
[ -n "${lambda_name}" ] || continue
70+
echo "TF_VAR_${lambda_name}_image_uri=$(resolve_or_placeholder "${lambda_name}_image_uri" "${repository_name}")" >> $GITHUB_ENV
71+
done <<< "${LAMBDA_IMAGE_REPOSITORIES}"
5872
5973
- name: Install poetry
6074
run: pip install poetry==2.1.4
@@ -129,6 +143,8 @@ jobs:
129143
--output json
130144
}
131145
132-
for repository_name in imms-recordprocessor-repo imms-ackbackend-repo; do
146+
while IFS=: read -r lambda_name repository_name; do
147+
[ -n "${lambda_name}" ] || continue
148+
[ -n "${repository_name}" ] || continue
133149
cleanup_repo_by_prefix "${repository_name}"
134-
done
150+
done <<< "${LAMBDA_IMAGE_REPOSITORIES}"

infrastructure/account/ackbackend_ecr_repo.tf

Lines changed: 0 additions & 33 deletions
This file was deleted.
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
locals {
2+
lambda_source_arn_prefix = "arn:aws:lambda:${var.aws_region}:${var.imms_account_id}:function:imms-"
3+
4+
lambda_ecr_repositories = {
5+
operation = {
6+
name = "imms-backend-repo"
7+
lambda_source_names = [
8+
"*_get_status",
9+
"*_not_found",
10+
"*_search_imms",
11+
"*_get_imms",
12+
"*_delete_imms",
13+
"*_create_imms",
14+
"*_update_imms"
15+
]
16+
}
17+
batch_processor_filter = {
18+
name = "imms-batch-processor-filter-repo"
19+
lambda_source_names = ["*-batch-processor-filter-lambda"]
20+
}
21+
delta = {
22+
name = "imms-delta-backend-repo"
23+
lambda_source_names = ["*-delta-lambda"]
24+
}
25+
filenameprocessor = {
26+
name = "imms-filenameprocessor-repo"
27+
lambda_source_names = ["*-filenameproc-lambda"]
28+
}
29+
id_sync = {
30+
name = "imms-id-sync-repo"
31+
lambda_source_names = ["*-id-sync-lambda"]
32+
}
33+
mesh_processor = {
34+
name = "imms-mesh-processor-repo"
35+
lambda_source_names = ["*-mesh-processor-lambda"]
36+
}
37+
mns_publisher = {
38+
name = "imms-mns-publisher-repo"
39+
lambda_source_names = ["*-mns-publisher-lambda"]
40+
}
41+
ack_backend = {
42+
name = "imms-ackbackend-repo"
43+
lambda_source_names = ["*-ack-lambda"]
44+
}
45+
recordforwarder = {
46+
name = "imms-recordforwarder-repo"
47+
lambda_source_names = ["*-forwarding-lambda"]
48+
}
49+
recordprocessor = {
50+
name = "imms-recordprocessor-repo"
51+
lifecycle_policy = jsonencode({
52+
rules = [
53+
{
54+
rulePriority = 1
55+
description = "Keep last 10 images."
56+
selection = {
57+
tagStatus = "any"
58+
countType = "imageCountMoreThan"
59+
countNumber = 10
60+
}
61+
action = {
62+
type = "expire"
63+
}
64+
}
65+
]
66+
})
67+
}
68+
redis_sync = {
69+
name = "imms-redis-sync-repo"
70+
lambda_source_names = ["*-redis-sync-lambda"]
71+
}
72+
}
73+
}
74+
#lambda repo
75+
resource "aws_ecr_repository" "lambda_repository" {
76+
for_each = local.lambda_ecr_repositories
77+
78+
image_scanning_configuration {
79+
scan_on_push = true
80+
}
81+
82+
image_tag_mutability = "IMMUTABLE"
83+
name = each.value.name
84+
}
85+
86+
resource "aws_ecr_repository_policy" "lambda_repository_image_retrieval_policy" {
87+
for_each = {
88+
for key, repo in local.lambda_ecr_repositories : key => repo if try(repo.lambda_source_names, null) != null
89+
}
90+
91+
repository = aws_ecr_repository.lambda_repository[each.key].name
92+
93+
policy = jsonencode({
94+
Version = "2012-10-17"
95+
Statement = [
96+
{
97+
Sid = "LambdaECRImageRetrievalPolicy"
98+
Effect = "Allow"
99+
Principal = {
100+
Service = "lambda.amazonaws.com"
101+
}
102+
Action = [
103+
"ecr:BatchGetImage",
104+
"ecr:GetDownloadUrlForLayer"
105+
]
106+
Condition = {
107+
StringLike = {
108+
"aws:sourceArn" = formatlist("${local.lambda_source_arn_prefix}%s", each.value.lambda_source_names)
109+
}
110+
}
111+
}
112+
]
113+
})
114+
}
115+
116+
resource "aws_ecr_lifecycle_policy" "lambda_repository_lifecycle_policy" {
117+
for_each = {
118+
for key, repo in local.lambda_ecr_repositories : key => repo if try(repo.lifecycle_policy, null) != null
119+
}
120+
121+
repository = aws_ecr_repository.lambda_repository[each.key].name
122+
policy = each.value.lifecycle_policy
123+
}
124+
125+
moved {
126+
from = aws_ecr_repository.ackbackend_repository
127+
to = aws_ecr_repository.lambda_repository["ack_backend"]
128+
}
129+
130+
moved {
131+
from = aws_ecr_repository_policy.ackbackend_repository_lambda_image_retrieval_policy
132+
to = aws_ecr_repository_policy.lambda_repository_image_retrieval_policy["ack_backend"]
133+
}
134+
135+
moved {
136+
from = aws_ecr_repository.recordprocessor_repository
137+
to = aws_ecr_repository.lambda_repository["recordprocessor"]
138+
}
139+
140+
moved {
141+
from = aws_ecr_lifecycle_policy.recordprocessor_repository_lifecycle_policy
142+
to = aws_ecr_lifecycle_policy.lambda_repository_lifecycle_policy["recordprocessor"]
143+
}

infrastructure/account/recordprocessor_ecr_repo.tf

Lines changed: 0 additions & 7 deletions
This file was deleted.

0 commit comments

Comments
 (0)