1111from mypy_boto3_sns .client import SNSClient
1212from mypy_boto3_sts .client import STSClient
1313
14+ from awspub .common import _get_regions
1415from awspub .context import Context
1516from awspub .exceptions import AWSAuthorizationException , AWSNotificationException
17+ from awspub .s3 import S3
1618
1719logger = logging .getLogger (__name__ )
1820
@@ -23,13 +25,13 @@ class SNSNotification(object):
2325 structuring rules for SNS notification JSON
2426 """
2527
26- def __init__ (self , context : Context , image_name : str , region_name : str ):
28+ def __init__ (self , context : Context , image_name : str ):
2729 """
2830 Construct a message and verify that it is valid
2931 """
3032 self ._ctx : Context = context
3133 self ._image_name : str = image_name
32- self ._region_name : str = region_name
34+ self ._s3 : S3 = S3 ( context )
3335
3436 @property
3537 def conf (self ) -> List [Dict [str , Any ]]:
@@ -38,7 +40,21 @@ def conf(self) -> List[Dict[str, Any]]:
3840 """
3941 return self ._ctx .conf ["images" ][self ._image_name ]["sns" ]
4042
41- def _get_topic_arn (self , topic_name : str ) -> str :
43+ def _sns_regions (self , topic_config : Dict [Any , Any ]) -> List [str ]:
44+ """
45+ Get the sns regions. Either configured in the sns configuration
46+ or all available regions.
47+ If a region is listed that is not available in the currently used partition,
48+ that region will be ignored (eg. having us-east-1 configured but running in the aws-cn
49+ partition doesn't include us-east-1 here).
50+ """
51+
52+ regions_configured = topic_config ["regions" ] if "regions" in topic_config else []
53+ sns_regions = _get_regions (self ._s3 .bucket_region , regions_configured )
54+
55+ return sns_regions
56+
57+ def _get_topic_arn (self , topic_name : str , region_name : str ) -> str :
4258 """
4359 Calculate topic ARN based on partition, region, account and topic name
4460 :param topic_name: Name of topic
@@ -49,40 +65,41 @@ def _get_topic_arn(self, topic_name: str) -> str:
4965 :rtype: str
5066 """
5167
52- stsclient : STSClient = boto3 .client ("sts" , region_name = self . _region_name )
68+ stsclient : STSClient = boto3 .client ("sts" , region_name = region_name )
5369 resp = stsclient .get_caller_identity ()
5470
5571 account = resp ["Account" ]
5672 # resp["Arn"] has string format "arn:partition:iam::accountnumber:user/iam_role"
5773 partition = resp ["Arn" ].rsplit (":" )[1 ]
5874
59- return f"arn:{ partition } :sns:{ self . _region_name } :{ account } :{ topic_name } "
75+ return f"arn:{ partition } :sns:{ region_name } :{ account } :{ topic_name } "
6076
6177 def publish (self ) -> None :
6278 """
6379 send notification to subscribers
6480 """
6581
66- snsclient : SNSClient = boto3 .client ("sns" , region_name = self ._region_name )
67-
6882 for topic in self .conf :
6983 for topic_name , topic_config in topic .items ():
70- try :
71- snsclient .publish (
72- TopicArn = self ._get_topic_arn (topic_name ),
73- Subject = topic_config ["subject" ],
74- Message = json .dumps (topic_config ["message" ]),
75- MessageStructure = "json" ,
76- )
77- except ClientError as e :
78- exception_code : str = e .response ["Error" ]["Code" ]
79- if exception_code == "AuthorizationError" :
80- raise AWSAuthorizationException (
81- "Profile does not have a permission to send the SNS notification. Please review the policy."
84+ for region_name in self ._sns_regions (topic_config ):
85+ snsclient : SNSClient = boto3 .client ("sns" , region_name = region_name )
86+ try :
87+ snsclient .publish (
88+ TopicArn = self ._get_topic_arn (topic_name , region_name ),
89+ Subject = topic_config ["subject" ],
90+ Message = json .dumps (topic_config ["message" ]),
91+ MessageStructure = "json" ,
8292 )
83- else :
84- raise AWSNotificationException (str (e ))
85- logger .info (
86- f"The SNS notification { topic_config ['subject' ]} "
87- f" for the topic { topic_name } in { self ._region_name } has been sent."
88- )
93+ except ClientError as e :
94+ exception_code : str = e .response ["Error" ]["Code" ]
95+ if exception_code == "AuthorizationError" :
96+ raise AWSAuthorizationException (
97+ "Profile does not have a permission to send the SNS notification."
98+ " Please review the policy."
99+ )
100+ else :
101+ raise AWSNotificationException (str (e ))
102+ logger .info (
103+ f"The SNS notification { topic_config ['subject' ]} "
104+ f" for the topic { topic_name } in { region_name } has been sent."
105+ )
0 commit comments