diff --git a/packages/@aws-cdk/aws-lambda-event-sources/lib/sqs.ts b/packages/@aws-cdk/aws-lambda-event-sources/lib/sqs.ts index c6cba08abd13d..fb416a727655e 100644 --- a/packages/@aws-cdk/aws-lambda-event-sources/lib/sqs.ts +++ b/packages/@aws-cdk/aws-lambda-event-sources/lib/sqs.ts @@ -39,6 +39,13 @@ export interface SqsEventSourceProps { * @default true */ readonly enabled?: boolean; + + /** + * Add filter criteria option + * + * @default - None + */ + readonly filters?: Array<{[key: string]: any}>; } /** @@ -73,6 +80,7 @@ export class SqsEventSource implements lambda.IEventSource { reportBatchItemFailures: this.props.reportBatchItemFailures, enabled: this.props.enabled, eventSourceArn: this.queue.queueArn, + filters: this.props.filters, }); this._eventSourceMappingId = eventSourceMapping.eventSourceMappingId; diff --git a/packages/@aws-cdk/aws-lambda-event-sources/lib/stream.ts b/packages/@aws-cdk/aws-lambda-event-sources/lib/stream.ts index e8f7f2a40de3e..acf0f55cb793d 100644 --- a/packages/@aws-cdk/aws-lambda-event-sources/lib/stream.ts +++ b/packages/@aws-cdk/aws-lambda-event-sources/lib/stream.ts @@ -107,6 +107,13 @@ export interface StreamEventSourceProps extends BaseStreamEventSourceProps { * @default - discarded records are ignored */ readonly onFailure?: lambda.IEventSourceDlq; + + /** + * Add filter criteria option + * + * @default - None + */ + readonly filters?: Array<{[key: string]: any}>; } /** @@ -132,6 +139,7 @@ export abstract class StreamEventSource implements lambda.IEventSource { onFailure: this.props.onFailure, tumblingWindow: this.props.tumblingWindow, enabled: this.props.enabled, + filters: this.props.filters, }; } } diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamo.test.ts b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamo.test.ts index a4b210156aae6..214ea8612274b 100644 --- a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamo.test.ts +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamo.test.ts @@ -243,6 +243,57 @@ describe('DynamoEventSource', () => { }); + test('adding filter criteria', () => { + // GIVEN + const stack = new cdk.Stack(); + const fn = new TestFunction(stack, 'Fn'); + const table = new dynamodb.Table(stack, 'T', { + partitionKey: { + name: 'id', + type: dynamodb.AttributeType.STRING, + }, + stream: dynamodb.StreamViewType.NEW_IMAGE, + }); + + // WHEN + fn.addEventSource(new sources.DynamoEventSource(table, { + startingPosition: lambda.StartingPosition.LATEST, + filters: [ + lambda.FilterCriteria.filter({ + eventName: lambda.FilterRule.isEqual('INSERT'), + dynamodb: { + Keys: { + id: { + S: lambda.FilterRule.exists(), + }, + }, + }, + }), + ], + })); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::EventSourceMapping', { + 'EventSourceArn': { + 'Fn::GetAtt': [ + 'TD925BC7E', + 'StreamArn', + ], + }, + 'FunctionName': { + 'Ref': 'Fn9270CBC0', + }, + 'FilterCriteria': { + 'Filters': [ + { + 'Pattern': '{"eventName":["INSERT"],"dynamodb":{"Keys":{"id":{"S":[{"exists":true}]}}}}', + }, + ], + }, + 'StartingPosition': 'LATEST', + }); + }); + test('specific maxBatchingWindow', () => { // GIVEN const stack = new cdk.Stack(); diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.assets.json b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.assets.json new file mode 100644 index 0000000000000..7bbad778ecd94 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.template.json b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/cdk.out new file mode 100644 index 0000000000000..8ecc185e9dbee --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/integ.json b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/integ.json new file mode 100644 index 0000000000000..b6cc14632ae83 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "21.0.0", + "testCases": { + "DynamoDBFilterCriteria/DefaultTest": { + "stacks": [ + "lambda-event-source-filter-criteria-dynamodb" + ], + "assertionStack": "DynamoDBFilterCriteria/DefaultTest/DeployAssert", + "assertionStackName": "DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-dynamodb.assets.json b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-dynamodb.assets.json new file mode 100644 index 0000000000000..ab5dd103772f8 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-dynamodb.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "8ddecd300b64f1e8196cec45f3e0f752e4a04060a8cd32fbcd88c192b14499fc": { + "source": { + "path": "lambda-event-source-filter-criteria-dynamodb.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "8ddecd300b64f1e8196cec45f3e0f752e4a04060a8cd32fbcd88c192b14499fc.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-dynamodb.template.json b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-dynamodb.template.json new file mode 100644 index 0000000000000..5d859d58bc0bf --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-dynamodb.template.json @@ -0,0 +1,173 @@ +{ + "Resources": { + "FServiceRole3AC82EE1": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "FServiceRoleDefaultPolicy17A19BFA": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": "dynamodb:ListStreams", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "dynamodb:DescribeStream", + "dynamodb:GetRecords", + "dynamodb:GetShardIterator" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "TD925BC7E", + "StreamArn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "FServiceRoleDefaultPolicy17A19BFA", + "Roles": [ + { + "Ref": "FServiceRole3AC82EE1" + } + ] + } + }, + "FC4345940": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = async function handler(event) {\n console.log('event:', JSON.stringify(event, undefined, 2));\n return { event };\n}" + }, + "Role": { + "Fn::GetAtt": [ + "FServiceRole3AC82EE1", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "FServiceRoleDefaultPolicy17A19BFA", + "FServiceRole3AC82EE1" + ] + }, + "FDynamoDBEventSourcelambdaeventsourcefiltercriteriadynamodbT9CFE7D0657833F11": { + "Type": "AWS::Lambda::EventSourceMapping", + "Properties": { + "FunctionName": { + "Ref": "FC4345940" + }, + "BatchSize": 5, + "EventSourceArn": { + "Fn::GetAtt": [ + "TD925BC7E", + "StreamArn" + ] + }, + "FilterCriteria": { + "Filters": [ + { + "Pattern": "{\"eventName\":[\"INSERT\"],\"dynamodb\":{\"Keys\":{\"id\":{\"S\":[{\"exists\":true}]}}}}" + } + ] + }, + "StartingPosition": "LATEST" + } + }, + "TD925BC7E": { + "Type": "AWS::DynamoDB::Table", + "Properties": { + "KeySchema": [ + { + "AttributeName": "id", + "KeyType": "HASH" + } + ], + "AttributeDefinitions": [ + { + "AttributeName": "id", + "AttributeType": "S" + } + ], + "ProvisionedThroughput": { + "ReadCapacityUnits": 5, + "WriteCapacityUnits": 5 + }, + "StreamSpecification": { + "StreamViewType": "NEW_IMAGE" + } + }, + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/manifest.json new file mode 100644 index 0000000000000..40f80338882b3 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/manifest.json @@ -0,0 +1,135 @@ +{ + "version": "21.0.0", + "artifacts": { + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "lambda-event-source-filter-criteria-dynamodb.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "lambda-event-source-filter-criteria-dynamodb.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "lambda-event-source-filter-criteria-dynamodb": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "lambda-event-source-filter-criteria-dynamodb.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/8ddecd300b64f1e8196cec45f3e0f752e4a04060a8cd32fbcd88c192b14499fc.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "lambda-event-source-filter-criteria-dynamodb.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "lambda-event-source-filter-criteria-dynamodb.assets" + ], + "metadata": { + "/lambda-event-source-filter-criteria-dynamodb/F/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FServiceRole3AC82EE1" + } + ], + "/lambda-event-source-filter-criteria-dynamodb/F/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FServiceRoleDefaultPolicy17A19BFA" + } + ], + "/lambda-event-source-filter-criteria-dynamodb/F/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FC4345940" + } + ], + "/lambda-event-source-filter-criteria-dynamodb/F/DynamoDBEventSource:lambdaeventsourcefiltercriteriadynamodbT9CFE7D06/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FDynamoDBEventSourcelambdaeventsourcefiltercriteriadynamodbT9CFE7D0657833F11" + } + ], + "/lambda-event-source-filter-criteria-dynamodb/T/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "TD925BC7E" + } + ], + "/lambda-event-source-filter-criteria-dynamodb/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/lambda-event-source-filter-criteria-dynamodb/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "lambda-event-source-filter-criteria-dynamodb" + }, + "DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "DynamoDBFilterCriteriaDefaultTestDeployAssert448231D5.assets" + ], + "metadata": { + "/DynamoDBFilterCriteria/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/DynamoDBFilterCriteria/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "DynamoDBFilterCriteria/DefaultTest/DeployAssert" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/tree.json b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/tree.json new file mode 100644 index 0000000000000..17aee7db14441 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/dynamodb-with-filter-criteria.integ.snapshot/tree.json @@ -0,0 +1,294 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.92" + } + }, + "lambda-event-source-filter-criteria-dynamodb": { + "id": "lambda-event-source-filter-criteria-dynamodb", + "path": "lambda-event-source-filter-criteria-dynamodb", + "children": { + "F": { + "id": "F", + "path": "lambda-event-source-filter-criteria-dynamodb/F", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "lambda-event-source-filter-criteria-dynamodb/F/ServiceRole", + "children": { + "Resource": { + "id": "Resource", + "path": "lambda-event-source-filter-criteria-dynamodb/F/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "lambda-event-source-filter-criteria-dynamodb/F/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "lambda-event-source-filter-criteria-dynamodb/F/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": "dynamodb:ListStreams", + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "dynamodb:DescribeStream", + "dynamodb:GetRecords", + "dynamodb:GetShardIterator" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "TD925BC7E", + "StreamArn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "FServiceRoleDefaultPolicy17A19BFA", + "roles": [ + { + "Ref": "FServiceRole3AC82EE1" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "lambda-event-source-filter-criteria-dynamodb/F/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "exports.handler = async function handler(event) {\n console.log('event:', JSON.stringify(event, undefined, 2));\n return { event };\n}" + }, + "role": { + "Fn::GetAtt": [ + "FServiceRole3AC82EE1", + "Arn" + ] + }, + "handler": "index.handler", + "runtime": "nodejs14.x" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + }, + "DynamoDBEventSource:lambdaeventsourcefiltercriteriadynamodbT9CFE7D06": { + "id": "DynamoDBEventSource:lambdaeventsourcefiltercriteriadynamodbT9CFE7D06", + "path": "lambda-event-source-filter-criteria-dynamodb/F/DynamoDBEventSource:lambdaeventsourcefiltercriteriadynamodbT9CFE7D06", + "children": { + "Resource": { + "id": "Resource", + "path": "lambda-event-source-filter-criteria-dynamodb/F/DynamoDBEventSource:lambdaeventsourcefiltercriteriadynamodbT9CFE7D06/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::EventSourceMapping", + "aws:cdk:cloudformation:props": { + "functionName": { + "Ref": "FC4345940" + }, + "batchSize": 5, + "eventSourceArn": { + "Fn::GetAtt": [ + "TD925BC7E", + "StreamArn" + ] + }, + "filterCriteria": { + "filters": [ + { + "pattern": "{\"eventName\":[\"INSERT\"],\"dynamodb\":{\"Keys\":{\"id\":{\"S\":[{\"exists\":true}]}}}}" + } + ] + }, + "startingPosition": "LATEST" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnEventSourceMapping", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.EventSourceMapping", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + }, + "T": { + "id": "T", + "path": "lambda-event-source-filter-criteria-dynamodb/T", + "children": { + "Resource": { + "id": "Resource", + "path": "lambda-event-source-filter-criteria-dynamodb/T/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::DynamoDB::Table", + "aws:cdk:cloudformation:props": { + "keySchema": [ + { + "attributeName": "id", + "keyType": "HASH" + } + ], + "attributeDefinitions": [ + { + "attributeName": "id", + "attributeType": "S" + } + ], + "provisionedThroughput": { + "readCapacityUnits": 5, + "writeCapacityUnits": 5 + }, + "streamSpecification": { + "streamViewType": "NEW_IMAGE" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-dynamodb.CfnTable", + "version": "0.0.0" + } + }, + "ScalingRole": { + "id": "ScalingRole", + "path": "lambda-event-source-filter-criteria-dynamodb/T/ScalingRole", + "constructInfo": { + "fqn": "@aws-cdk/core.Resource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-dynamodb.Table", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "DynamoDBFilterCriteria": { + "id": "DynamoDBFilterCriteria", + "path": "DynamoDBFilterCriteria", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "DynamoDBFilterCriteria/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "DynamoDBFilterCriteria/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.92" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "DynamoDBFilterCriteria/DefaultTest/DeployAssert", + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/integ.dynamodb-with-filter-criteria.ts b/packages/@aws-cdk/aws-lambda-event-sources/test/integ.dynamodb-with-filter-criteria.ts new file mode 100644 index 0000000000000..082964ef26518 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/integ.dynamodb-with-filter-criteria.ts @@ -0,0 +1,43 @@ +import * as dynamodb from '@aws-cdk/aws-dynamodb'; +import * as lambda from '@aws-cdk/aws-lambda'; +import * as cdk from '@aws-cdk/core'; +import * as integ from '@aws-cdk/integ-tests'; +import { DynamoEventSource } from '../lib'; +import { TestFunction } from './test-function'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'lambda-event-source-filter-criteria-dynamodb'); + +const fn = new TestFunction(stack, 'F'); +const table = new dynamodb.Table(stack, 'T', { + partitionKey: { + name: 'id', + type: dynamodb.AttributeType.STRING, + }, + stream: dynamodb.StreamViewType.NEW_IMAGE, + removalPolicy: cdk.RemovalPolicy.DESTROY, +}); + +fn.addEventSource(new DynamoEventSource(table, { + batchSize: 5, + startingPosition: lambda.StartingPosition.LATEST, + filters: [ + lambda.FilterCriteria.filter({ + eventName: lambda.FilterRule.isEqual('INSERT'), + dynamodb: { + Keys: { + id: { + S: lambda.FilterRule.exists(), + }, + }, + }, + }), + ], +})); + +new integ.IntegTest(app, 'DynamoDBFilterCriteria', { + testCases: [stack], +}); + +app.synth(); diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/integ.sqs-with-filter-criteria.ts b/packages/@aws-cdk/aws-lambda-event-sources/test/integ.sqs-with-filter-criteria.ts new file mode 100644 index 0000000000000..b180736709fe9 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/integ.sqs-with-filter-criteria.ts @@ -0,0 +1,30 @@ +import * as lambda from '@aws-cdk/aws-lambda'; +import * as sqs from '@aws-cdk/aws-sqs'; +import * as cdk from '@aws-cdk/core'; +import * as integ from '@aws-cdk/integ-tests'; +import { SqsEventSource } from '../lib'; +import { TestFunction } from './test-function'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'lambda-event-source-filter-criteria-sqs'); + +const fn = new TestFunction(stack, 'F'); +const queue = new sqs.Queue(stack, 'Q'); + +fn.addEventSource(new SqsEventSource(queue, { + batchSize: 5, + filters: [ + lambda.FilterCriteria.filter({ + body: { + id: lambda.FilterRule.exists(), + }, + }), + ], +})); + +new integ.IntegTest(app, 'SQSFilterCriteria', { + testCases: [stack], +}); + +app.synth(); \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/SQSFilterCriteriaDefaultTestDeployAssert70A9A808.assets.json b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/SQSFilterCriteriaDefaultTestDeployAssert70A9A808.assets.json new file mode 100644 index 0000000000000..d64b21f030971 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/SQSFilterCriteriaDefaultTestDeployAssert70A9A808.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "SQSFilterCriteriaDefaultTestDeployAssert70A9A808.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/SQSFilterCriteriaDefaultTestDeployAssert70A9A808.template.json b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/SQSFilterCriteriaDefaultTestDeployAssert70A9A808.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/SQSFilterCriteriaDefaultTestDeployAssert70A9A808.template.json @@ -0,0 +1,36 @@ +{ + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/cdk.out b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/cdk.out new file mode 100644 index 0000000000000..8ecc185e9dbee --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/integ.json b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/integ.json new file mode 100644 index 0000000000000..2026729f3374b --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "21.0.0", + "testCases": { + "SQSFilterCriteria/DefaultTest": { + "stacks": [ + "lambda-event-source-filter-criteria-sqs" + ], + "assertionStack": "SQSFilterCriteria/DefaultTest/DeployAssert", + "assertionStackName": "SQSFilterCriteriaDefaultTestDeployAssert70A9A808" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-sqs.assets.json b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-sqs.assets.json new file mode 100644 index 0000000000000..af98b5f96579d --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-sqs.assets.json @@ -0,0 +1,19 @@ +{ + "version": "21.0.0", + "files": { + "879ea05cb693492da58c7a50d14e304f03f420185f19e668345fbee2bcf9fe44": { + "source": { + "path": "lambda-event-source-filter-criteria-sqs.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "879ea05cb693492da58c7a50d14e304f03f420185f19e668345fbee2bcf9fe44.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-sqs.template.json b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-sqs.template.json new file mode 100644 index 0000000000000..07811e3edcdbc --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/lambda-event-source-filter-criteria-sqs.template.json @@ -0,0 +1,148 @@ +{ + "Resources": { + "FServiceRole3AC82EE1": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "FServiceRoleDefaultPolicy17A19BFA": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "sqs:ChangeMessageVisibility", + "sqs:DeleteMessage", + "sqs:GetQueueAttributes", + "sqs:GetQueueUrl", + "sqs:ReceiveMessage" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "Q63C6E3AB", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "FServiceRoleDefaultPolicy17A19BFA", + "Roles": [ + { + "Ref": "FServiceRole3AC82EE1" + } + ] + } + }, + "FC4345940": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "ZipFile": "exports.handler = async function handler(event) {\n console.log('event:', JSON.stringify(event, undefined, 2));\n return { event };\n}" + }, + "Role": { + "Fn::GetAtt": [ + "FServiceRole3AC82EE1", + "Arn" + ] + }, + "Handler": "index.handler", + "Runtime": "nodejs14.x" + }, + "DependsOn": [ + "FServiceRoleDefaultPolicy17A19BFA", + "FServiceRole3AC82EE1" + ] + }, + "FSqsEventSourcelambdaeventsourcefiltercriteriasqsQA0FC5C93EBF98B38": { + "Type": "AWS::Lambda::EventSourceMapping", + "Properties": { + "FunctionName": { + "Ref": "FC4345940" + }, + "BatchSize": 5, + "EventSourceArn": { + "Fn::GetAtt": [ + "Q63C6E3AB", + "Arn" + ] + }, + "FilterCriteria": { + "Filters": [ + { + "Pattern": "{\"body\":{\"id\":[{\"exists\":true}]}}" + } + ] + } + } + }, + "Q63C6E3AB": { + "Type": "AWS::SQS::Queue", + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/manifest.json b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/manifest.json new file mode 100644 index 0000000000000..37b440978a5bb --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/manifest.json @@ -0,0 +1,135 @@ +{ + "version": "21.0.0", + "artifacts": { + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "lambda-event-source-filter-criteria-sqs.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "lambda-event-source-filter-criteria-sqs.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "lambda-event-source-filter-criteria-sqs": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "lambda-event-source-filter-criteria-sqs.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/879ea05cb693492da58c7a50d14e304f03f420185f19e668345fbee2bcf9fe44.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "lambda-event-source-filter-criteria-sqs.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "lambda-event-source-filter-criteria-sqs.assets" + ], + "metadata": { + "/lambda-event-source-filter-criteria-sqs/F/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FServiceRole3AC82EE1" + } + ], + "/lambda-event-source-filter-criteria-sqs/F/ServiceRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FServiceRoleDefaultPolicy17A19BFA" + } + ], + "/lambda-event-source-filter-criteria-sqs/F/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FC4345940" + } + ], + "/lambda-event-source-filter-criteria-sqs/F/SqsEventSource:lambdaeventsourcefiltercriteriasqsQA0FC5C93/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FSqsEventSourcelambdaeventsourcefiltercriteriasqsQA0FC5C93EBF98B38" + } + ], + "/lambda-event-source-filter-criteria-sqs/Q/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Q63C6E3AB" + } + ], + "/lambda-event-source-filter-criteria-sqs/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/lambda-event-source-filter-criteria-sqs/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "lambda-event-source-filter-criteria-sqs" + }, + "SQSFilterCriteriaDefaultTestDeployAssert70A9A808.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "SQSFilterCriteriaDefaultTestDeployAssert70A9A808.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "SQSFilterCriteriaDefaultTestDeployAssert70A9A808": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "SQSFilterCriteriaDefaultTestDeployAssert70A9A808.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "SQSFilterCriteriaDefaultTestDeployAssert70A9A808.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "SQSFilterCriteriaDefaultTestDeployAssert70A9A808.assets" + ], + "metadata": { + "/SQSFilterCriteria/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/SQSFilterCriteria/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "SQSFilterCriteria/DefaultTest/DeployAssert" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/tree.json b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/tree.json new file mode 100644 index 0000000000000..0655a941d1334 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs-with-filter-criteria.integ.snapshot/tree.json @@ -0,0 +1,262 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.92" + } + }, + "lambda-event-source-filter-criteria-sqs": { + "id": "lambda-event-source-filter-criteria-sqs", + "path": "lambda-event-source-filter-criteria-sqs", + "children": { + "F": { + "id": "F", + "path": "lambda-event-source-filter-criteria-sqs/F", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "lambda-event-source-filter-criteria-sqs/F/ServiceRole", + "children": { + "Resource": { + "id": "Resource", + "path": "lambda-event-source-filter-criteria-sqs/F/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "lambda-event-source-filter-criteria-sqs/F/ServiceRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "lambda-event-source-filter-criteria-sqs/F/ServiceRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "sqs:ChangeMessageVisibility", + "sqs:DeleteMessage", + "sqs:GetQueueAttributes", + "sqs:GetQueueUrl", + "sqs:ReceiveMessage" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "Q63C6E3AB", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "FServiceRoleDefaultPolicy17A19BFA", + "roles": [ + { + "Ref": "FServiceRole3AC82EE1" + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "lambda-event-source-filter-criteria-sqs/F/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "zipFile": "exports.handler = async function handler(event) {\n console.log('event:', JSON.stringify(event, undefined, 2));\n return { event };\n}" + }, + "role": { + "Fn::GetAtt": [ + "FServiceRole3AC82EE1", + "Arn" + ] + }, + "handler": "index.handler", + "runtime": "nodejs14.x" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + }, + "SqsEventSource:lambdaeventsourcefiltercriteriasqsQA0FC5C93": { + "id": "SqsEventSource:lambdaeventsourcefiltercriteriasqsQA0FC5C93", + "path": "lambda-event-source-filter-criteria-sqs/F/SqsEventSource:lambdaeventsourcefiltercriteriasqsQA0FC5C93", + "children": { + "Resource": { + "id": "Resource", + "path": "lambda-event-source-filter-criteria-sqs/F/SqsEventSource:lambdaeventsourcefiltercriteriasqsQA0FC5C93/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::EventSourceMapping", + "aws:cdk:cloudformation:props": { + "functionName": { + "Ref": "FC4345940" + }, + "batchSize": 5, + "eventSourceArn": { + "Fn::GetAtt": [ + "Q63C6E3AB", + "Arn" + ] + }, + "filterCriteria": { + "filters": [ + { + "pattern": "{\"body\":{\"id\":[{\"exists\":true}]}}" + } + ] + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnEventSourceMapping", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.EventSourceMapping", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + }, + "Q": { + "id": "Q", + "path": "lambda-event-source-filter-criteria-sqs/Q", + "children": { + "Resource": { + "id": "Resource", + "path": "lambda-event-source-filter-criteria-sqs/Q/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SQS::Queue", + "aws:cdk:cloudformation:props": {} + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sqs.CfnQueue", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-sqs.Queue", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + }, + "SQSFilterCriteria": { + "id": "SQSFilterCriteria", + "path": "SQSFilterCriteria", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "SQSFilterCriteria/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "SQSFilterCriteria/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.92" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "SQSFilterCriteria/DefaultTest/DeployAssert", + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests.IntegTest", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda-event-sources/test/sqs.test.ts b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs.test.ts index 0f019671460af..e84e2c87e9f17 100644 --- a/packages/@aws-cdk/aws-lambda-event-sources/test/sqs.test.ts +++ b/packages/@aws-cdk/aws-lambda-event-sources/test/sqs.test.ts @@ -1,4 +1,5 @@ import { Template } from '@aws-cdk/assertions'; +import * as lambda from '@aws-cdk/aws-lambda'; import * as sqs from '@aws-cdk/aws-sqs'; import * as cdk from '@aws-cdk/core'; import * as sources from '../lib'; @@ -284,4 +285,33 @@ describe('SQSEventSource', () => { }); + + test('adding filter criteria', () => { + // GIVEN + const stack = new cdk.Stack(); + const fn = new TestFunction(stack, 'Fn'); + const q = new sqs.Queue(stack, 'Q'); + + // WHEN + fn.addEventSource(new sources.SqsEventSource(q, { + filters: [ + lambda.FilterCriteria.filter({ + body: { + id: lambda.FilterRule.exists(), + }, + }), + ], + })); + + // THEN + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::EventSourceMapping', { + 'FilterCriteria': { + 'Filters': [ + { + 'Pattern': '{"body":{"id":[{"exists":true}]}}', + }, + ], + }, + }); + }); }); diff --git a/packages/@aws-cdk/aws-lambda/README.md b/packages/@aws-cdk/aws-lambda/README.md index f12afc0c3d809..d5644331cec0d 100644 --- a/packages/@aws-cdk/aws-lambda/README.md +++ b/packages/@aws-cdk/aws-lambda/README.md @@ -632,6 +632,26 @@ fn.addEventSource(new eventsources.S3EventSource(bucket, { })); ``` +The following code adds an DynamoDB notification as an event source filtering insert events: + +```ts +import * as eventsources from '@aws-cdk/aws-lambda-event-sources'; +import * as dynamodb from '@aws-cdk/aws-dynamodb'; + +declare const fn: lambda.Function; +const table = new dynamodb.Table(this, 'Table', { + partitionKey: { + name: 'id', + type: dynamodb.AttributeType.STRING, + }, + stream: dynamodb.StreamViewType.NEW_IMAGE, +}); +fn.addEventSource(new eventsources.DynamoEventSource(table, { + startingPosition: lambda.StartingPosition.LATEST, + filters: [{ eventName: lambda.FilterRule.isEqual('INSERT') }], +})); +``` + See the documentation for the __@aws-cdk/aws-lambda-event-sources__ module for more details. ## Imported Lambdas diff --git a/packages/@aws-cdk/aws-lambda/lib/event-source-filter.ts b/packages/@aws-cdk/aws-lambda/lib/event-source-filter.ts new file mode 100644 index 0000000000000..50bce839123ba --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/lib/event-source-filter.ts @@ -0,0 +1,82 @@ +/** + * Filter rules for Lambda event filtering + */ +export class FilterRule { + /** + * Null comparison operator + */ + public static null(): string[] { + return []; + } + + /** + * Empty comparison operator + */ + public static empty(): string[] { + return ['']; + } + + /** + * Equals comparison operator + */ + public static isEqual(item: string | number): any { + if (typeof item === 'number') { + return [{ numeric: ['=', item] }]; + } + return [item]; + } + + /** + * Or comparison operator + */ + public static or(...elem: string[]): string[] { + return elem; + } + + /** + * Not equals comparison operator + */ + public static notEquals(elem: string): {[key:string]: string[]}[] { + return [{ 'anything-but': [elem] }]; + } + + /** + * Numeric range comparison operator + */ + public static between(first: number, second: number): {[key:string]: any[]}[] { + return [{ numeric: ['>', first, '<=', second] }]; + } + + /** + * Exists comparison operator + */ + public static exists(): {[key:string]: boolean}[] { + return [{ exists: true }]; + } + + /** + * Not exists comparison operator + */ + public static notExists(): {[key:string]: boolean}[] { + return [{ exists: false }]; + } + + /** + * Begins with comparison operator + */ + public static beginsWith(elem: string): {[key:string]: string}[] { + return [{ prefix: elem }]; + } +} + +/** + * Filter criteria for Lambda event filtering + */ +export class FilterCriteria { + /** + * Filter for event source + */ + public static filter(filter: {[key:string]: any}): {[key:string]: any} { + return { pattern: JSON.stringify(filter) }; + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/lib/event-source-mapping.ts b/packages/@aws-cdk/aws-lambda/lib/event-source-mapping.ts index 08e43ca31e310..9798a31c313f0 100644 --- a/packages/@aws-cdk/aws-lambda/lib/event-source-mapping.ts +++ b/packages/@aws-cdk/aws-lambda/lib/event-source-mapping.ts @@ -232,6 +232,14 @@ export interface EventSourceMappingOptions { * @default - none */ readonly sourceAccessConfigurations?: SourceAccessConfiguration[] + + /** + * Add filter criteria to Event Source + * @see https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventfiltering.html + * + * @default - none + */ + readonly filters?: Array<{[key: string]: any}> } /** @@ -366,6 +374,7 @@ export class EventSourceMapping extends cdk.Resource implements IEventSourceMapp tumblingWindowInSeconds: props.tumblingWindow?.toSeconds(), sourceAccessConfigurations: props.sourceAccessConfigurations?.map((o) => {return { type: o.type.type, uri: o.uri };}), selfManagedEventSource, + filterCriteria: props.filters ? { filters: props.filters }: undefined, selfManagedKafkaEventSourceConfig: props.kafkaBootstrapServers ? consumerGroupConfig : undefined, amazonManagedKafkaEventSourceConfig: props.eventSourceArn ? consumerGroupConfig : undefined, }); diff --git a/packages/@aws-cdk/aws-lambda/lib/index.ts b/packages/@aws-cdk/aws-lambda/lib/index.ts index a56224d5fba12..104afa76627a0 100644 --- a/packages/@aws-cdk/aws-lambda/lib/index.ts +++ b/packages/@aws-cdk/aws-lambda/lib/index.ts @@ -13,6 +13,7 @@ export * from './lambda-version'; export * from './singleton-lambda'; export * from './event-source'; export * from './event-source-mapping'; +export * from './event-source-filter'; export * from './destination'; export * from './event-invoke-config'; export * from './scalable-attribute-api'; diff --git a/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/cdk.out b/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/cdk.out new file mode 100644 index 0000000000000..8ecc185e9dbee --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/cdk.out @@ -0,0 +1 @@ +{"version":"21.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/lambda-test-assets.assets.json b/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/lambda-test-assets.assets.json new file mode 100644 index 0000000000000..981e7b2f4cbc4 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/lambda-test-assets.assets.json @@ -0,0 +1,32 @@ +{ + "version": "21.0.0", + "files": { + "9678c34eca93259d11f2d714177347afd66c50116e1e08996eff893d3ca81232": { + "source": { + "path": "/home/marcio/marcio/aws-cdk/packages/@aws-cdk/aws-lambda/test/my-lambda-handler", + "packaging": "zip" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "9678c34eca93259d11f2d714177347afd66c50116e1e08996eff893d3ca81232.zip", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + }, + "b7318e1b9cb46d3116b3092ae8d67eeb76f991783ed974f75c3199bbcccc1847": { + "source": { + "path": "lambda-test-assets.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "b7318e1b9cb46d3116b3092ae8d67eeb76f991783ed974f75c3199bbcccc1847.json", + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}" + } + } + } + }, + "dockerImages": {} +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/lambda-test-assets.template.json b/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/lambda-test-assets.template.json new file mode 100644 index 0000000000000..4bf977885b091 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/lambda-test-assets.template.json @@ -0,0 +1,91 @@ +{ + "Resources": { + "MyLambdaServiceRole4539ECB6": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "MyLambdaCCE802FB": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Code": { + "S3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "S3Key": "9678c34eca93259d11f2d714177347afd66c50116e1e08996eff893d3ca81232.zip" + }, + "Role": { + "Fn::GetAtt": [ + "MyLambdaServiceRole4539ECB6", + "Arn" + ] + }, + "Handler": "index.main", + "Runtime": "python3.9" + }, + "DependsOn": [ + "MyLambdaServiceRole4539ECB6" + ] + } + }, + "Parameters": { + "BootstrapVersion": { + "Type": "AWS::SSM::Parameter::Value", + "Default": "/cdk-bootstrap/hnb659fds/version", + "Description": "Version of the CDK Bootstrap resources in this environment, automatically retrieved from SSM Parameter Store. [cdk:skip]" + } + }, + "Rules": { + "CheckBootstrapVersion": { + "Assertions": [ + { + "Assert": { + "Fn::Not": [ + { + "Fn::Contains": [ + [ + "1", + "2", + "3", + "4", + "5" + ], + { + "Ref": "BootstrapVersion" + } + ] + } + ] + }, + "AssertDescription": "CDK bootstrap stack version 6 required. Please run 'cdk bootstrap' with a recent version of the CDK CLI." + } + ] + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/manifest.json b/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/manifest.json new file mode 100644 index 0000000000000..d517f7fd89f45 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/manifest.json @@ -0,0 +1,70 @@ +{ + "version": "21.0.0", + "artifacts": { + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + }, + "lambda-test-assets.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "lambda-test-assets.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "lambda-test-assets": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "lambda-test-assets.template.json", + "validateOnSynth": false, + "assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-deploy-role-${AWS::AccountId}-${AWS::Region}", + "cloudFormationExecutionRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-cfn-exec-role-${AWS::AccountId}-${AWS::Region}", + "stackTemplateAssetObjectUrl": "s3://cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}/b7318e1b9cb46d3116b3092ae8d67eeb76f991783ed974f75c3199bbcccc1847.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "lambda-test-assets.assets" + ], + "lookupRole": { + "arn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-lookup-role-${AWS::AccountId}-${AWS::Region}", + "requiresBootstrapStackVersion": 8, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "dependencies": [ + "lambda-test-assets.assets" + ], + "metadata": { + "/lambda-test-assets/MyLambda/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyLambdaServiceRole4539ECB6" + } + ], + "/lambda-test-assets/MyLambda/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyLambdaCCE802FB" + } + ], + "/lambda-test-assets/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/lambda-test-assets/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "lambda-test-assets" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/tree.json b/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/tree.json new file mode 100644 index 0000000000000..b16b292afcec8 --- /dev/null +++ b/packages/@aws-cdk/aws-lambda/test/cdk-integ.out/tree.json @@ -0,0 +1,143 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.1.92" + } + }, + "lambda-test-assets": { + "id": "lambda-test-assets", + "path": "lambda-test-assets", + "children": { + "MyLambda": { + "id": "MyLambda", + "path": "lambda-test-assets/MyLambda", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "lambda-test-assets/MyLambda/ServiceRole", + "children": { + "Resource": { + "id": "Resource", + "path": "lambda-test-assets/MyLambda/ServiceRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "lambda.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + }, + "managedPolicyArns": [ + { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole" + ] + ] + } + ] + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-iam.Role", + "version": "0.0.0" + } + }, + "Code": { + "id": "Code", + "path": "lambda-test-assets/MyLambda/Code", + "children": { + "Stage": { + "id": "Stage", + "path": "lambda-test-assets/MyLambda/Code/Stage", + "constructInfo": { + "fqn": "@aws-cdk/core.AssetStaging", + "version": "0.0.0" + } + }, + "AssetBucket": { + "id": "AssetBucket", + "path": "lambda-test-assets/MyLambda/Code/AssetBucket", + "constructInfo": { + "fqn": "@aws-cdk/aws-s3.BucketBase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-s3-assets.Asset", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "lambda-test-assets/MyLambda/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Function", + "aws:cdk:cloudformation:props": { + "code": { + "s3Bucket": { + "Fn::Sub": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}" + }, + "s3Key": "9678c34eca93259d11f2d714177347afd66c50116e1e08996eff893d3ca81232.zip" + }, + "role": { + "Fn::GetAtt": [ + "MyLambdaServiceRole4539ECB6", + "Arn" + ] + }, + "handler": "index.main", + "runtime": "python3.9" + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/aws-lambda.Function", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/core.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk/aws-lambda/test/event-source-mapping.test.ts b/packages/@aws-cdk/aws-lambda/test/event-source-mapping.test.ts index d283c63f09c09..728cfd5d161ee 100644 --- a/packages/@aws-cdk/aws-lambda/test/event-source-mapping.test.ts +++ b/packages/@aws-cdk/aws-lambda/test/event-source-mapping.test.ts @@ -1,6 +1,6 @@ import { Match, Template } from '@aws-cdk/assertions'; import * as cdk from '@aws-cdk/core'; -import { Code, EventSourceMapping, Function, Runtime, Alias, StartingPosition } from '../lib'; +import { Code, EventSourceMapping, Function, Runtime, Alias, StartingPosition, FilterRule, FilterCriteria } from '../lib'; let stack: cdk.Stack; let fn: Function; @@ -212,6 +212,71 @@ describe('event source mapping', () => { }); }); + test('filter with one pattern', () => { + const topicNameParam = new cdk.CfnParameter(stack, 'TopicNameParam', { + type: 'String', + }); + + let eventSourceArn = 'some-arn'; + + new EventSourceMapping(stack, 'test', { + target: fn, + eventSourceArn: eventSourceArn, + kafkaTopic: topicNameParam.valueAsString, + filters: [ + FilterCriteria.filter({ + numericEquals: FilterRule.isEqual(1), + }), + ], + }); + + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::EventSourceMapping', { + FilterCriteria: { + Filters: [ + { + Pattern: '{"numericEquals":[{"numeric":["=",1]}]}', + }, + ], + }, + }); + }); + + test('filter with more than one pattern', () => { + const topicNameParam = new cdk.CfnParameter(stack, 'TopicNameParam', { + type: 'String', + }); + + let eventSourceArn = 'some-arn'; + + new EventSourceMapping(stack, 'test', { + target: fn, + eventSourceArn: eventSourceArn, + kafkaTopic: topicNameParam.valueAsString, + filters: [ + FilterCriteria.filter({ + orFilter: FilterRule.or('one', 'two'), + stringEquals: FilterRule.isEqual('test'), + }), + FilterCriteria.filter({ + numericEquals: FilterRule.isEqual(1), + }), + ], + }); + + Template.fromStack(stack).hasResourceProperties('AWS::Lambda::EventSourceMapping', { + FilterCriteria: { + Filters: [ + { + Pattern: '{"orFilter":["one","two"],"stringEquals":["test"]}', + }, + { + Pattern: '{"numericEquals":[{"numeric":["=",1]}]}', + }, + ], + }, + }); + }); + test('kafkaBootstrapServers appears in stack', () => { const topicNameParam = new cdk.CfnParameter(stack, 'TopicNameParam', { type: 'String',