Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: SNS Event FilterPolicyScope attribute #2988

Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions integration/combination/test_function_with_sns.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,4 @@ def test_function_with_sns_intrinsics(self):
subscription_arn = subscription["SubscriptionArn"]
subscription_attributes = sns_client.get_subscription_attributes(SubscriptionArn=subscription_arn)
self.assertEqual(subscription_attributes["Attributes"]["FilterPolicy"], '{"price_usd":[{"numeric":["<",100]}]}')
self.assertEqual(subscription_attributes["Attributes"]["FilterPolicyScope"], "MessageAttributes")
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Resources:
- numeric:
- <
- 100
FilterPolicyScope: MessageAttributes
Region:
Ref: AWS::Region
SqsSubscription: true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ class SqsSubscription(BaseModel):

class SNSEventProperties(BaseModel):
FilterPolicy: Optional[PassThroughProp] = snseventproperties("FilterPolicy")
FilterPolicyScope: Optional[PassThroughProp] = snseventproperties("FilterPolicyScope")
Region: Optional[PassThroughProp] = snseventproperties("Region")
SqsSubscription: Optional[Union[bool, SqsSubscription]] = snseventproperties("SqsSubscription")
Topic: PassThroughProp = snseventproperties("Topic")
Expand Down
1 change: 1 addition & 0 deletions samtranslator/internal/schema_source/sam-docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@
},
"sam-property-function-sns": {
"FilterPolicy": "The filter policy JSON assigned to the subscription\\. For more information, see [GetSubscriptionAttributes](https://docs.aws.amazon.com/sns/latest/api/API_GetSubscriptionAttributes.html) in the Amazon Simple Notification Service API Reference\\. \n*Type*: [SnsFilterPolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sns-subscription.html#cfn-sns-subscription-filterpolicy) \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`FilterPolicy`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sns-subscription.html#cfn-sns-subscription-filterpolicy) property of an `AWS::SNS::Subscription` resource\\.",
"FilterPolicyScope": "This attribute lets you choose the filtering scope by using one of the following string value types: \n+ `MessageAttributes` \\(default\\) \\- The filter is applied on the message attributes\\.\n+ `MessageBody` \\- The filter is applied on the message body\\.\n*Required*: No \n*Type*: String \n*Update requires*: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)",
mustafa-sadiq marked this conversation as resolved.
Show resolved Hide resolved
"RedrivePolicy": "When specified, sends undeliverable messages to the specified Amazon SQS dead\\-letter queue\\. Messages that can't be delivered due to client errors \\(for example, when the subscribed endpoint is unreachable\\) or server errors \\(for example, when the service that powers the subscribed endpoint becomes unavailable\\) are held in the dead\\-letter queue for further analysis or reprocessing\\. \nFor more information about the redrive policy and dead\\-letter queues, see [ Amazon SQS dead\\-letter queues](https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-dead-letter-queues.html) in the *Amazon Simple Queue Service Developer Guide*\\. \n*Type*: Json \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the `[ RedrivePolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sns-subscription.html#cfn-sns-subscription-redrivepolicy)` property of an `AWS::SNS::Subscription` resource\\.",
"Region": "For cross\\-region subscriptions, the region in which the topic resides\\. \nIf no region is specified, CloudFormation uses the region of the caller as the default\\. \n*Type*: String \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`Region`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sns-subscription.html#cfn-sns-subscription-region) property of an `AWS::SNS::Subscription` resource\\.",
"SqsSubscription": "Set this property to true, or specify `SqsSubscriptionObject` to enable batching SNS topic notifications in an SQS queue\\. Setting this property to `true` creates a new SQS queue, whereas specifying a `SqsSubscriptionObject` uses an existing SQS queue\\. \n*Type*: Boolean \\| [SqsSubscriptionObject](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-property-function-sqssubscriptionobject.html) \n*Required*: No \n*AWS CloudFormation compatibility*: This property is unique to AWS SAM and doesn't have an AWS CloudFormation equivalent\\.",
Expand Down
25 changes: 23 additions & 2 deletions samtranslator/model/eventsources/push.py
Original file line number Diff line number Diff line change
Expand Up @@ -486,13 +486,15 @@ class SNS(PushEventSource):
"Topic": PropertyType(True, IS_STR),
"Region": PropertyType(False, IS_STR),
"FilterPolicy": PropertyType(False, dict_of(IS_STR, list_of(one_of(IS_STR, IS_DICT)))),
"FilterPolicyScope": PropertyType(False, IS_STR),
mustafa-sadiq marked this conversation as resolved.
Show resolved Hide resolved
"SqsSubscription": PropertyType(False, one_of(IS_BOOL, IS_DICT)),
"RedrivePolicy": PropertyType(False, IS_DICT),
}

Topic: str
Region: Optional[str]
FilterPolicy: Optional[Dict[str, Any]]
FilterPolicyScope: Optional[str]
SqsSubscription: Optional[Any]
RedrivePolicy: Optional[Dict[str, Any]]

Expand All @@ -518,6 +520,7 @@ def to_cloudformation(self, **kwargs): # type: ignore[no-untyped-def]
self.Topic,
self.Region,
self.FilterPolicy,
self.FilterPolicyScope,
self.RedrivePolicy,
function,
)
Expand All @@ -532,7 +535,14 @@ def to_cloudformation(self, **kwargs): # type: ignore[no-untyped-def]

queue_policy = self._inject_sqs_queue_policy(self.Topic, queue_arn, queue_url, function) # type: ignore[no-untyped-call]
subscription = self._inject_subscription(
"sqs", queue_arn, self.Topic, self.Region, self.FilterPolicy, self.RedrivePolicy, function
"sqs",
queue_arn,
self.Topic,
self.Region,
self.FilterPolicy,
self.FilterPolicyScope,
self.RedrivePolicy,
function,
)
event_source = self._inject_sqs_event_source_mapping(function, role, queue_arn) # type: ignore[no-untyped-call]

Expand Down Expand Up @@ -560,7 +570,14 @@ def to_cloudformation(self, **kwargs): # type: ignore[no-untyped-def]
self.Topic, queue_arn, queue_url, function, queue_policy_logical_id
)
subscription = self._inject_subscription(
"sqs", queue_arn, self.Topic, self.Region, self.FilterPolicy, self.RedrivePolicy, function
"sqs",
queue_arn,
self.Topic,
self.Region,
self.FilterPolicy,
self.FilterPolicyScope,
self.RedrivePolicy,
function,
)
event_source = self._inject_sqs_event_source_mapping(function, role, queue_arn, batch_size, enabled) # type: ignore[no-untyped-call]

Expand All @@ -576,6 +593,7 @@ def _inject_subscription( # noqa: too-many-arguments
topic: str,
region: Optional[str],
filterPolicy: Optional[Dict[str, Any]],
filterPolicyScope: Optional[str],
redrivePolicy: Optional[Dict[str, Any]],
function: Any,
) -> SNSSubscription:
Expand All @@ -590,6 +608,9 @@ def _inject_subscription( # noqa: too-many-arguments
if filterPolicy is not None:
subscription.FilterPolicy = filterPolicy

if filterPolicyScope is not None:
subscription.FilterPolicyScope = filterPolicyScope

if redrivePolicy is not None:
subscription.RedrivePolicy = redrivePolicy

Expand Down
1 change: 1 addition & 0 deletions samtranslator/model/sns.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class SNSSubscription(Resource):
"TopicArn": GeneratedProperty(),
"Region": GeneratedProperty(),
"FilterPolicy": GeneratedProperty(),
"FilterPolicyScope": GeneratedProperty(),
"RedrivePolicy": GeneratedProperty(),
}

Expand Down
10 changes: 10 additions & 0 deletions samtranslator/schema/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -196069,6 +196069,16 @@
"markdownDescription": "The filter policy JSON assigned to the subscription\\. For more information, see [GetSubscriptionAttributes](https://docs.aws.amazon.com/sns/latest/api/API_GetSubscriptionAttributes.html) in the Amazon Simple Notification Service API Reference\\. \n*Type*: [SnsFilterPolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sns-subscription.html#cfn-sns-subscription-filterpolicy) \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`FilterPolicy`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sns-subscription.html#cfn-sns-subscription-filterpolicy) property of an `AWS::SNS::Subscription` resource\\.",
"title": "FilterPolicy"
},
"FilterPolicyScope": {
"allOf": [
{
"$ref": "#/definitions/PassThroughProp"
}
],
"description": "This attribute lets you choose the filtering scope by using one of the following string value types: \n+ `MessageAttributes` \\(default\\) \\- The filter is applied on the message attributes\\.\n+ `MessageBody` \\- The filter is applied on the message body\\.\n*Required*: No \n*Type*: String \n*Update requires*: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)",
"markdownDescription": "This attribute lets you choose the filtering scope by using one of the following string value types: \n+ `MessageAttributes` \\(default\\) \\- The filter is applied on the message attributes\\.\n+ `MessageBody` \\- The filter is applied on the message body\\.\n*Required*: No \n*Type*: String \n*Update requires*: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)",
"title": "FilterPolicyScope"
},
"Region": {
"allOf": [
{
Expand Down
3 changes: 3 additions & 0 deletions samtranslator/validator/sam_schema/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -783,6 +783,9 @@
},
"FilterPolicy": {
"type": "object"
},
"FilterPolicyScope": {
"type": "string"
}
},
"required": [
Expand Down
10 changes: 10 additions & 0 deletions schema_source/sam.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -2470,6 +2470,16 @@
"markdownDescription": "The filter policy JSON assigned to the subscription\\. For more information, see [GetSubscriptionAttributes](https://docs.aws.amazon.com/sns/latest/api/API_GetSubscriptionAttributes.html) in the Amazon Simple Notification Service API Reference\\. \n*Type*: [SnsFilterPolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sns-subscription.html#cfn-sns-subscription-filterpolicy) \n*Required*: No \n*AWS CloudFormation compatibility*: This property is passed directly to the [`FilterPolicy`](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-sns-subscription.html#cfn-sns-subscription-filterpolicy) property of an `AWS::SNS::Subscription` resource\\.",
"title": "FilterPolicy"
},
"FilterPolicyScope": {
"allOf": [
{
"$ref": "#/definitions/PassThroughProp"
}
],
"description": "This attribute lets you choose the filtering scope by using one of the following string value types: \n+ `MessageAttributes` \\(default\\) \\- The filter is applied on the message attributes\\.\n+ `MessageBody` \\- The filter is applied on the message body\\.\n*Required*: No \n*Type*: String \n*Update requires*: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)",
"markdownDescription": "This attribute lets you choose the filtering scope by using one of the following string value types: \n+ `MessageAttributes` \\(default\\) \\- The filter is applied on the message attributes\\.\n+ `MessageBody` \\- The filter is applied on the message body\\.\n*Required*: No \n*Type*: String \n*Update requires*: [No interruption](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-updating-stacks-update-behaviors.html#update-no-interrupt)",
"title": "FilterPolicyScope"
},
"Region": {
"allOf": [
{
Expand Down
12 changes: 12 additions & 0 deletions tests/model/eventsources/test_sns_event_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ def test_to_cloudformation_returns_permission_and_subscription_resources(self):
self.assertEqual(subscription.Endpoint, "arn:aws:lambda:mock")
self.assertIsNone(subscription.Region)
self.assertIsNone(subscription.FilterPolicy)
self.assertIsNone(subscription.FilterPolicyScope)
self.assertIsNone(subscription.RedrivePolicy)

def test_to_cloudformation_passes_the_region(self):
Expand All @@ -56,6 +57,16 @@ def test_to_cloudformation_passes_the_filter_policy(self):
subscription = resources[1]
self.assertEqual(subscription.FilterPolicy, filterPolicy)

def test_to_cloudformation_passes_the_filter_policy_scope(self):
filterPolicyScope = "MessageAttributes"
self.sns_event_source.FilterPolicyScope = filterPolicyScope

resources = self.sns_event_source.to_cloudformation(function=self.function)
self.assertEqual(len(resources), 2)
self.assertEqual(resources[1].resource_type, "AWS::SNS::Subscription")
subscription = resources[1]
self.assertEqual(subscription.FilterPolicyScope, filterPolicyScope)

def test_to_cloudformation_passes_the_redrive_policy(self):
redrive_policy = {"deadLetterTargetArn": "arn:aws:sqs:us-east-2:123456789012:MyDeadLetterQueue"}
self.sns_event_source.RedrivePolicy = redrive_policy
Expand Down Expand Up @@ -89,4 +100,5 @@ def test_to_cloudformation_when_sqs_subscription_disable(self):
self.assertEqual(subscription.Endpoint, "arn:aws:lambda:mock")
self.assertIsNone(subscription.Region)
self.assertIsNone(subscription.FilterPolicy)
self.assertIsNone(subscription.FilterPolicyScope)
self.assertIsNone(subscription.RedrivePolicy)
Original file line number Diff line number Diff line change
@@ -1,27 +1,28 @@
Resources:
MyAwesomeFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/hello.zip
Handler: hello.handler
Runtime: python2.7

Events:
NotificationTopic:
Type: SNS
Properties:
Topic: topicArn
Region: region
FilterPolicy:
store:
- example_corp
event:
- anything-but: order_cancelled
customer_interests:
- rugby
- football
- baseball
price_usd:
- numeric:
- '>='
- 100
Resources:
mustafa-sadiq marked this conversation as resolved.
Show resolved Hide resolved
MyAwesomeFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/hello.zip
Handler: hello.handler
Runtime: python2.7

Events:
NotificationTopic:
Type: SNS
Properties:
Topic: topicArn
Region: region
FilterPolicy:
store:
- example_corp
event:
- anything-but: order_cancelled
customer_interests:
- rugby
- football
- baseball
price_usd:
- numeric:
- '>='
- 100
FilterPolicyScope: MessageAttributes
63 changes: 32 additions & 31 deletions tests/translator/input/sns_existing_sqs.yaml
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
Resources:
SaveNotificationFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/notifications.zip
Handler: index.save_notification
Runtime: nodejs12.x
Events:
NotificationTopic:
Type: SNS
Properties:
Topic: !Ref Notifications
SqsSubscription:
QueueUrl: !Ref Queue
QueueArn: !GetAtt Queue.Arn
QueuePolicyLogicalId: NotificationA
BatchSize: 8
Enabled: true
FilterPolicy:
store:
- example_corp
price_usd:
- numeric:
- '>='
- 100

Notifications:
Type: AWS::SNS::Topic

Queue:
Type: AWS::SQS::Queue
Resources:
SaveNotificationFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/notifications.zip
Handler: index.save_notification
Runtime: nodejs12.x
Events:
NotificationTopic:
Type: SNS
Properties:
Topic: !Ref Notifications
SqsSubscription:
QueueUrl: !Ref Queue
QueueArn: !GetAtt Queue.Arn
QueuePolicyLogicalId: NotificationA
BatchSize: 8
Enabled: true
FilterPolicy:
store:
- example_corp
price_usd:
- numeric:
- '>='
- 100
FilterPolicyScope: MessageAttributes

Notifications:
Type: AWS::SNS::Topic

Queue:
Type: AWS::SQS::Queue
83 changes: 42 additions & 41 deletions tests/translator/input/sns_intrinsics.yaml
Original file line number Diff line number Diff line change
@@ -1,41 +1,42 @@
Parameters:
SnsRegion:
Type: String
Default: us-east-1

Conditions:
MyCondition:
Fn::Equals:
- true
- false

Resources:
SaveNotificationFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/notifications.zip
Handler: index.save_notification
Runtime: nodejs12.x
Events:
NotificationTopic:
Type: SNS
Properties:
FilterPolicy:
Fn::If:
- MyCondition
- price_usd:
- numeric:
- '>='
- 100
- price_usd:
- numeric:
- <
- 100
Region:
Ref: SnsRegion
SqsSubscription: true
Topic:
Ref: Notifications

Notifications:
Type: AWS::SNS::Topic
Parameters:
SnsRegion:
Type: String
Default: us-east-1

Conditions:
MyCondition:
Fn::Equals:
- true
- false

Resources:
SaveNotificationFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/notifications.zip
Handler: index.save_notification
Runtime: nodejs12.x
Events:
NotificationTopic:
Type: SNS
Properties:
FilterPolicy:
Fn::If:
- MyCondition
- price_usd:
- numeric:
- '>='
- 100
- price_usd:
- numeric:
- <
- 100
FilterPolicyScope: MessageAttributes
Region:
Ref: SnsRegion
SqsSubscription: true
Topic:
Ref: Notifications

Notifications:
Type: AWS::SNS::Topic
Loading