1+ import json
12import logging
23import re
34
1920 topicARN ,
2021 topicName ,
2122)
22- from localstack .services .sns .v2 .models import SnsStore , Topic , create_topic , sns_stores
23+ from localstack .services .sns .v2 .models import SnsStore , Topic , sns_stores
2324from localstack .utils .aws .arns import ArnData , parse_arn , sns_topic_arn
2425from localstack .utils .collections import PaginatedList
2526
@@ -41,18 +42,18 @@ def create_topic(
4142 ** kwargs ,
4243 ) -> CreateTopicResponse :
4344 store = self .get_store (context .account_id , context .region )
44- topic_ARN = sns_topic_arn (
45+ topic_arn = sns_topic_arn (
4546 topic_name = name , region_name = context .region , account_id = context .account_id
4647 )
47- topic : Topic = store .topics .get (topic_ARN )
48+ topic : Topic = store .topics .get (topic_arn )
4849 attributes = attributes or {}
4950 if topic :
5051 attrs = topic ["attributes" ]
5152 for k , v in attributes .values ():
5253 if not attrs .get (k ) or not attrs .get (k ) == v :
5354 # TODO:
5455 raise InvalidParameterException ("Fix this Exception message and type" )
55- return CreateTopicResponse (TopicArn = topic_ARN )
56+ return CreateTopicResponse (TopicArn = topic_arn )
5657
5758 attributes = attributes or {}
5859 if attributes .get ("FifoTopic" ) and attributes ["FifoTopic" ].lower () == "true" :
@@ -64,19 +65,16 @@ def create_topic(
6465 )
6566 else :
6667 # AWS does not seem to save explicit settings of fifo = false
67- try :
68- attributes .pop ("FifoTopic" , None )
69- except KeyError :
70- pass
68+ attributes .pop ("FifoTopic" , None )
7169 name_match = re .match (SNS_TOPIC_NAME_PATTERN , name )
7270 if not name_match :
7371 raise InvalidParameterException ("Invalid parameter: Topic Name" )
7472
75- topic = create_topic (name = name , attributes = attributes , context = context )
76- store .topics [topic_ARN ] = topic
73+ topic = _create_topic (name = name , attributes = attributes , context = context )
74+ store .topics [topic_arn ] = topic
7775 # todo: tags
7876
79- return CreateTopicResponse (TopicArn = topic_ARN )
77+ return CreateTopicResponse (TopicArn = topic_arn )
8078
8179 def get_topic_attributes (
8280 self , context : RequestContext , topic_arn : topicARN , ** kwargs
@@ -122,12 +120,13 @@ def set_topic_attributes(
122120 def get_store (account_id : str , region : str ) -> SnsStore :
123121 return sns_stores [account_id ][region ]
124122
123+ # TODO: reintroduce multi-region parameter (latest before final migration from v1)
125124 @staticmethod
126125 def _get_topic (arn : str , context : RequestContext ) -> Topic :
127126 """
128127 :param arn: the Topic ARN
129128 :param context: the RequestContext of the request
130- :return: the Moto model Topic
129+ :return: the model Topic
131130 """
132131 arn_data = parse_and_validate_topic_arn (arn )
133132 if context .region != arn_data ["region" ]:
@@ -148,3 +147,68 @@ def parse_and_validate_topic_arn(topic_arn: str | None) -> ArnData:
148147 raise InvalidParameterException (
149148 f"Invalid parameter: TopicArn Reason: An ARN must have at least 6 elements, not { count } "
150149 )
150+
151+
152+ def _create_topic (name : str , attributes : dict , context : RequestContext ) -> Topic :
153+ topic_arn = sns_topic_arn (
154+ topic_name = name , region_name = context .region , account_id = context .account_id
155+ )
156+ topic : Topic = {
157+ "name" : name ,
158+ "arn" : topic_arn ,
159+ "attributes" : {},
160+ }
161+ attrs = _default_attributes (topic , context )
162+ attrs .update (attributes or {})
163+ topic ["attributes" ] = attrs
164+
165+ return topic
166+
167+
168+ def _default_attributes (topic : Topic , context : RequestContext ) -> TopicAttributesMap :
169+ default_attributes = {
170+ "DisplayName" : "" ,
171+ "Owner" : context .account_id ,
172+ "Policy" : _create_default_topic_policy (topic , context ),
173+ "SubscriptionsConfirmed" : "0" ,
174+ "SubscriptionsDeleted" : "0" ,
175+ "SubscriptionsPending" : "0" ,
176+ "TopicArn" : topic ["arn" ],
177+ }
178+ if topic ["name" ].endswith (".fifo" ):
179+ default_attributes .update (
180+ {
181+ "ContentBasedDeduplication" : "false" ,
182+ "FifoTopic" : "false" ,
183+ "SignatureVersion" : "2" ,
184+ }
185+ )
186+ return default_attributes
187+
188+
189+ def _create_default_topic_policy (topic : Topic , context : RequestContext ) -> str :
190+ return json .dumps (
191+ {
192+ "Version" : "2008-10-17" ,
193+ "Id" : "__default_policy_ID" ,
194+ "Statement" : [
195+ {
196+ "Effect" : "Allow" ,
197+ "Sid" : "__default_statement_ID" ,
198+ "Principal" : {"AWS" : "*" },
199+ "Action" : [
200+ "SNS:GetTopicAttributes" ,
201+ "SNS:SetTopicAttributes" ,
202+ "SNS:AddPermission" ,
203+ "SNS:RemovePermission" ,
204+ "SNS:DeleteTopic" ,
205+ "SNS:Subscribe" ,
206+ "SNS:ListSubscriptionsByTopic" ,
207+ "SNS:Publish" ,
208+ ],
209+ "Resource" : topic ["arn" ],
210+ "Condition" : {"StringEquals" : {"AWS:SourceOwner" : context .account_id }},
211+ }
212+ ],
213+ }
214+ )
0 commit comments