-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
S3: Adding notification for eventbridge (#7252)
- Loading branch information
1 parent
59248f3
commit b9d7c20
Showing
6 changed files
with
307 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import json | ||
from uuid import uuid4 | ||
|
||
import boto3 | ||
|
||
from moto import mock_aws | ||
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID | ||
|
||
REGION_NAME = "us-east-1" | ||
|
||
|
||
@mock_aws | ||
def test_pub_object_notification(): | ||
s3_res = boto3.resource("s3", region_name=REGION_NAME) | ||
s3_client = boto3.client("s3", region_name=REGION_NAME) | ||
events_client = boto3.client("events", region_name=REGION_NAME) | ||
logs_client = boto3.client("logs", region_name=REGION_NAME) | ||
|
||
rule_name = "test-rule" | ||
events_client.put_rule( | ||
Name=rule_name, EventPattern=json.dumps({"account": [ACCOUNT_ID]}) | ||
) | ||
log_group_name = "/test-group" | ||
logs_client.create_log_group(logGroupName=log_group_name) | ||
events_client.put_targets( | ||
Rule=rule_name, | ||
Targets=[ | ||
{ | ||
"Id": "test", | ||
"Arn": f"arn:aws:logs:{REGION_NAME}:{ACCOUNT_ID}:log-group:{log_group_name}", | ||
} | ||
], | ||
) | ||
|
||
# Create S3 bucket | ||
bucket_name = str(uuid4()) | ||
s3_res.create_bucket(Bucket=bucket_name) | ||
|
||
# Put Notification | ||
s3_client.put_bucket_notification_configuration( | ||
Bucket=bucket_name, | ||
NotificationConfiguration={"EventBridgeConfiguration": {}}, | ||
) | ||
|
||
# Put Object | ||
s3_client.put_object(Bucket=bucket_name, Key="keyname", Body="bodyofnewobject") | ||
|
||
events = sorted( | ||
logs_client.filter_log_events(logGroupName=log_group_name)["events"], | ||
key=lambda item: item["eventId"], | ||
) | ||
assert len(events) == 1 | ||
event_message = json.loads(events[0]["message"]) | ||
assert event_message["detail-type"] == "Object Created" | ||
assert event_message["source"] == "aws.s3" | ||
assert event_message["account"] == ACCOUNT_ID | ||
assert event_message["region"] == REGION_NAME | ||
assert event_message["detail"]["bucket"]["name"] == bucket_name | ||
assert event_message["detail"]["reason"] == "ObjectCreated" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
import json | ||
from typing import List | ||
from unittest import SkipTest | ||
from uuid import uuid4 | ||
|
||
import boto3 | ||
import pytest | ||
|
||
from moto import mock_aws, settings | ||
from moto.core import DEFAULT_ACCOUNT_ID as ACCOUNT_ID | ||
from moto.s3.models import FakeBucket, FakeKey | ||
from moto.s3.notifications import ( | ||
S3NotificationEvent, | ||
_detail_type, | ||
_send_event_bridge_message, | ||
) | ||
|
||
REGION_NAME = "us-east-1" | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"event_names, expected_event_message", | ||
[ | ||
( | ||
[ | ||
S3NotificationEvent.OBJECT_CREATED_PUT_EVENT, | ||
S3NotificationEvent.OBJECT_CREATED_POST_EVENT, | ||
S3NotificationEvent.OBJECT_CREATED_COPY_EVENT, | ||
S3NotificationEvent.OBJECT_CREATED_COMPLETE_MULTIPART_UPLOAD_EVENT, | ||
], | ||
"Object Created", | ||
), | ||
( | ||
[ | ||
S3NotificationEvent.OBJECT_REMOVED_DELETE_EVENT, | ||
S3NotificationEvent.OBJECT_REMOVED_DELETE_MARKER_CREATED_EVENT, | ||
], | ||
"Object Deleted", | ||
), | ||
([S3NotificationEvent.OBJECT_RESTORE_POST_EVENT], "Object Restore Initiated"), | ||
( | ||
[S3NotificationEvent.OBJECT_RESTORE_COMPLETED_EVENT], | ||
"Object Restore Completed", | ||
), | ||
( | ||
[S3NotificationEvent.OBJECT_RESTORE_DELETE_EVENT], | ||
"Object Restore Expired", | ||
), | ||
( | ||
[S3NotificationEvent.LIFECYCLE_TRANSITION_EVENT], | ||
"Object Storage Class Changed", | ||
), | ||
([S3NotificationEvent.INTELLIGENT_TIERING_EVENT], "Object Access Tier Changed"), | ||
([S3NotificationEvent.OBJECT_ACL_EVENT], "Object ACL Updated"), | ||
([S3NotificationEvent.OBJECT_TAGGING_PUT_EVENT], "Object Tags Added"), | ||
([S3NotificationEvent.OBJECT_TAGGING_DELETE_EVENT], "Object Tags Deleted"), | ||
], | ||
) | ||
def test_detail_type(event_names: List[str], expected_event_message: str): | ||
for event_name in event_names: | ||
assert _detail_type(event_name) == expected_event_message | ||
|
||
|
||
def test_detail_type_unknown_event(): | ||
with pytest.raises(ValueError) as ex: | ||
_detail_type("unknown event") | ||
assert ( | ||
str(ex.value) | ||
== "unsupported event `unknown event` for s3 eventbridge notification (https://docs.aws.amazon.com/AmazonS3/latest/userguide/EventBridge.html)" | ||
) | ||
|
||
|
||
@mock_aws | ||
def test_send_event_bridge_message(): | ||
# setup mocks | ||
events_client = boto3.client("events", region_name=REGION_NAME) | ||
logs_client = boto3.client("logs", region_name=REGION_NAME) | ||
rule_name = "test-rule" | ||
events_client.put_rule( | ||
Name=rule_name, EventPattern=json.dumps({"account": [ACCOUNT_ID]}) | ||
) | ||
log_group_name = "/test-group" | ||
logs_client.create_log_group(logGroupName=log_group_name) | ||
mocked_bucket = FakeBucket(str(uuid4()), ACCOUNT_ID, REGION_NAME) | ||
mocked_key = FakeKey( | ||
"test-key", bytes("test content", encoding="utf-8"), ACCOUNT_ID | ||
) | ||
|
||
# do nothing if event target does not exists. | ||
_send_event_bridge_message( | ||
ACCOUNT_ID, | ||
mocked_bucket, | ||
S3NotificationEvent.OBJECT_CREATED_PUT_EVENT, | ||
mocked_key, | ||
) | ||
assert ( | ||
len(logs_client.filter_log_events(logGroupName=log_group_name)["events"]) == 0 | ||
) | ||
|
||
# do nothing even if an error is raised while sending events. | ||
events_client.put_targets( | ||
Rule=rule_name, | ||
Targets=[ | ||
{ | ||
"Id": "test", | ||
"Arn": f"arn:aws:logs:{REGION_NAME}:{ACCOUNT_ID}:log-group:{log_group_name}", | ||
} | ||
], | ||
) | ||
|
||
_send_event_bridge_message(ACCOUNT_ID, mocked_bucket, "unknown-event", mocked_key) | ||
assert ( | ||
len(logs_client.filter_log_events(logGroupName=log_group_name)["events"]) == 0 | ||
) | ||
|
||
if not settings.TEST_DECORATOR_MODE: | ||
raise SkipTest(("Doesn't quite work right with the Proxy or Server")) | ||
# an event is correctly sent to the log group. | ||
_send_event_bridge_message( | ||
ACCOUNT_ID, | ||
mocked_bucket, | ||
S3NotificationEvent.OBJECT_CREATED_PUT_EVENT, | ||
mocked_key, | ||
) | ||
events = logs_client.filter_log_events(logGroupName=log_group_name)["events"] | ||
assert len(events) == 1 | ||
event_msg = json.loads(events[0]["message"]) | ||
assert event_msg["detail-type"] == "Object Created" | ||
assert event_msg["source"] == "aws.s3" | ||
assert event_msg["region"] == REGION_NAME | ||
assert event_msg["resources"] == [f"arn:aws:s3:::{mocked_bucket.name}"] | ||
event_detail = event_msg["detail"] | ||
assert event_detail["bucket"] == {"name": mocked_bucket.name} | ||
assert event_detail["object"]["key"] == mocked_key.name | ||
assert event_detail["reason"] == "ObjectCreated" |