From ee0d83f0ed0ecadd4d8d5d8a8928db7622ba0aef Mon Sep 17 00:00:00 2001 From: Michael Brewer Date: Tue, 12 Apr 2022 16:30:34 -0700 Subject: [PATCH 1/7] fix: Extract landing page docs Changes: - Extract all code examples - Fix yaml, terraform and python - Add make file to format, lint and validate examples Related to - #1064 Fixed - #1067 - #1069 --- Makefile | 11 + docs/examples/index/debug_mode.py | 3 + docs/examples/index/lambda_layer_cdk_app.py | 19 ++ docs/examples/index/lambda_layer_main.tf | 38 +++ docs/examples/index/lambda_layer_template.yml | 11 + .../index/least_priviledged_template.yml | 54 +++++ docs/examples/index/sar_cdk_app.py | 35 +++ docs/examples/index/sar_main.tf | 41 ++++ docs/examples/index/sar_template.yml | 19 ++ docs/index.md | 229 +----------------- 10 files changed, 244 insertions(+), 216 deletions(-) create mode 100644 docs/examples/index/debug_mode.py create mode 100644 docs/examples/index/lambda_layer_cdk_app.py create mode 100644 docs/examples/index/lambda_layer_main.tf create mode 100644 docs/examples/index/lambda_layer_template.yml create mode 100644 docs/examples/index/least_priviledged_template.yml create mode 100644 docs/examples/index/sar_cdk_app.py create mode 100644 docs/examples/index/sar_main.tf create mode 100644 docs/examples/index/sar_template.yml diff --git a/Makefile b/Makefile index 73667eb5f58..3acbddbdd57 100644 --- a/Makefile +++ b/Makefile @@ -90,3 +90,14 @@ changelog: mypy: poetry run mypy --pretty aws_lambda_powertools + +format-examples: + poetry run isort docs/shared + poetry run black docs/shared/*.py + poetry run isort docs/examples + poetry run black docs/examples/*/*.py + +lint-examples: + poetry run python3 -m py_compile docs/shared/*.py + poetry run python3 -m py_compile docs/examples/*/*.py + cfn-lint docs/examples/*/*.yml diff --git a/docs/examples/index/debug_mode.py b/docs/examples/index/debug_mode.py new file mode 100644 index 00000000000..d063da98645 --- /dev/null +++ b/docs/examples/index/debug_mode.py @@ -0,0 +1,3 @@ +from aws_lambda_powertools.logging.logger import set_package_logger + +set_package_logger() # (1) diff --git a/docs/examples/index/lambda_layer_cdk_app.py b/docs/examples/index/lambda_layer_cdk_app.py new file mode 100644 index 00000000000..44e7a98c440 --- /dev/null +++ b/docs/examples/index/lambda_layer_cdk_app.py @@ -0,0 +1,19 @@ +from aws_cdk import aws_lambda, core + + +class SampleApp(core.Construct): + def __init__(self, scope: core.Construct, id_: str, env: core.Environment) -> None: + super().__init__(scope, id_) + + powertools_layer = aws_lambda.LayerVersion.from_layer_version_arn( + self, + id="lambda-powertools", + layer_version_arn=f"arn:aws:lambda:{env.region}:017000801446:layer:AWSLambdaPowertoolsPython:17", + ) + aws_lambda.Function( + self, + "sample-app-lambda", + runtime=aws_lambda.Runtime.PYTHON_3_9, + layers=[powertools_layer] + # other props... + ) diff --git a/docs/examples/index/lambda_layer_main.tf b/docs/examples/index/lambda_layer_main.tf new file mode 100644 index 00000000000..0e77c214a9e --- /dev/null +++ b/docs/examples/index/lambda_layer_main.tf @@ -0,0 +1,38 @@ +terraform { + required_version = "~> 1.1.7" + required_providers { + aws = "~> 4.4.0" + } +} + +provider "aws" { + region = "{region}" +} + +resource "aws_iam_role" "iam_for_lambda" { + name = "iam_for_lambda" + + assume_role_policy = jsonencode({ + Version = "2012-10-17", + Statement = [ + { + Action = "sts:AssumeRole", + Principal = { + Service = "lambda.amazonaws.com" + }, + Effect = "Allow" + } + ] + }) +} + +resource "aws_lambda_function" "test_lambda" { + filename = "lambda_function_payload.zip" + function_name = "lambda_function_name" + role = aws_iam_role.iam_for_lambda.arn + handler = "index.test" + runtime = "python3.9" + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPython:17"] + + source_code_hash = filebase64sha256("lambda_function_payload.zip") +} diff --git a/docs/examples/index/lambda_layer_template.yml b/docs/examples/index/lambda_layer_template.yml new file mode 100644 index 00000000000..4f5d4840ef2 --- /dev/null +++ b/docs/examples/index/lambda_layer_template.yml @@ -0,0 +1,11 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Resources: + MyLambdaFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: src + Handler: app.lambda_handler + Runtime: python3.9 + Layers: + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPython:17 diff --git a/docs/examples/index/least_priviledged_template.yml b/docs/examples/index/least_priviledged_template.yml new file mode 100644 index 00000000000..bb33810fca7 --- /dev/null +++ b/docs/examples/index/least_priviledged_template.yml @@ -0,0 +1,54 @@ +AWSTemplateFormatVersion: "2010-09-09" +Resources: + PowertoolsLayerIamRole: + Type: "AWS::IAM::Role" + Properties: + AssumeRolePolicyDocument: + Version: "2012-10-17" + Statement: + - Effect: "Allow" + Principal: + Service: + - "cloudformation.amazonaws.com" + Action: + - "sts:AssumeRole" + Path: "/" + PowertoolsLayerIamPolicy: + Type: "AWS::IAM::Policy" + Properties: + PolicyName: PowertoolsLambdaLayerPolicy + PolicyDocument: + Version: "2012-10-17" + Statement: + - Sid: CloudFormationTransform + Effect: Allow + Action: cloudformation:CreateChangeSet + Resource: + - arn:aws:cloudformation:us-east-1:aws:transform/Serverless-2016-10-31 + - Sid: GetCfnTemplate + Effect: Allow + Action: + - serverlessrepo:CreateCloudFormationTemplate + - serverlessrepo:GetCloudFormationTemplate + Resource: + # this is arn of the powertools SAR app + - arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer + - Sid: S3AccessLayer + Effect: Allow + Action: + - s3:GetObject + Resource: + # AWS publishes to an external S3 bucket locked down to your account ID + # The below example is us publishing lambda powertools + # Bucket: awsserverlessrepo-changesets-plntc6bfnfj + # Key: *****/arn:aws:serverlessrepo:eu-west-1:057560766410:applications-aws-lambda-powertools-python-layer-versions-1.10.2/aeeccf50-****-****-****-********* + - arn:aws:s3:::awsserverlessrepo-changesets-*/* + - Sid: GetLayerVersion + Effect: Allow + Action: + - lambda:PublishLayerVersion + - lambda:GetLayerVersion + Resource: + - !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:layer:aws-lambda-powertools-python-layer* + Roles: + - Ref: "PowertoolsLayerIamRole" diff --git a/docs/examples/index/sar_cdk_app.py b/docs/examples/index/sar_cdk_app.py new file mode 100644 index 00000000000..5072861e0db --- /dev/null +++ b/docs/examples/index/sar_cdk_app.py @@ -0,0 +1,35 @@ +from aws_cdk import aws_lambda +from aws_cdk import aws_sam as sam +from aws_cdk import core + +POWERTOOLS_BASE_NAME = "AWSLambdaPowertools" +# Find latest from github.com/awslabs/aws-lambda-powertools-python/releases +POWERTOOLS_VER = "1.25.6" +POWERTOOLS_ARN = "arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer" + + +class SampleApp(core.Construct): + def __init__(self, scope: core.Construct, id_: str) -> None: + super().__init__(scope, id_) + + # Launches SAR App as CloudFormation nested stack and return Lambda Layer + powertools_app = sam.CfnApplication( + self, + f"{POWERTOOLS_BASE_NAME}Application", + location={"applicationId": POWERTOOLS_ARN, "semanticVersion": POWERTOOLS_VER}, + ) + + powertools_layer_arn = powertools_app.get_att("Outputs.LayerVersionArn").to_string() + powertools_layer_version = aws_lambda.LayerVersion.from_layer_version_arn( + self, f"{POWERTOOLS_BASE_NAME}", powertools_layer_arn + ) + + aws_lambda.Function( + self, + "sample-app-lambda", + runtime=aws_lambda.Runtime.PYTHON_3_8, + function_name="sample-lambda", + code=aws_lambda.Code.asset("./src"), + handler="app.handler", + layers=[powertools_layer_version], + ) diff --git a/docs/examples/index/sar_main.tf b/docs/examples/index/sar_main.tf new file mode 100644 index 00000000000..26d04f3be4d --- /dev/null +++ b/docs/examples/index/sar_main.tf @@ -0,0 +1,41 @@ +terraform { + required_version = "~> 0.13" + required_providers { + aws = "~> 3.50.0" + } +} + +provider "aws" { + region = "us-east-1" +} + +resource "aws_serverlessapplicationrepository_cloudformation_stack" "deploy_sar_stack" { + name = "aws-lambda-powertools-python-layer" + + application_id = data.aws_serverlessapplicationrepository_application.sar_app.application_id + semantic_version = data.aws_serverlessapplicationrepository_application.sar_app.semantic_version + capabilities = [ + "CAPABILITY_IAM", + "CAPABILITY_NAMED_IAM" + ] +} + +data "aws_serverlessapplicationrepository_application" "sar_app" { + application_id = "arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer" + semantic_version = var.aws_powertools_version +} + +variable "aws_powertools_version" { + type = string + default = "1.25.6" + description = "The AWS Powertools release version" +} + +output "deployed_powertools_sar_version" { + value = data.aws_serverlessapplicationrepository_application.sar_app.semantic_version +} + +# Fetch Lambda Powertools Layer ARN from deployed SAR App +output "aws_lambda_powertools_layer_arn" { + value = aws_serverlessapplicationrepository_cloudformation_stack.deploy_sar_stack.outputs.LayerVersionArn +} diff --git a/docs/examples/index/sar_template.yml b/docs/examples/index/sar_template.yml new file mode 100644 index 00000000000..5a66c68d99a --- /dev/null +++ b/docs/examples/index/sar_template.yml @@ -0,0 +1,19 @@ +AWSTemplateFormatVersion: '2010-09-09' +Transform: AWS::Serverless-2016-10-31 +Resources: + AwsLambdaPowertoolsPythonLayer: + Type: AWS::Serverless::Application + Properties: + Location: + ApplicationId: arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer + SemanticVersion: 1.25.6 # change to latest semantic version available in SAR + + MyLambdaFunction: + Type: AWS::Serverless::Function + Properties: + CodeUri: src + Handler: app.lambda_handler + Runtime: python3.9 + Layers: + # fetch Layer ARN from SAR App stack output + - !GetAtt AwsLambdaPowertoolsPythonLayer.Outputs.LayerVersionArn diff --git a/docs/index.md b/docs/index.md index 9a1a876fa0d..aa9dfa4750b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -9,7 +9,6 @@ A suite of utilities for AWS Lambda functions to ease adopting best practices su Check out [this detailed blog post](https://aws.amazon.com/blogs/opensource/simplifying-serverless-best-practices-with-lambda-powertools/) with a practical example. - ## Install Powertools is available in the following formats: @@ -58,12 +57,8 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: === "SAM" - ```yaml hl_lines="5" - MyLambdaFunction: - Type: AWS::Serverless::Function - Properties: - Layers: - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPython:17 + ```yaml hl_lines="11" + --8<-- "docs/examples/index/lambda_layer_template.yml" ``` === "Serverless framework" @@ -79,71 +74,13 @@ You can include Lambda Powertools Lambda Layer using [AWS Lambda Console](https: === "CDK" ```python hl_lines="11 16" - from aws_cdk import core, aws_lambda - - class SampleApp(core.Construct): - - def __init__(self, scope: core.Construct, id_: str, env: core.Environment) -> None: - super().__init__(scope, id_) - - powertools_layer = aws_lambda.LayerVersion.from_layer_version_arn( - self, - id="lambda-powertools", - layer_version_arn=f"arn:aws:lambda:{env.region}:017000801446:layer:AWSLambdaPowertoolsPython:17" - ) - aws_lambda.Function(self, - 'sample-app-lambda', - runtime=aws_lambda.Runtime.PYTHON_3_9, - layers=[powertools_layer] - # other props... - ) + --8<-- "docs/examples/index/lambda_layer_cdk_app.py" ``` === "Terraform" - ```terraform hl_lines="9 38" - terraform { - required_version = "~> 1.0.5" - required_providers { - aws = "~> 3.50.0" - } - } - - provider "aws" { - region = "{region}" - } - - resource "aws_iam_role" "iam_for_lambda" { - name = "iam_for_lambda" - - assume_role_policy = < None: - super().__init__(scope, id_) - - # Launches SAR App as CloudFormation nested stack and return Lambda Layer - powertools_app = sam.CfnApplication(self, - f'{POWERTOOLS_BASE_NAME}Application', - location={ - 'applicationId': POWERTOOLS_ARN, - 'semanticVersion': POWERTOOLS_VER - }, - ) - - powertools_layer_arn = powertools_app.get_att("Outputs.LayerVersionArn").to_string() - powertools_layer_version = aws_lambda.LayerVersion.from_layer_version_arn(self, f'{POWERTOOLS_BASE_NAME}', powertools_layer_arn) - - aws_lambda.Function(self, - 'sample-app-lambda', - runtime=aws_lambda.Runtime.PYTHON_3_8, - function_name='sample-lambda', - code=aws_lambda.Code.asset('./src'), - handler='app.handler', - layers: [powertools_layer_version] - ) + ```python hl_lines="19 22-25 34" + --8<-- "docs/examples/index/sar_cdk_app.py" ``` === "Terraform" @@ -289,47 +181,7 @@ If using SAM, you can include this SAR App as part of your shared Layers stack, > Credits to [Dani Comnea](https://github.com/DanyC97) for providing the Terraform equivalent. ```terraform hl_lines="12-13 15-20 23-25 40" - terraform { - required_version = "~> 0.13" - required_providers { - aws = "~> 3.50.0" - } - } - - provider "aws" { - region = "us-east-1" - } - - resource "aws_serverlessapplicationrepository_cloudformation_stack" "deploy_sar_stack" { - name = "aws-lambda-powertools-python-layer" - - application_id = data.aws_serverlessapplicationrepository_application.sar_app.application_id - semantic_version = data.aws_serverlessapplicationrepository_application.sar_app.semantic_version - capabilities = [ - "CAPABILITY_IAM", - "CAPABILITY_NAMED_IAM" - ] - } - - data "aws_serverlessapplicationrepository_application" "sar_app" { - application_id = "arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer" - semantic_version = var.aws_powertools_version - } - - variable "aws_powertools_version" { - type = string - default = "1.20.2" - description = "The AWS Powertools release version" - } - - output "deployed_powertools_sar_version" { - value = data.aws_serverlessapplicationrepository_application.sar_app.semantic_version - } - - # Fetch Lambda Powertools Layer ARN from deployed SAR App - output "aws_lambda_powertools_layer_arn" { - value = aws_serverlessapplicationrepository_cloudformation_stack.deploy_sar_stack.outputs.LayerVersionArn - } + --8<-- "docs/examples/index/sar_main.tf" ``` ??? example "Example: Least-privileged IAM permissions to deploy Layer" @@ -341,60 +193,7 @@ If using SAM, you can include this SAR App as part of your shared Layers stack, === "template.yml" ```yaml hl_lines="21-52" - AWSTemplateFormatVersion: "2010-09-09" - Resources: - PowertoolsLayerIamRole: - Type: "AWS::IAM::Role" - Properties: - AssumeRolePolicyDocument: - Version: "2012-10-17" - Statement: - - Effect: "Allow" - Principal: - Service: - - "cloudformation.amazonaws.com" - Action: - - "sts:AssumeRole" - Path: "/" - PowertoolsLayerIamPolicy: - Type: "AWS::IAM::Policy" - Properties: - PolicyName: PowertoolsLambdaLayerPolicy - PolicyDocument: - Version: "2012-10-17" - Statement: - - Sid: CloudFormationTransform - Effect: Allow - Action: cloudformation:CreateChangeSet - Resource: - - arn:aws:cloudformation:us-east-1:aws:transform/Serverless-2016-10-31 - - Sid: GetCfnTemplate - Effect: Allow - Action: - - serverlessrepo:CreateCloudFormationTemplate - - serverlessrepo:GetCloudFormationTemplate - Resource: - # this is arn of the powertools SAR app - - arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer - - Sid: S3AccessLayer - Effect: Allow - Action: - - s3:GetObject - Resource: - # AWS publishes to an external S3 bucket locked down to your account ID - # The below example is us publishing lambda powertools - # Bucket: awsserverlessrepo-changesets-plntc6bfnfj - # Key: *****/arn:aws:serverlessrepo:eu-west-1:057560766410:applications-aws-lambda-powertools-python-layer-versions-1.10.2/aeeccf50-****-****-****-********* - - arn:aws:s3:::awsserverlessrepo-changesets-*/* - - Sid: GetLayerVersion - Effect: Allow - Action: - - lambda:PublishLayerVersion - - lambda:GetLayerVersion - Resource: - - !Sub arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:layer:aws-lambda-powertools-python-layer* - Roles: - - Ref: "PowertoolsLayerIamRole" + --8<-- "docs/examples/index/least_priviledged_template.yml" ``` You can fetch available versions via SAR ListApplicationVersions API: @@ -455,9 +254,7 @@ Core utilities such as Tracing, Logging, Metrics, and Event Handler will be avai As a best practice, AWS Lambda Powertools module logging statements are suppressed. If necessary, you can enable debugging using `set_package_logger` for additional information on every internal operation: ```python title="Powertools debug mode example" -from aws_lambda_powertools.logging.logger import set_package_logger - -set_package_logger() # (1) +--8<-- "docs/examples/index/debug_mode.py" ``` 1. :information_source: this will configure our `aws_lambda_powertools` logger with debug. From eb26d9f6bb5bdda921b033320032b2dc9330a946 Mon Sep 17 00:00:00 2001 From: Michael Brewer Date: Thu, 21 Apr 2022 10:05:14 -0700 Subject: [PATCH 2/7] chore: sync up changes --- docs/examples/index/lambda_layer_template.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/index/lambda_layer_template.yml b/docs/examples/index/lambda_layer_template.yml index 4f5d4840ef2..68b3782c9bb 100644 --- a/docs/examples/index/lambda_layer_template.yml +++ b/docs/examples/index/lambda_layer_template.yml @@ -8,4 +8,4 @@ Resources: Handler: app.lambda_handler Runtime: python3.9 Layers: - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPython:17 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPython:18 From e8a7232af678ff3fed8a0266dde62023b249aced Mon Sep 17 00:00:00 2001 From: Michael Brewer Date: Thu, 21 Apr 2022 10:05:57 -0700 Subject: [PATCH 3/7] chore: sync up changes --- docs/examples/index/lambda_layer_main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/index/lambda_layer_main.tf b/docs/examples/index/lambda_layer_main.tf index 0e77c214a9e..739ebf55495 100644 --- a/docs/examples/index/lambda_layer_main.tf +++ b/docs/examples/index/lambda_layer_main.tf @@ -32,7 +32,7 @@ resource "aws_lambda_function" "test_lambda" { role = aws_iam_role.iam_for_lambda.arn handler = "index.test" runtime = "python3.9" - layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPython:17"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPython:18"] source_code_hash = filebase64sha256("lambda_function_payload.zip") } From f9a7e79e270493b3a9b5b23d505b373a75763b66 Mon Sep 17 00:00:00 2001 From: Michael Brewer Date: Thu, 21 Apr 2022 10:06:30 -0700 Subject: [PATCH 4/7] chore: sync up changes --- docs/examples/index/lambda_layer_cdk_app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/examples/index/lambda_layer_cdk_app.py b/docs/examples/index/lambda_layer_cdk_app.py index 44e7a98c440..5dd9e5cb765 100644 --- a/docs/examples/index/lambda_layer_cdk_app.py +++ b/docs/examples/index/lambda_layer_cdk_app.py @@ -8,7 +8,7 @@ def __init__(self, scope: core.Construct, id_: str, env: core.Environment) -> No powertools_layer = aws_lambda.LayerVersion.from_layer_version_arn( self, id="lambda-powertools", - layer_version_arn=f"arn:aws:lambda:{env.region}:017000801446:layer:AWSLambdaPowertoolsPython:17", + layer_version_arn=f"arn:aws:lambda:{env.region}:017000801446:layer:AWSLambdaPowertoolsPython:18", ) aws_lambda.Function( self, From 31fe45ec28d7ac9579d509351be214cabecd9c3e Mon Sep 17 00:00:00 2001 From: Simon Thulbourn Date: Thu, 28 Apr 2022 17:34:36 +0100 Subject: [PATCH 5/7] Revert "fix(parser): Add missing fields for SESEvent (#1027)" (#1190) This reverts commit 797a10afac80544e2d69bcb7d624909436f2b12a. --- .../utilities/parser/models/__init__.py | 8 -- .../utilities/parser/models/ses.py | 34 +----- tests/events/sesEventS3.json | 114 ------------------ tests/functional/parser/test_ses.py | 58 +-------- 4 files changed, 8 insertions(+), 206 deletions(-) delete mode 100644 tests/events/sesEventS3.json diff --git a/aws_lambda_powertools/utilities/parser/models/__init__.py b/aws_lambda_powertools/utilities/parser/models/__init__.py index 34c8e6ce6a1..e3fb50a2d5d 100644 --- a/aws_lambda_powertools/utilities/parser/models/__init__.py +++ b/aws_lambda_powertools/utilities/parser/models/__init__.py @@ -37,11 +37,7 @@ SesModel, SesReceipt, SesReceiptAction, - SesReceiptActionBase, - SesReceiptBounceAction, - SesReceiptS3Action, SesReceiptVerdict, - SesReceiptWorkmailAction, SesRecordModel, ) from .sns import SnsModel, SnsNotificationModel, SnsRecordModel @@ -88,10 +84,6 @@ "SesMailHeaders", "SesReceipt", "SesReceiptAction", - "SesReceiptActionBase", - "SesReceiptBounceAction", - "SesReceiptWorkmailAction", - "SesReceiptS3Action", "SesReceiptVerdict", "SnsModel", "SnsNotificationModel", diff --git a/aws_lambda_powertools/utilities/parser/models/ses.py b/aws_lambda_powertools/utilities/parser/models/ses.py index 7cd655ea28c..70fd2e83978 100644 --- a/aws_lambda_powertools/utilities/parser/models/ses.py +++ b/aws_lambda_powertools/utilities/parser/models/ses.py @@ -1,5 +1,5 @@ from datetime import datetime -from typing import List, Optional, Union +from typing import List, Optional from pydantic import BaseModel, Field from pydantic.networks import EmailStr @@ -12,38 +12,12 @@ class SesReceiptVerdict(BaseModel): status: Literal["PASS", "FAIL", "GRAY", "PROCESSING_FAILED"] -class SesReceiptActionBase(BaseModel): - topicArn: Optional[str] - - -class SesReceiptAction(SesReceiptActionBase): +class SesReceiptAction(BaseModel): type: Literal["Lambda"] # noqa A003,VNE003 invocationType: Literal["Event"] functionArn: str -class SesReceiptS3Action(SesReceiptActionBase): - type: Literal["S3"] # noqa A003,VNE003 - topicArn: str - bucketName: str - objectKey: str - - -class SesReceiptBounceAction(SesReceiptActionBase): - type: Literal["Bounce"] # noqa A003,VNE003 - topicArn: str - smtpReplyCode: str - message: str - sender: str - statusCode: str - - -class SesReceiptWorkmailAction(SesReceiptActionBase): - type: Literal["WorkMail"] # noqa A003,VNE003 - topicArn: str - organizationArn: str - - class SesReceipt(BaseModel): timestamp: datetime processingTimeMillis: PositiveInt @@ -51,10 +25,8 @@ class SesReceipt(BaseModel): spamVerdict: SesReceiptVerdict virusVerdict: SesReceiptVerdict spfVerdict: SesReceiptVerdict - dkimVerdict: SesReceiptVerdict dmarcVerdict: SesReceiptVerdict - dmarcPolicy: Optional[Literal["quarantine", "reject", "none"]] - action: Union[SesReceiptAction, SesReceiptS3Action, SesReceiptBounceAction, SesReceiptWorkmailAction] + action: SesReceiptAction class SesMailHeaders(BaseModel): diff --git a/tests/events/sesEventS3.json b/tests/events/sesEventS3.json deleted file mode 100644 index dbea2d42ce1..00000000000 --- a/tests/events/sesEventS3.json +++ /dev/null @@ -1,114 +0,0 @@ -{ - "Records": [ - { - "eventVersion": "1.0", - "ses": { - "receipt": { - "timestamp": "2015-09-11T20:32:33.936Z", - "processingTimeMillis": 406, - "recipients": [ - "recipient@example.com" - ], - "spamVerdict": { - "status": "PASS" - }, - "virusVerdict": { - "status": "PASS" - }, - "spfVerdict": { - "status": "PASS" - }, - "dkimVerdict": { - "status": "PASS" - }, - "dmarcVerdict": { - "status": "PASS" - }, - "dmarcPolicy": "reject", - "action": { - "type": "S3", - "topicArn": "arn:aws:sns:us-east-1:012345678912:example-topic", - "bucketName": "my-S3-bucket", - "objectKey": "email" - } - }, - "mail": { - "timestamp": "2015-09-11T20:32:33.936Z", - "source": "0000014fbe1c09cf-7cb9f704-7531-4e53-89a1-5fa9744f5eb6-000000@amazonses.com", - "messageId": "d6iitobk75ur44p8kdnnp7g2n800", - "destination": [ - "recipient@example.com" - ], - "headersTruncated": false, - "headers": [ - { - "name": "Return-Path", - "value": "<0000014fbe1c09cf-7cb9f704-7531-4e53-89a1-5fa9744f5eb6-000000@amazonses.com>" - }, - { - "name": "Received", - "value": "from a9-183.smtp-out.amazonses.com (a9-183.smtp-out.amazonses.com [54.240.9.183]) by inbound-smtp.us-east-1.amazonaws.com with SMTP id d6iitobk75ur44p8kdnnp7g2n800 for recipient@example.com; Fri, 11 Sep 2015 20:32:33 +0000 (UTC)" - }, - { - "name": "DKIM-Signature", - "value": "v=1; a=rsa-sha256; q=dns/txt; c=relaxed/simple; s=ug7nbtf4gccmlpwj322ax3p6ow6yfsug; d=amazonses.com; t=1442003552; h=From:To:Subject:MIME-Version:Content-Type:Content-Transfer-Encoding:Date:Message-ID:Feedback-ID; bh=DWr3IOmYWoXCA9ARqGC/UaODfghffiwFNRIb2Mckyt4=; b=p4ukUDSFqhqiub+zPR0DW1kp7oJZakrzupr6LBe6sUuvqpBkig56UzUwc29rFbJF hlX3Ov7DeYVNoN38stqwsF8ivcajXpQsXRC1cW9z8x875J041rClAjV7EGbLmudVpPX 4hHst1XPyX5wmgdHIhmUuh8oZKpVqGi6bHGzzf7g=" - }, - { - "name": "From", - "value": "sender@example.com" - }, - { - "name": "To", - "value": "recipient@example.com" - }, - { - "name": "Subject", - "value": "Example subject" - }, - { - "name": "MIME-Version", - "value": "1.0" - }, - { - "name": "Content-Type", - "value": "text/plain; charset=UTF-8" - }, - { - "name": "Content-Transfer-Encoding", - "value": "7bit" - }, - { - "name": "Date", - "value": "Fri, 11 Sep 2015 20:32:32 +0000" - }, - { - "name": "Message-ID", - "value": "<61967230-7A45-4A9D-BEC9-87CBCF2211C9@example.com>" - }, - { - "name": "X-SES-Outgoing", - "value": "2015.09.11-54.240.9.183" - }, - { - "name": "Feedback-ID", - "value": "1.us-east-1.Krv2FKpFdWV+KUYw3Qd6wcpPJ4Sv/pOPpEPSHn2u2o4=:AmazonSES" - } - ], - "commonHeaders": { - "returnPath": "0000014fbe1c09cf-7cb9f704-7531-4e53-89a1-5fa9744f5eb6-000000@amazonses.com", - "from": [ - "sender@example.com" - ], - "date": "Fri, 11 Sep 2015 20:32:32 +0000", - "to": [ - "recipient@example.com" - ], - "messageId": "<61967230-7A45-4A9D-BEC9-87CBCF2211C9@example.com>", - "subject": "Example subject" - } - } - }, - "eventSource": "aws:ses" - } - ] -} diff --git a/tests/functional/parser/test_ses.py b/tests/functional/parser/test_ses.py index 34a44253514..d434e2350f8 100644 --- a/tests/functional/parser/test_ses.py +++ b/tests/functional/parser/test_ses.py @@ -1,22 +1,11 @@ from aws_lambda_powertools.utilities.parser import event_parser -from aws_lambda_powertools.utilities.parser.models import ( - SesModel, - SesReceiptBounceAction, - SesReceiptWorkmailAction, - SesRecordModel, -) +from aws_lambda_powertools.utilities.parser.models import SesModel, SesRecordModel from aws_lambda_powertools.utilities.typing import LambdaContext from tests.functional.utils import load_event @event_parser(model=SesModel) -def handle_ses(event: SesModel, _: LambdaContext) -> SesModel: - return event - - -def test_ses_trigger_lambda_event(): - event_dict = load_event("sesEvent.json") - event = handle_ses(event_dict, LambdaContext()) +def handle_ses(event: SesModel, _: LambdaContext): expected_address = "johndoe@example.com" records = event.Records record: SesRecordModel = records[0] @@ -40,10 +29,6 @@ def test_ses_trigger_lambda_event(): assert common_headers.to == [expected_address] assert common_headers.messageId == "<0123456789example.com>" assert common_headers.subject == "Test Subject" - assert common_headers.cc is None - assert common_headers.bcc is None - assert common_headers.sender is None - assert common_headers.reply_to is None receipt = record.ses.receipt convert_time = int(round(receipt.timestamp.timestamp() * 1000)) assert convert_time == 0 @@ -53,45 +38,12 @@ def test_ses_trigger_lambda_event(): assert receipt.virusVerdict.status == "PASS" assert receipt.spfVerdict.status == "PASS" assert receipt.dmarcVerdict.status == "PASS" - assert receipt.dmarcVerdict.status == "PASS" - assert receipt.dmarcPolicy is None action = receipt.action assert action.type == "Lambda" assert action.functionArn == "arn:aws:lambda:us-west-2:012345678912:function:Example" assert action.invocationType == "Event" - assert action.topicArn is None - -def test_ses_trigger_event_s3(): - event_dict = load_event("sesEventS3.json") - event = handle_ses(event_dict, LambdaContext()) - records = list(event.Records) - record = records[0] - receipt = record.ses.receipt - assert receipt.dmarcPolicy == "reject" - action = record.ses.receipt.action - assert action.type == "S3" - assert action.topicArn == "arn:aws:sns:us-east-1:012345678912:example-topic" - assert action.bucketName == "my-S3-bucket" - assert action.objectKey == "email" - - -def test_ses_trigger_event_bounce(): - event_dict = { - "type": "Bounce", - "topicArn": "arn:aws:sns:us-east-1:123456789012:topic:my-topic", - "smtpReplyCode": "5.1.1", - "message": "message", - "sender": "sender", - "statusCode": "550", - } - SesReceiptBounceAction(**event_dict) - -def test_ses_trigger_event_work_mail(): - event_dict = { - "type": "WorkMail", - "topicArn": "arn:aws:sns:us-east-1:123456789012:topic:my-topic", - "organizationArn": "arn", - } - SesReceiptWorkmailAction(**event_dict) +def test_ses_trigger_event(): + event_dict = load_event("sesEvent.json") + handle_ses(event_dict, LambdaContext()) From 3b137f75b9fa4fdfe3e6a3d2bdb94e503e566ccf Mon Sep 17 00:00:00 2001 From: Michael Brewer Date: Mon, 13 Jun 2022 14:36:47 -0700 Subject: [PATCH 6/7] chore: update to layer version 1.26.1 --- docs/examples/index/lambda_layer_cdk_app.py | 2 +- docs/examples/index/lambda_layer_main.tf | 2 +- docs/examples/index/lambda_layer_template.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/examples/index/lambda_layer_cdk_app.py b/docs/examples/index/lambda_layer_cdk_app.py index 0ed27628b28..e13332aa235 100644 --- a/docs/examples/index/lambda_layer_cdk_app.py +++ b/docs/examples/index/lambda_layer_cdk_app.py @@ -8,7 +8,7 @@ def __init__(self, scope: core.Construct, id_: str, env: core.Environment) -> No powertools_layer = aws_lambda.LayerVersion.from_layer_version_arn( self, id="lambda-powertools", - layer_version_arn=f"arn:aws:lambda:{env.region}:017000801446:layer:AWSLambdaPowertoolsPython:19", + layer_version_arn=f"arn:aws:lambda:{env.region}:017000801446:layer:AWSLambdaPowertoolsPython:20", ) aws_lambda.Function( self, diff --git a/docs/examples/index/lambda_layer_main.tf b/docs/examples/index/lambda_layer_main.tf index 0d61f13f164..0c4b44e5e08 100644 --- a/docs/examples/index/lambda_layer_main.tf +++ b/docs/examples/index/lambda_layer_main.tf @@ -32,7 +32,7 @@ resource "aws_lambda_function" "test_lambda" { role = aws_iam_role.iam_for_lambda.arn handler = "index.test" runtime = "python3.9" - layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPython:19"] + layers = ["arn:aws:lambda:{region}:017000801446:layer:AWSLambdaPowertoolsPython:20"] source_code_hash = filebase64sha256("lambda_function_payload.zip") } diff --git a/docs/examples/index/lambda_layer_template.yml b/docs/examples/index/lambda_layer_template.yml index 2a769595cf0..ac81b62e54f 100644 --- a/docs/examples/index/lambda_layer_template.yml +++ b/docs/examples/index/lambda_layer_template.yml @@ -8,4 +8,4 @@ Resources: Handler: app.lambda_handler Runtime: python3.9 Layers: - - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPython:19 + - !Sub arn:aws:lambda:${AWS::Region}:017000801446:layer:AWSLambdaPowertoolsPython:20 From 2a480b62b5db9d97fbdff92b58b82772a4b67976 Mon Sep 17 00:00:00 2001 From: Michael Brewer Date: Mon, 13 Jun 2022 14:46:42 -0700 Subject: [PATCH 7/7] chore: update to SAR version 1.26.1 --- docs/examples/index/sar_cdk_app.py | 2 +- docs/examples/index/sar_main.tf | 2 +- docs/examples/index/sar_template.yml | 2 +- docs/index.md | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/examples/index/sar_cdk_app.py b/docs/examples/index/sar_cdk_app.py index 93e403b849d..6c6068a9104 100644 --- a/docs/examples/index/sar_cdk_app.py +++ b/docs/examples/index/sar_cdk_app.py @@ -4,7 +4,7 @@ POWERTOOLS_BASE_NAME = "AWSLambdaPowertools" # Find latest from github.com/awslabs/aws-lambda-powertools-python/releases -POWERTOOLS_VER = "1.25.10" +POWERTOOLS_VER = "1.26.1" POWERTOOLS_ARN = "arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer" diff --git a/docs/examples/index/sar_main.tf b/docs/examples/index/sar_main.tf index 4b9c2173978..53625ceb641 100644 --- a/docs/examples/index/sar_main.tf +++ b/docs/examples/index/sar_main.tf @@ -27,7 +27,7 @@ data "aws_serverlessapplicationrepository_application" "sar_app" { variable "aws_powertools_version" { type = string - default = "1.25.10" + default = "1.26.1" description = "The AWS Powertools release version" } diff --git a/docs/examples/index/sar_template.yml b/docs/examples/index/sar_template.yml index 93af5818f41..a031bcdbbad 100644 --- a/docs/examples/index/sar_template.yml +++ b/docs/examples/index/sar_template.yml @@ -6,7 +6,7 @@ Resources: Properties: Location: ApplicationId: arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer - SemanticVersion: 1.25.10 # change to latest semantic version available in SAR + SemanticVersion: 1.26.1 # change to latest semantic version available in SAR MyLambdaFunction: Type: AWS::Serverless::Function diff --git a/docs/index.md b/docs/index.md index 8baa28ff91a..886586024b7 100644 --- a/docs/index.md +++ b/docs/index.md @@ -166,7 +166,7 @@ If using SAM, you can include this SAR App as part of your shared Layers stack, Location: ApplicationId: arn:aws:serverlessrepo:eu-west-1:057560766410:applications/aws-lambda-powertools-python-layer # Find latest from github.com/awslabs/aws-lambda-powertools-python/releases - SemanticVersion: 1.25.10 + SemanticVersion: 1.26.1 ``` === "CDK"