diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/cdk.out b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/cdk.out new file mode 100644 index 0000000000000..1f0068d32659a --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/cdk.out @@ -0,0 +1 @@ +{"version":"36.0.0"} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/integ.json b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/integ.json new file mode 100644 index 0000000000000..578d4d8ef3900 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/integ.json @@ -0,0 +1,12 @@ +{ + "version": "36.0.0", + "testCases": { + "issue-4324/DefaultTest": { + "stacks": [ + "tester" + ], + "assertionStack": "issue-4324/DefaultTest/DeployAssert", + "assertionStackName": "issue4324DefaultTestDeployAssert63CED672" + } + } +} \ No newline at end of file diff --git a/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/issue4324DefaultTestDeployAssert63CED672.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/issue4324DefaultTestDeployAssert63CED672.assets.json new file mode 100644 index 0000000000000..c1ae0a39382b7 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/issue4324DefaultTestDeployAssert63CED672.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "21fbb51d7b23f6a6c262b46a9caee79d744a3ac019fd45422d988b96d44b2a22": { + "source": { + "path": "issue4324DefaultTestDeployAssert63CED672.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-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/issue4324DefaultTestDeployAssert63CED672.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/issue4324DefaultTestDeployAssert63CED672.template.json new file mode 100644 index 0000000000000..ad9d0fb73d1dd --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/issue4324DefaultTestDeployAssert63CED672.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-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/manifest.json b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/manifest.json new file mode 100644 index 0000000000000..c1b8f4c6cc749 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/manifest.json @@ -0,0 +1,204 @@ +{ + "version": "36.0.0", + "artifacts": { + "tester.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "tester.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "tester": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "tester.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}/20b12eefa53416ecf7d0a8d33e90ce9780a9d0cc4fc24750616b10cae4aa2b74.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "tester.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": [ + "testersetup", + "tester.assets" + ], + "metadata": { + "/tester/Imported/Notifications/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "ImportedNotificationsDB5DE386" + } + ], + "/tester/Imported/AllowBucketNotificationsTotesterFD715D26C": [ + { + "type": "aws:cdk:logicalId", + "data": "ImportedAllowBucketNotificationsTotesterFD715D26C4DE5336A" + } + ], + "/tester/F/ServiceRole/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FServiceRole3AC82EE1" + } + ], + "/tester/F/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "FC4345940" + } + ], + "/tester/BucketNotificationsHandler050a0587b7544547bf325f094a3db834/Role/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BucketNotificationsHandler050a0587b7544547bf325f094a3db834RoleB6FB88EC" + } + ], + "/tester/BucketNotificationsHandler050a0587b7544547bf325f094a3db834/Role/DefaultPolicy/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BucketNotificationsHandler050a0587b7544547bf325f094a3db834RoleDefaultPolicy2CF63D36" + } + ], + "/tester/BucketNotificationsHandler050a0587b7544547bf325f094a3db834/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "BucketNotificationsHandler050a0587b7544547bf325f094a3db8347ECC3691" + } + ], + "/tester/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/tester/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "tester" + }, + "testersetup.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "testersetup.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "testersetup": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "testersetup.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}/6e0ab0e0ad91bedecc73073614a2f4199a937352dfa2e4408afe2152b5e1809c.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version", + "additionalDependencies": [ + "testersetup.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": [ + "testersetup.assets" + ], + "metadata": { + "/testersetup/bucket/Resource": [ + { + "type": "aws:cdk:logicalId", + "data": "bucket43879C71" + } + ], + "/testersetup/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/testersetup/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "testersetup" + }, + "issue4324DefaultTestDeployAssert63CED672.assets": { + "type": "cdk:asset-manifest", + "properties": { + "file": "issue4324DefaultTestDeployAssert63CED672.assets.json", + "requiresBootstrapStackVersion": 6, + "bootstrapStackVersionSsmParameter": "/cdk-bootstrap/hnb659fds/version" + } + }, + "issue4324DefaultTestDeployAssert63CED672": { + "type": "aws:cloudformation:stack", + "environment": "aws://unknown-account/unknown-region", + "properties": { + "templateFile": "issue4324DefaultTestDeployAssert63CED672.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": [ + "issue4324DefaultTestDeployAssert63CED672.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": [ + "issue4324DefaultTestDeployAssert63CED672.assets" + ], + "metadata": { + "/issue-4324/DefaultTest/DeployAssert/BootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "BootstrapVersion" + } + ], + "/issue-4324/DefaultTest/DeployAssert/CheckBootstrapVersion": [ + { + "type": "aws:cdk:logicalId", + "data": "CheckBootstrapVersion" + } + ] + }, + "displayName": "issue-4324/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-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/tester.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/tester.assets.json new file mode 100644 index 0000000000000..46965f0d43fb8 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/tester.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "20b12eefa53416ecf7d0a8d33e90ce9780a9d0cc4fc24750616b10cae4aa2b74": { + "source": { + "path": "tester.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "20b12eefa53416ecf7d0a8d33e90ce9780a9d0cc4fc24750616b10cae4aa2b74.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-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/tester.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/tester.template.json new file mode 100644 index 0000000000000..8bad325aed1ad --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/tester.template.json @@ -0,0 +1,224 @@ +{ + "Resources": { + "ImportedNotificationsDB5DE386": { + "Type": "Custom::S3BucketNotifications", + "Properties": { + "ServiceToken": { + "Fn::GetAtt": [ + "BucketNotificationsHandler050a0587b7544547bf325f094a3db8347ECC3691", + "Arn" + ] + }, + "BucketName": "cdk-test-bucket-event-source", + "NotificationConfiguration": { + "LambdaFunctionConfigurations": [ + { + "Events": [ + "s3:ObjectCreated:*" + ], + "LambdaFunctionArn": { + "Fn::GetAtt": [ + "FC4345940", + "Arn" + ] + } + } + ] + }, + "Managed": false + }, + "DependsOn": [ + "ImportedAllowBucketNotificationsTotesterFD715D26C4DE5336A" + ] + }, + "ImportedAllowBucketNotificationsTotesterFD715D26C4DE5336A": { + "Type": "AWS::Lambda::Permission", + "Properties": { + "Action": "lambda:InvokeFunction", + "FunctionName": { + "Fn::GetAtt": [ + "FC4345940", + "Arn" + ] + }, + "Principal": "s3.amazonaws.com", + "SourceAccount": { + "Ref": "AWS::AccountId" + }, + "SourceArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::cdk-test-bucket-event-source" + ] + ] + } + } + }, + "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" + ] + ] + } + ] + } + }, + "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}" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "FServiceRole3AC82EE1", + "Arn" + ] + }, + "Runtime": "nodejs18.x" + }, + "DependsOn": [ + "FServiceRole3AC82EE1" + ] + }, + "BucketNotificationsHandler050a0587b7544547bf325f094a3db834RoleB6FB88EC": { + "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" + ] + ] + } + ] + } + }, + "BucketNotificationsHandler050a0587b7544547bf325f094a3db834RoleDefaultPolicy2CF63D36": { + "Type": "AWS::IAM::Policy", + "Properties": { + "PolicyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetBucketNotification", + "s3:PutBucketNotification" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "PolicyName": "BucketNotificationsHandler050a0587b7544547bf325f094a3db834RoleDefaultPolicy2CF63D36", + "Roles": [ + { + "Ref": "BucketNotificationsHandler050a0587b7544547bf325f094a3db834RoleB6FB88EC" + } + ] + } + }, + "BucketNotificationsHandler050a0587b7544547bf325f094a3db8347ECC3691": { + "Type": "AWS::Lambda::Function", + "Properties": { + "Description": "AWS CloudFormation handler for \"Custom::S3BucketNotifications\" resources (@aws-cdk/aws-s3)", + "Code": { + "ZipFile": "import boto3 # type: ignore\nimport json\nimport logging\nimport urllib.request\n\ns3 = boto3.client(\"s3\")\n\nEVENTBRIDGE_CONFIGURATION = 'EventBridgeConfiguration'\nCONFIGURATION_TYPES = [\"TopicConfigurations\", \"QueueConfigurations\", \"LambdaFunctionConfigurations\"]\n\ndef handler(event: dict, context):\n response_status = \"SUCCESS\"\n error_message = \"\"\n try:\n props = event[\"ResourceProperties\"]\n notification_configuration = props[\"NotificationConfiguration\"]\n managed = props.get('Managed', 'true').lower() == 'true'\n stack_id = event['StackId']\n old = event.get(\"OldResourceProperties\", {}).get(\"NotificationConfiguration\", {})\n if managed:\n config = handle_managed(event[\"RequestType\"], notification_configuration)\n else:\n config = handle_unmanaged(props[\"BucketName\"], stack_id, event[\"RequestType\"], notification_configuration, old)\n s3.put_bucket_notification_configuration(Bucket=props[\"BucketName\"], NotificationConfiguration=config)\n except Exception as e:\n logging.exception(\"Failed to put bucket notification configuration\")\n response_status = \"FAILED\"\n error_message = f\"Error: {str(e)}. \"\n finally:\n submit_response(event, context, response_status, error_message)\n\ndef handle_managed(request_type, notification_configuration):\n if request_type == 'Delete':\n return {}\n return notification_configuration\n\ndef handle_unmanaged(bucket, stack_id, request_type, notification_configuration, old):\n def with_id(n):\n n['Id'] = f\"{stack_id}-{hash(json.dumps(n, sort_keys=True))}\"\n return n\n\n external_notifications = {}\n existing_notifications = s3.get_bucket_notification_configuration(Bucket=bucket)\n for t in CONFIGURATION_TYPES:\n if request_type == 'Update':\n ids = [with_id(n) for n in old.get(t, [])]\n old_incoming_ids = [n['Id'] for n in ids]\n external_notifications[t] = [n for n in existing_notifications.get(t, []) if not n['Id'] in old_incoming_ids]\n elif request_type == 'Create':\n external_notifications[t] = [n for n in existing_notifications.get(t, [])]\n if EVENTBRIDGE_CONFIGURATION in existing_notifications:\n external_notifications[EVENTBRIDGE_CONFIGURATION] = existing_notifications[EVENTBRIDGE_CONFIGURATION]\n\n if request_type == 'Delete':\n return external_notifications\n\n notifications = {}\n for t in CONFIGURATION_TYPES:\n external = external_notifications.get(t, [])\n incoming = [with_id(n) for n in notification_configuration.get(t, [])]\n notifications[t] = external + incoming\n\n if EVENTBRIDGE_CONFIGURATION in notification_configuration:\n notifications[EVENTBRIDGE_CONFIGURATION] = notification_configuration[EVENTBRIDGE_CONFIGURATION]\n elif EVENTBRIDGE_CONFIGURATION in external_notifications:\n notifications[EVENTBRIDGE_CONFIGURATION] = external_notifications[EVENTBRIDGE_CONFIGURATION]\n\n return notifications\n\ndef submit_response(event: dict, context, response_status: str, error_message: str):\n response_body = json.dumps(\n {\n \"Status\": response_status,\n \"Reason\": f\"{error_message}See the details in CloudWatch Log Stream: {context.log_stream_name}\",\n \"PhysicalResourceId\": event.get(\"PhysicalResourceId\") or event[\"LogicalResourceId\"],\n \"StackId\": event[\"StackId\"],\n \"RequestId\": event[\"RequestId\"],\n \"LogicalResourceId\": event[\"LogicalResourceId\"],\n \"NoEcho\": False,\n }\n ).encode(\"utf-8\")\n headers = {\"content-type\": \"\", \"content-length\": str(len(response_body))}\n try:\n req = urllib.request.Request(url=event[\"ResponseURL\"], headers=headers, data=response_body, method=\"PUT\")\n with urllib.request.urlopen(req) as response:\n print(response.read().decode(\"utf-8\"))\n print(\"Status code: \" + response.reason)\n except Exception as e:\n print(\"send(..) failed executing request.urlopen(..): \" + str(e))\n" + }, + "Handler": "index.handler", + "Role": { + "Fn::GetAtt": [ + "BucketNotificationsHandler050a0587b7544547bf325f094a3db834RoleB6FB88EC", + "Arn" + ] + }, + "Runtime": "python3.9", + "Timeout": 300 + }, + "DependsOn": [ + "BucketNotificationsHandler050a0587b7544547bf325f094a3db834RoleDefaultPolicy2CF63D36", + "BucketNotificationsHandler050a0587b7544547bf325f094a3db834RoleB6FB88EC" + ] + } + }, + "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-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/testersetup.assets.json b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/testersetup.assets.json new file mode 100644 index 0000000000000..87734cf2c9fa1 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/testersetup.assets.json @@ -0,0 +1,19 @@ +{ + "version": "36.0.0", + "files": { + "6e0ab0e0ad91bedecc73073614a2f4199a937352dfa2e4408afe2152b5e1809c": { + "source": { + "path": "testersetup.template.json", + "packaging": "file" + }, + "destinations": { + "current_account-current_region": { + "bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}", + "objectKey": "6e0ab0e0ad91bedecc73073614a2f4199a937352dfa2e4408afe2152b5e1809c.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-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/testersetup.template.json b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/testersetup.template.json new file mode 100644 index 0000000000000..4aba989a28d13 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/testersetup.template.json @@ -0,0 +1,46 @@ +{ + "Resources": { + "bucket43879C71": { + "Type": "AWS::S3::Bucket", + "Properties": { + "BucketName": "cdk-test-bucket-event-source" + }, + "UpdateReplacePolicy": "Retain", + "DeletionPolicy": "Retain" + } + }, + "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-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/tree.json b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/tree.json new file mode 100644 index 0000000000000..beba93a32f461 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.js.snapshot/tree.json @@ -0,0 +1,423 @@ +{ + "version": "tree-0.1", + "tree": { + "id": "App", + "path": "", + "children": { + "tester": { + "id": "tester", + "path": "tester", + "children": { + "Imported": { + "id": "Imported", + "path": "tester/Imported", + "children": { + "Notifications": { + "id": "Notifications", + "path": "tester/Imported/Notifications", + "children": { + "Resource": { + "id": "Resource", + "path": "tester/Imported/Notifications/Resource", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "AllowBucketNotificationsTotesterFD715D26C": { + "id": "AllowBucketNotificationsTotesterFD715D26C", + "path": "tester/Imported/AllowBucketNotificationsTotesterFD715D26C", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::Lambda::Permission", + "aws:cdk:cloudformation:props": { + "action": "lambda:InvokeFunction", + "functionName": { + "Fn::GetAtt": [ + "FC4345940", + "Arn" + ] + }, + "principal": "s3.amazonaws.com", + "sourceAccount": { + "Ref": "AWS::AccountId" + }, + "sourceArn": { + "Fn::Join": [ + "", + [ + "arn:", + { + "Ref": "AWS::Partition" + }, + ":s3:::cdk-test-bucket-event-source" + ] + ] + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_lambda.CfnPermission", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.BucketBase", + "version": "0.0.0" + } + }, + "F": { + "id": "F", + "path": "tester/F", + "children": { + "ServiceRole": { + "id": "ServiceRole", + "path": "tester/F/ServiceRole", + "children": { + "ImportServiceRole": { + "id": "ImportServiceRole", + "path": "tester/F/ServiceRole/ImportServiceRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "tester/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-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_iam.Role", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "tester/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}" + }, + "handler": "index.handler", + "role": { + "Fn::GetAtt": [ + "FServiceRole3AC82EE1", + "Arn" + ] + }, + "runtime": "nodejs18.x" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_lambda.CfnFunction", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_lambda.Function", + "version": "0.0.0" + } + }, + "BucketNotificationsHandler050a0587b7544547bf325f094a3db834": { + "id": "BucketNotificationsHandler050a0587b7544547bf325f094a3db834", + "path": "tester/BucketNotificationsHandler050a0587b7544547bf325f094a3db834", + "children": { + "Role": { + "id": "Role", + "path": "tester/BucketNotificationsHandler050a0587b7544547bf325f094a3db834/Role", + "children": { + "ImportRole": { + "id": "ImportRole", + "path": "tester/BucketNotificationsHandler050a0587b7544547bf325f094a3db834/Role/ImportRole", + "constructInfo": { + "fqn": "aws-cdk-lib.Resource", + "version": "0.0.0" + } + }, + "Resource": { + "id": "Resource", + "path": "tester/BucketNotificationsHandler050a0587b7544547bf325f094a3db834/Role/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-lib.aws_iam.CfnRole", + "version": "0.0.0" + } + }, + "DefaultPolicy": { + "id": "DefaultPolicy", + "path": "tester/BucketNotificationsHandler050a0587b7544547bf325f094a3db834/Role/DefaultPolicy", + "children": { + "Resource": { + "id": "Resource", + "path": "tester/BucketNotificationsHandler050a0587b7544547bf325f094a3db834/Role/DefaultPolicy/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::IAM::Policy", + "aws:cdk:cloudformation:props": { + "policyDocument": { + "Statement": [ + { + "Action": [ + "s3:GetBucketNotification", + "s3:PutBucketNotification" + ], + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" + }, + "policyName": "BucketNotificationsHandler050a0587b7544547bf325f094a3db834RoleDefaultPolicy2CF63D36", + "roles": [ + { + "Ref": "BucketNotificationsHandler050a0587b7544547bf325f094a3db834RoleB6FB88EC" + } + ] + } + }, + "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" + } + }, + "Resource": { + "id": "Resource", + "path": "tester/BucketNotificationsHandler050a0587b7544547bf325f094a3db834/Resource", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnResource", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "tester/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "tester/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "testersetup": { + "id": "testersetup", + "path": "testersetup", + "children": { + "bucket": { + "id": "bucket", + "path": "testersetup/bucket", + "children": { + "Resource": { + "id": "Resource", + "path": "testersetup/bucket/Resource", + "attributes": { + "aws:cdk:cloudformation:type": "AWS::S3::Bucket", + "aws:cdk:cloudformation:props": { + "bucketName": "cdk-test-bucket-event-source" + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.CfnBucket", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.aws_s3.Bucket", + "version": "0.0.0" + } + }, + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "testersetup/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "testersetup/CheckBootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnRule", + "version": "0.0.0" + } + } + }, + "constructInfo": { + "fqn": "aws-cdk-lib.Stack", + "version": "0.0.0" + } + }, + "issue-4324": { + "id": "issue-4324", + "path": "issue-4324", + "children": { + "DefaultTest": { + "id": "DefaultTest", + "path": "issue-4324/DefaultTest", + "children": { + "Default": { + "id": "Default", + "path": "issue-4324/DefaultTest/Default", + "constructInfo": { + "fqn": "constructs.Construct", + "version": "10.3.0" + } + }, + "DeployAssert": { + "id": "DeployAssert", + "path": "issue-4324/DefaultTest/DeployAssert", + "children": { + "BootstrapVersion": { + "id": "BootstrapVersion", + "path": "issue-4324/DefaultTest/DeployAssert/BootstrapVersion", + "constructInfo": { + "fqn": "aws-cdk-lib.CfnParameter", + "version": "0.0.0" + } + }, + "CheckBootstrapVersion": { + "id": "CheckBootstrapVersion", + "path": "issue-4324/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-lambda-event-sources/test/integ.s3.imported-bucket.ts b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.ts new file mode 100644 index 0000000000000..f6cc041f04294 --- /dev/null +++ b/packages/@aws-cdk-testing/framework-integ/test/aws-lambda-event-sources/test/integ.s3.imported-bucket.ts @@ -0,0 +1,39 @@ +import { App, Stack } from 'aws-cdk-lib'; +import { Bucket, EventType } from 'aws-cdk-lib/aws-s3'; +import { S3EventSourceV2 } from 'aws-cdk-lib/aws-lambda-event-sources'; +import { TestFunction } from './test-function'; +import { IntegTest } from '@aws-cdk/integ-tests-alpha'; +import { Construct } from 'constructs'; + +const bucketName = 'cdk-test-bucket-event-source'; +class TestStack extends Stack { + constructor(scope: Construct, id: string) { + super(scope, id); + const setupStack = new class extends Stack { + constructor() { + super(scope, id + 'setup'); + new Bucket(this, 'bucket', { + bucketName, + }); + } + }(); + + const importBucket = Bucket.fromBucketName(this, 'Imported', bucketName); + importBucket.node.addDependency(setupStack); + + const fn = new TestFunction(this, 'F'); + fn.addEventSource(new S3EventSourceV2(importBucket, { + events: [ + EventType.OBJECT_CREATED, + ], + })); + } +} + +const app = new App(); + +new IntegTest(app, 'issue-4324', { + testCases: [ + new TestStack(app, 'tester'), + ], +}); \ No newline at end of file diff --git a/packages/aws-cdk-lib/aws-lambda-event-sources/README.md b/packages/aws-cdk-lib/aws-lambda-event-sources/README.md index 9b3351830f269..c7fe6791f4df6 100644 --- a/packages/aws-cdk-lib/aws-lambda-event-sources/README.md +++ b/packages/aws-cdk-lib/aws-lambda-event-sources/README.md @@ -92,6 +92,24 @@ fn.addEventSource(new S3EventSource(bucket, { })); ``` +In the example above, `S3EventSource` is accepting `Bucket` type as parameter. +However, Functions like `from_bucket_name` and `from_bucket_arn` will return `IBucket` +and is not compliant with `S3EventSource`. If this is the case, please consider using +`S3EventSourceV2` instead, this class accepts `IBucket`. + +```ts +import * as s3 from 'aws-cdk-lib/aws-s3'; +import { S3EventSourceV2 } from 'aws-cdk-lib/aws-lambda-event-sources'; + +const bucket = s3.Bucket.fromBucketName(this, 'Bucket', 'bucket-name'); +declare const fn: lambda.Function; + +fn.addEventSource(new S3EventSourceV2(bucket, { + events: [ s3.EventType.OBJECT_CREATED, s3.EventType.OBJECT_REMOVED ], + filters: [ { prefix: 'subdir/' } ], // optional +})); +``` + ## SNS You can write Lambda functions to process Amazon Simple Notification Service diff --git a/packages/aws-cdk-lib/aws-lambda-event-sources/lib/s3.ts b/packages/aws-cdk-lib/aws-lambda-event-sources/lib/s3.ts index 2a11b81398b0f..7b95423da49c3 100644 --- a/packages/aws-cdk-lib/aws-lambda-event-sources/lib/s3.ts +++ b/packages/aws-cdk-lib/aws-lambda-event-sources/lib/s3.ts @@ -32,3 +32,19 @@ export class S3EventSource implements lambda.IEventSource { } } } + +/** + * S3EventSourceV2 Use S3 bucket notifications as an event source for AWS Lambda. + */ +export class S3EventSourceV2 implements lambda.IEventSource { + constructor(private readonly bucket: s3.IBucket, private readonly props: S3EventSourceProps) { + + } + + public bind(target: lambda.IFunction) { + const filters = this.props.filters || []; + for (const event of this.props.events) { + this.bucket.addEventNotification(event, new notifs.LambdaDestination(target), ...filters); + } + } +} diff --git a/packages/aws-cdk-lib/aws-lambda-event-sources/test/s3.test.ts b/packages/aws-cdk-lib/aws-lambda-event-sources/test/s3.test.ts index 2e2441c1ea5a4..f5ab8a7fc4bb3 100644 --- a/packages/aws-cdk-lib/aws-lambda-event-sources/test/s3.test.ts +++ b/packages/aws-cdk-lib/aws-lambda-event-sources/test/s3.test.ts @@ -80,4 +80,152 @@ describe('S3EventSource', () => { }, }); }); + + test('test S3EventSourceV2 with IBucket', () => { + // GIVEN + const stack = new cdk.Stack(); + const fn = new TestFunction(stack, 'Fn'); + const bucket = s3.Bucket.fromBucketName(stack, 'Bucket', 'bucket-name'); + + // WHEN + fn.addEventSource(new sources.S3EventSourceV2(bucket, { + events: [s3.EventType.OBJECT_CREATED, s3.EventType.OBJECT_REMOVED], + filters: [ + { prefix: 'prefix/' }, + { suffix: '.png' }, + ], + })); + + // THEN + Template.fromStack(stack).hasResourceProperties('Custom::S3BucketNotifications', { + 'NotificationConfiguration': { + 'LambdaFunctionConfigurations': [ + { + 'Events': [ + 's3:ObjectCreated:*', + ], + 'Filter': { + 'Key': { + 'FilterRules': [ + { + 'Name': 'prefix', + 'Value': 'prefix/', + }, + { + 'Name': 'suffix', + 'Value': '.png', + }, + ], + }, + }, + 'LambdaFunctionArn': { + 'Fn::GetAtt': [ + 'Fn9270CBC0', + 'Arn', + ], + }, + }, + { + 'Events': [ + 's3:ObjectRemoved:*', + ], + 'Filter': { + 'Key': { + 'FilterRules': [ + { + 'Name': 'prefix', + 'Value': 'prefix/', + }, + { + 'Name': 'suffix', + 'Value': '.png', + }, + ], + }, + }, + 'LambdaFunctionArn': { + 'Fn::GetAtt': [ + 'Fn9270CBC0', + 'Arn', + ], + }, + }, + ], + }, + }); + }); + + test('test S3EventSourceV2 with Bucket', () => { + // GIVEN + const stack = new cdk.Stack(); + const fn = new TestFunction(stack, 'Fn'); + const bucket = new s3.Bucket(stack, 'B'); + + // WHEN + fn.addEventSource(new sources.S3EventSourceV2(bucket, { + events: [s3.EventType.OBJECT_CREATED, s3.EventType.OBJECT_REMOVED], + filters: [ + { prefix: 'prefix/' }, + { suffix: '.png' }, + ], + })); + + // THEN + Template.fromStack(stack).hasResourceProperties('Custom::S3BucketNotifications', { + 'NotificationConfiguration': { + 'LambdaFunctionConfigurations': [ + { + 'Events': [ + 's3:ObjectCreated:*', + ], + 'Filter': { + 'Key': { + 'FilterRules': [ + { + 'Name': 'prefix', + 'Value': 'prefix/', + }, + { + 'Name': 'suffix', + 'Value': '.png', + }, + ], + }, + }, + 'LambdaFunctionArn': { + 'Fn::GetAtt': [ + 'Fn9270CBC0', + 'Arn', + ], + }, + }, + { + 'Events': [ + 's3:ObjectRemoved:*', + ], + 'Filter': { + 'Key': { + 'FilterRules': [ + { + 'Name': 'prefix', + 'Value': 'prefix/', + }, + { + 'Name': 'suffix', + 'Value': '.png', + }, + ], + }, + }, + 'LambdaFunctionArn': { + 'Fn::GetAtt': [ + 'Fn9270CBC0', + 'Arn', + ], + }, + }, + ], + }, + }); + }); });