forked from aws-samples/serverless-test-samples
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
104 lines (89 loc) · 3.95 KB
/
app.py
File metadata and controls
104 lines (89 loc) · 3.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
"""
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: MIT-0
"""
# Start of lambda handler code: src/sampleLambda/app.py
from os import environ
from typing import Any, Dict
from boto3 import resource
from aws_lambda_powertools.utilities.data_classes import APIGatewayProxyEvent
from aws_lambda_powertools.utilities.typing import LambdaContext
from aws_lambda_powertools.utilities.validation import validator
# Import the schema for the Lambda Powertools Validator
from schemas import INPUT_SCHEMA, OUTPUT_SCHEMA
# [1] Globally scoped resources
# Initialize the resources once per Lambda execution environment by using global scope.
_LAMBDA_DYNAMODB_RESOURCE = { "resource" : resource('dynamodb'),
"table_name" : environ.get("DYNAMODB_TABLE_NAME","NONE") }
_LAMBDA_S3_RESOURCE = { "resource" : resource('s3'),
"bucket_name" : environ.get("S3_BUCKET_NAME","NONE") }
# [2] Define a Global class an AWS Resource: Amazon DynamoDB.
class LambdaDynamoDBClass:
"""
AWS DynamoDB Resource Class
"""
def __init__(self, lambda_dynamodb_resource):
"""
Initialize a DynamoDB Resource
"""
self.resource = lambda_dynamodb_resource["resource"]
self.table_name = lambda_dynamodb_resource["table_name"]
self.table = self.resource.Table(self.table_name)
# [3] Define a Global class an AWS Resource: Amazon S3 bucket.
class LambdaS3Class:
"""
AWS S3 Resource Class
"""
def __init__(self, lambda_s3_resource):
"""
Initialize an S3 Resource
"""
self.resource = lambda_s3_resource["resource"]
self.bucket_name = lambda_s3_resource["bucket_name"]
self.bucket = self.resource.Bucket(self.bucket_name)
# [4] Validate the event schema and return schema using Lambda Power Tools
@validator(inbound_schema=INPUT_SCHEMA, outbound_schema=OUTPUT_SCHEMA)
def lambda_handler(event: APIGatewayProxyEvent, context: LambdaContext) -> Dict[str, Any]:
"""
Lambda Entry Point
"""
# [5] Use the Global variables to optimize AWS resource connections
global _LAMBDA_DYNAMODB_RESOURCE
global _LAMBDA_S3_RESOURCE
dynamodb_resource_class = LambdaDynamoDBClass(_LAMBDA_DYNAMODB_RESOURCE)
s3_resource_class = LambdaS3Class(_LAMBDA_S3_RESOURCE)
# [6] Explicitly pass the global resource to subsequent functions
return create_letter_in_s3(
dynamo_db = dynamodb_resource_class,
s3 = s3_resource_class,
doc_type = event["pathParameters"]["docType"],
cust_id = event["pathParameters"]["customerId"])
def create_letter_in_s3( dynamo_db: LambdaDynamoDBClass,
s3: LambdaS3Class,
doc_type: str,
cust_id: str) -> dict:
"""
Given a document type and a customer id, create a text document in S3
Document contents and customer name are retrieved from DynamoDB
"""
status_code = 200
body = "OK"
try:
# [7] Use the passed environment class for AWS resource access - DynamoDB
customer_name = dynamo_db.table.get_item(Key={"PK": f"C#{cust_id}"})["Item"]["data"]
document_text = dynamo_db.table.get_item(Key={"PK": f"D#{doc_type}"})["Item"]["data"]
# [8] Use the passed environment class for AWS resource access - S3
s3_file_key = f"{cust_id}/{doc_type}.txt"
s3.bucket.put_object(Key=s3_file_key,
Body=f"Dear {customer_name};\n{document_text}".encode('utf-8'),
ServerSideEncryption='AES256')
body = f"{body} {s3_file_key}"
except KeyError as index_error:
body = "Not Found: " + str(index_error)
status_code = 404
except Exception as other_error:
body = "ERROR: " + str(other_error)
status_code = 500
finally:
return {"statusCode": status_code, "body" : body }
# End of lambda handler code