From a36c71f383e140e9943f19f8be1bba77bdd4e4de Mon Sep 17 00:00:00 2001 From: maz Date: Fri, 13 Sep 2024 10:24:39 +0900 Subject: [PATCH] feat(events-target): support Dead Letter Queue for Kinesis Stream Event Target --- ...efaultTestDeployAssertE4CFAC29.assets.json | 19 ++ ...aultTestDeployAssertE4CFAC29.template.json | 36 ++ ...s-cdk-kinesis-event-target-dlq.assets.json | 19 ++ ...cdk-kinesis-event-target-dlq.template.json | 171 ++++++++++ .../cdk.out | 1 + .../integ.json | 12 + .../manifest.json | 143 ++++++++ .../tree.json | 315 ++++++++++++++++++ .../integ.kinesis-stream-dead-letter-queue.ts | 28 ++ .../aws-cdk-lib/aws-events-targets/README.md | 2 +- .../aws-events-targets/lib/kinesis-stream.ts | 5 +- .../test/kinesis/kinesis-stream.test.ts | 32 +- 12 files changed, 779 insertions(+), 4 deletions(-) create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/KinesisDlqDefaultTestDeployAssertE4CFAC29.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/KinesisDlqDefaultTestDeployAssertE4CFAC29.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/aws-cdk-kinesis-event-target-dlq.assets.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/aws-cdk-kinesis-event-target-dlq.template.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/cdk.out create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/integ.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/manifest.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/tree.json create mode 100644 packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.ts diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/KinesisDlqDefaultTestDeployAssertE4CFAC29.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/KinesisDlqDefaultTestDeployAssertE4CFAC29.assets.json new file mode 100644 index 0000000000000..3be133b269609 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/KinesisDlqDefaultTestDeployAssertE4CFAC29.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.24", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "KinesisDlqDefaultTestDeployAssertE4CFAC29.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-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/KinesisDlqDefaultTestDeployAssertE4CFAC29.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/KinesisDlqDefaultTestDeployAssertE4CFAC29.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/KinesisDlqDefaultTestDeployAssertE4CFAC29.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-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/aws-cdk-kinesis-event-target-dlq.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/aws-cdk-kinesis-event-target-dlq.assets.json new file mode 100644 index 0000000000000..7e452036ed237 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/aws-cdk-kinesis-event-target-dlq.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.24", + "files": { + "b92166c0aa5448c8df40d6ed216b585ca5a8c8f600b343c74efb8983a16eb5a1": { + "source": { + "path": "aws-cdk-kinesis-event-target-dlq.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "b92166c0aa5448c8df40d6ed216b585ca5a8c8f600b343c74efb8983a16eb5a1.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-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/aws-cdk-kinesis-event-target-dlq.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/aws-cdk-kinesis-event-target-dlq.template.json new file mode 100644 index 0000000000000..f86d9fd999442 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/aws-cdk-kinesis-event-target-dlq.template.json @@ -0,0 +1,171 @@ +{ + "Resources": { + "MyStream5C050E93": { + "Type": "AWS::Kinesis::Stream", + "Properties": { + "RetentionPeriodHours": 24, + "ShardCount": 1, + "StreamEncryption": { + "Fn::If": [ + "AwsCdkKinesisEncryptedStreamsUnsupportedRegions", + { + "Ref": "AWS::NoValue" + }, + { + "EncryptionType": "KMS", + "KeyId": "alias/aws/kinesis" + } + ] + } + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + }, + "MyStreamEventsRole5B6CC6AF": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "events.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "MyStreamEventsRoleDefaultPolicy2089B49E": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "kinesis:PutRecord", + "kinesis:PutRecords" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "MyStream5C050E93", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "MyStreamEventsRoleDefaultPolicy2089B49E", + "Roles": [ + { + "Ref": "MyStreamEventsRole5B6CC6AF" + } + ] + } + }, + "Queue4A7E3555": { + "Type": "AWS::SQS::Queue", + "UpdateReplacePolicy": "Delete", + "DeletionPolicy": "Delete" + }, + "EveryMinute2BBCEA8F": { + "Type": "AWS::Events::Rule", + "Properties": { + "ScheduleExpression": "rate(1 minute)", + "State": "ENABLED", + "Targets": [ + { + "Arn": { + "Fn::GetAtt": [ + "MyStream5C050E93", + "Arn" + ] + }, + "DeadLetterConfig": { + "Arn": { + "Fn::GetAtt": [ + "Queue4A7E3555", + "Arn" + ] + } + }, + "Id": "Target0", + "KinesisParameters": { + "PartitionKeyPath": "$.id" + }, + "RetryPolicy": { + "MaximumEventAgeInSeconds": 7200, + "MaximumRetryAttempts": 2 + }, + "RoleArn": { + "Fn::GetAtt": [ + "MyStreamEventsRole5B6CC6AF", + "Arn" + ] + } + } + ] + } + } + }, + "Conditions": { + "AwsCdkKinesisEncryptedStreamsUnsupportedRegions": { + "Fn::Or": [ + { + "Fn::Equals": [ + { + "Ref": "AWS::Region" + }, + "cn-north-1" + ] + }, + { + "Fn::Equals": [ + { + "Ref": "AWS::Region" + }, + "cn-northwest-1" + ] + } + ] + } + }, + "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-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/cdk.out new file mode 100644 index 0000000000000..4efaa16f29af9 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.24"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/integ.json new file mode 100644 index 0000000000000..a34d4ef7c0934 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.24", + "testCases": { + "KinesisDlq/DefaultTest": { + "stacks": [ + "aws-cdk-kinesis-event-target-dlq" + ], + "assertionStack": "KinesisDlq/DefaultTest/DeployAssert", + "assertionStackName": "KinesisDlqDefaultTestDeployAssertE4CFAC29" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/manifest.json new file mode 100644 index 0000000000000..dcc9d0018043f --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/manifest.json @@ -0,0 +1,143 @@ +{ + "version": "36.0.24", + "artifacts": { + "aws-cdk-kinesis-event-target-dlq.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "aws-cdk-kinesis-event-target-dlq.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "aws-cdk-kinesis-event-target-dlq": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "aws-cdk-kinesis-event-target-dlq.template.json", + "terminationProtection": false, + "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}/b92166c0aa5448c8df40d6ed216b585ca5a8c8f600b343c74efb8983a16eb5a1.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "aws-cdk-kinesis-event-target-dlq.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": [ + "aws-cdk-kinesis-event-target-dlq.assets" + ], + "metadata": { + "/aws-cdk-kinesis-event-target-dlq/MyStream/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyStream5C050E93" + } + ], + "/aws-cdk-kinesis-event-target-dlq/MyStream/EventsRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyStreamEventsRole5B6CC6AF" + } + ], + "/aws-cdk-kinesis-event-target-dlq/MyStream/EventsRole/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "MyStreamEventsRoleDefaultPolicy2089B49E" + } + ], + "/aws-cdk-kinesis-event-target-dlq/AwsCdkKinesisEncryptedStreamsUnsupportedRegions": [ + { + "type": "aws:cdk:logicalId", + "data": "AwsCdkKinesisEncryptedStreamsUnsupportedRegions" + } + ], + "/aws-cdk-kinesis-event-target-dlq/Queue/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "Queue4A7E3555" + } + ], + "/aws-cdk-kinesis-event-target-dlq/EveryMinute/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "EveryMinute2BBCEA8F" + } + ], + "/aws-cdk-kinesis-event-target-dlq/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/aws-cdk-kinesis-event-target-dlq/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "aws-cdk-kinesis-event-target-dlq" + }, + "KinesisDlqDefaultTestDeployAssertE4CFAC29.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "KinesisDlqDefaultTestDeployAssertE4CFAC29.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "KinesisDlqDefaultTestDeployAssertE4CFAC29": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "KinesisDlqDefaultTestDeployAssertE4CFAC29.template.json", + "terminationProtection": false, + "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": [ + "KinesisDlqDefaultTestDeployAssertE4CFAC29.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": [ + "KinesisDlqDefaultTestDeployAssertE4CFAC29.assets" + ], + "metadata": { + "/KinesisDlq/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/KinesisDlq/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "KinesisDlq/DefaultTest/DeployAssert" + }, + "Tree": { + "type": "cdk:tree", + "properties": { + "file": "tree.json" + } + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/tree.json new file mode 100644 index 0000000000000..6af467fa6c2b9 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.js.snapshot/tree.json @@ -0,0 +1,315 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "aws-cdk-kinesis-event-target-dlq": { + "id": "aws-cdk-kinesis-event-target-dlq", + "path": "aws-cdk-kinesis-event-target-dlq", + "children": { + "MyStream": { + "id": "MyStream", + "path": "aws-cdk-kinesis-event-target-dlq/MyStream", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-kinesis-event-target-dlq/MyStream/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Kinesis::Stream", + "aws:cdk:cloudformation:props": { + "retentionPeriodHours": 24, + "shardCount": 1, + "streamEncryption": { + "Fn::If": [ + "AwsCdkKinesisEncryptedStreamsUnsupportedRegions", + { + "Ref": "AWS::NoValue" + }, + { + "EncryptionType": "KMS", + "KeyId": "alias/aws/kinesis" + } + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kinesis.CfnStream", + "version": "0.0.0" + } + }, + "EventsRole": { + "id": "EventsRole", + "path": "aws-cdk-kinesis-event-target-dlq/MyStream/EventsRole", + "children": { + "ImportEventsRole": { + "id": "ImportEventsRole", + "path": "aws-cdk-kinesis-event-target-dlq/MyStream/EventsRole/ImportEventsRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "aws-cdk-kinesis-event-target-dlq/MyStream/EventsRole/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Role", + "aws:cdk:cloudformation:props": { + "assumeRolePolicyDocument": { + "Statement": [ + { + "Action": "sts:AssumeRole", + "Effect": "Allow", + "Principal": { + "Service": "events.amazonaws.com" + } + } + ], + "Version": "2012-10-17" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "aws-cdk-kinesis-event-target-dlq/MyStream/EventsRole/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-kinesis-event-target-dlq/MyStream/EventsRole/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "kinesis:PutRecord", + "kinesis:PutRecords" + ], + "Effect": "Allow", + "Resource": { + "Fn::GetAtt": [ + "MyStream5C050E93", + "Arn" + ] + } + } + ], + "Version": "2012-10-17" + }, + "policyName": "MyStreamEventsRoleDefaultPolicy2089B49E", + "roles": [ + { + "Ref": "MyStreamEventsRole5B6CC6AF" + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.CfnPolicy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Policy", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_kinesis.Stream", + "version": "0.0.0" + } + }, + "AwsCdkKinesisEncryptedStreamsUnsupportedRegions": { + "id": "AwsCdkKinesisEncryptedStreamsUnsupportedRegions", + "path": "aws-cdk-kinesis-event-target-dlq/AwsCdkKinesisEncryptedStreamsUnsupportedRegions", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnCondition", + "version": "0.0.0" + } + }, + "Queue": { + "id": "Queue", + "path": "aws-cdk-kinesis-event-target-dlq/Queue", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-kinesis-event-target-dlq/Queue/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::SQS::Queue", + "aws:cdk:cloudformation:props": {} + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_sqs.CfnQueue", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_sqs.Queue", + "version": "0.0.0" + } + }, + "EveryMinute": { + "id": "EveryMinute", + "path": "aws-cdk-kinesis-event-target-dlq/EveryMinute", + "children": { + "Resource": { + "id": "Resource", + "path": "aws-cdk-kinesis-event-target-dlq/EveryMinute/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Events::Rule", + "aws:cdk:cloudformation:props": { + "scheduleExpression": "rate(1 minute)", + "state": "ENABLED", + "targets": [ + { + "id": "Target0", + "arn": { + "Fn::GetAtt": [ + "MyStream5C050E93", + "Arn" + ] + }, + "roleArn": { + "Fn::GetAtt": [ + "MyStreamEventsRole5B6CC6AF", + "Arn" + ] + }, + "kinesisParameters": { + "partitionKeyPath": "$.id" + }, + "deadLetterConfig": { + "arn": { + "Fn::GetAtt": [ + "Queue4A7E3555", + "Arn" + ] + } + }, + "retryPolicy": { + "maximumRetryAttempts": 2, + "maximumEventAgeInSeconds": 7200 + } + } + ] + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_events.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_events.Rule", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "aws-cdk-kinesis-event-target-dlq/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "aws-cdk-kinesis-event-target-dlq/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "KinesisDlq": { + "id": "KinesisDlq", + "path": "KinesisDlq", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "KinesisDlq/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "KinesisDlq/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "KinesisDlq/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "KinesisDlq/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "KinesisDlq/DefaultTest/DeployAssert/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTestCase", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "@aws-cdk/integ-tests-alpha.IntegTest", + "version": "0.0.0" + } + }, + "Tree": { + "id": "Tree", + "path": "Tree", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.App", + "version": "0.0.0" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.ts new file mode 100644 index 0000000000000..a285776fef133 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-events-targets/test/kinesis/integ.kinesis-stream-dead-letter-queue.ts @@ -0,0 +1,28 @@ +import * as events from 'aws-cdk-lib/aws-events'; +import * as kinesis from 'aws-cdk-lib/aws-kinesis'; +import * as sqs from 'aws-cdk-lib/aws-sqs'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import * as cdk from 'aws-cdk-lib'; +import * as targets from 'aws-cdk-lib/aws-events-targets'; + +const app = new cdk.App(); + +const stack = new cdk.Stack(app, 'aws-cdk-kinesis-event-target-dlq'); + +const stream = new kinesis.Stream(stack, 'MyStream'); +const queue = new sqs.Queue(stack, 'Queue'); + +const event = new events.Rule(stack, 'EveryMinute', { + schedule: events.Schedule.rate(cdk.Duration.minutes(1)), +}); + +event.addTarget(new targets.KinesisStream(stream, { + partitionKeyPath: events.EventField.eventId, + retryAttempts: 2, + maxEventAge: cdk.Duration.hours(2), + deadLetterQueue: queue, +})); + +new IntegTest(app, 'KinesisDlq', { + testCases: [stack], +}); diff --git a/packages/aws-cdk-lib/aws-events-targets/README.md b/packages/aws-cdk-lib/aws-events-targets/README.md index 73c052ac889a2..f3680dba9cf45 100644 --- a/packages/aws-cdk-lib/aws-events-targets/README.md +++ b/packages/aws-cdk-lib/aws-events-targets/README.md @@ -30,7 +30,7 @@ EventBridge. ## Event retry policy and using dead-letter queues -The Codebuild, CodePipeline, Lambda, StepFunctions, LogGroup, SQSQueue, SNSTopic and ECSTask targets support attaching a [dead letter queue and setting retry policies](https://docs.aws.amazon.com/eventbridge/latest/userguide/rule-dlq.html). See the [lambda example](#invoke-a-lambda-function). +The Codebuild, CodePipeline, Lambda, Kinesis Data Streams, StepFunctions, LogGroup, SQSQueue, SNSTopic and ECSTask targets support attaching a [dead letter queue and setting retry policies](https://docs.aws.amazon.com/eventbridge/latest/userguide/rule-dlq.html). See the [lambda example](#invoke-a-lambda-function). Use [escape hatches](https://docs.aws.amazon.com/cdk/latest/guide/cfn_layer.html) for the other target types. ## Invoke a Lambda function diff --git a/packages/aws-cdk-lib/aws-events-targets/lib/kinesis-stream.ts b/packages/aws-cdk-lib/aws-events-targets/lib/kinesis-stream.ts index b0f33fbee5fc8..119992f6430e7 100644 --- a/packages/aws-cdk-lib/aws-events-targets/lib/kinesis-stream.ts +++ b/packages/aws-cdk-lib/aws-events-targets/lib/kinesis-stream.ts @@ -1,4 +1,4 @@ -import { singletonEventRole } from './util'; +import { bindBaseTargetConfig, singletonEventRole, TargetBaseProps } from './util'; import * as events from '../../aws-events'; import * as iam from '../../aws-iam'; import * as kinesis from '../../aws-kinesis'; @@ -6,7 +6,7 @@ import * as kinesis from '../../aws-kinesis'; /** * Customize the Kinesis Stream Event Target */ -export interface KinesisStreamProps { +export interface KinesisStreamProps extends TargetBaseProps { /** * Partition Key Path for records sent to this stream * @@ -52,6 +52,7 @@ export class KinesisStream implements events.IRuleTarget { })); return { + ...bindBaseTargetConfig(this.props), arn: this.stream.streamArn, role, input: this.props.message, diff --git a/packages/aws-cdk-lib/aws-events-targets/test/kinesis/kinesis-stream.test.ts b/packages/aws-cdk-lib/aws-events-targets/test/kinesis/kinesis-stream.test.ts index a16b007a193ff..705007b0c4421 100644 --- a/packages/aws-cdk-lib/aws-events-targets/test/kinesis/kinesis-stream.test.ts +++ b/packages/aws-cdk-lib/aws-events-targets/test/kinesis/kinesis-stream.test.ts @@ -1,7 +1,8 @@ import { Template } from '../../../assertions'; import * as events from '../../../aws-events'; import * as kinesis from '../../../aws-kinesis'; -import { Stack } from '../../../core'; +import * as sqs from '../../../aws-sqs'; +import { Duration, Stack } from '../../../core'; import * as targets from '../../lib'; describe('KinesisStream event target', () => { @@ -99,5 +100,34 @@ describe('KinesisStream event target', () => { }); }); }); + + describe('with dead letter queuse settings', () => { + test('specifying retry policy and dead letter queue', () => { + const queue = new sqs.Queue(stack, 'Queue'); + + rule.addTarget(new targets.KinesisStream(stream, { + retryAttempts: 2, + maxEventAge: Duration.hours(2), + deadLetterQueue: queue, + })); + + Template.fromStack(stack).hasResourceProperties('AWS::Events::Rule', { + Targets: [ + { + Arn: streamArn, + Id: 'Target0', + RoleArn: { 'Fn::GetAtt': ['MyStreamEventsRole5B6CC6AF', 'Arn'] }, + DeadLetterConfig: { + Arn: stack.resolve(queue.queueArn), + }, + RetryPolicy: { + MaximumEventAgeInSeconds: 7200, + MaximumRetryAttempts: 2, + }, + }, + ], + }); + }); + }); }); });