test_plugin.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. from functools import cached_property
  2. from unittest.mock import patch
  3. import orjson
  4. import pytest
  5. from botocore.client import ClientError
  6. from sentry.testutils.cases import PluginTestCase
  7. from sentry_plugins.amazon_sqs.plugin import AmazonSQSPlugin
  8. class AmazonSQSPluginTest(PluginTestCase):
  9. @cached_property
  10. def plugin(self):
  11. return AmazonSQSPlugin()
  12. def test_conf_key(self):
  13. assert self.plugin.conf_key == "amazon-sqs"
  14. def test_entry_point(self):
  15. self.assertPluginInstalled("amazon_sqs", self.plugin)
  16. def run_test(self):
  17. self.plugin.set_option("access_key", "access-key", self.project)
  18. self.plugin.set_option("secret_key", "secret-key", self.project)
  19. self.plugin.set_option("region", "us-east-1", self.project)
  20. self.plugin.set_option(
  21. "queue_url", "https://sqs.us-east-1.amazonaws.com/12345678/myqueue", self.project
  22. )
  23. event = self.store_event(
  24. data={
  25. "sentry.interfaces.Exception": {"type": "ValueError", "value": "foo bar"},
  26. "sentry.interfaces.User": {"id": "1", "email": "foo@example.com"},
  27. "type": "error",
  28. "metadata": {"type": "ValueError", "value": "foo bar"},
  29. },
  30. project_id=self.project.id,
  31. )
  32. with self.options({"system.url-prefix": "http://example.com"}):
  33. self.plugin.post_process(event)
  34. return event
  35. @patch("boto3.client")
  36. def test_simple_notification(self, mock_client):
  37. event = self.run_test()
  38. mock_client.assert_called_once_with(
  39. service_name="sqs",
  40. region_name="us-east-1",
  41. aws_access_key_id="access-key",
  42. aws_secret_access_key="secret-key",
  43. )
  44. mock_client.return_value.send_message.assert_called_once_with(
  45. QueueUrl="https://sqs.us-east-1.amazonaws.com/12345678/myqueue",
  46. MessageBody=orjson.dumps(
  47. self.plugin.get_event_payload(event), option=orjson.OPT_UTC_Z
  48. ).decode(),
  49. )
  50. @patch("sentry_plugins.amazon_sqs.plugin.logger")
  51. @patch("boto3.client")
  52. def test_token_error(self, mock_client, logger):
  53. mock_client.return_value.send_message.side_effect = ClientError(
  54. {"Error": {"Code": "Hello", "Message": "hello"}}, "SendMessage"
  55. )
  56. with pytest.raises(ClientError):
  57. self.run_test()
  58. assert len(logger.info.call_args_list) == 0
  59. mock_client.return_value.send_message.side_effect = ClientError(
  60. {"Error": {"Code": "AccessDenied", "Message": "Hello"}}, "SendMessage"
  61. )
  62. self.run_test()
  63. assert len(logger.info.call_args_list) == 1
  64. assert (
  65. logger.info.call_args_list[0][0][0] == "sentry_plugins.amazon_sqs.access_token_invalid"
  66. )
  67. @patch("sentry_plugins.amazon_sqs.plugin.logger")
  68. @patch("boto3.client")
  69. def test_message_group_error(self, mock_client, logger):
  70. mock_client.return_value.send_message.side_effect = ClientError(
  71. {
  72. "Error": {
  73. "Code": "MissingParameter",
  74. "Message": "The request must contain the parameter MessageGroupId.",
  75. }
  76. },
  77. "SendMessage",
  78. )
  79. self.run_test()
  80. assert len(logger.info.call_args_list) == 1
  81. assert (
  82. logger.info.call_args_list[0][0][0]
  83. == "sentry_plugins.amazon_sqs.missing_message_group_id"
  84. )
  85. @patch("uuid.uuid4")
  86. @patch("boto3.client")
  87. def test_pass_message_group_id(self, mock_client, mock_uuid):
  88. mock_uuid.return_value = self.get_mock_uuid()
  89. self.plugin.set_option("message_group_id", "my_group", self.project)
  90. event = self.run_test()
  91. mock_client.return_value.send_message.assert_called_once_with(
  92. QueueUrl="https://sqs.us-east-1.amazonaws.com/12345678/myqueue",
  93. MessageBody=orjson.dumps(
  94. self.plugin.get_event_payload(event), option=orjson.OPT_UTC_Z
  95. ).decode(),
  96. MessageGroupId="my_group",
  97. MessageDeduplicationId="abc123",
  98. )
  99. @patch("boto3.client")
  100. def test_use_s3_bucket(self, mock_client):
  101. self.plugin.set_option("s3_bucket", "my_bucket", self.project)
  102. event = self.run_test()
  103. date = event.datetime.strftime("%Y-%m-%d")
  104. key = f"{event.project.slug}/{date}/{event.event_id}"
  105. mock_client.return_value.send_message.assert_called_once_with(
  106. QueueUrl="https://sqs.us-east-1.amazonaws.com/12345678/myqueue",
  107. MessageBody=orjson.dumps(
  108. {
  109. "s3Url": f"https://my_bucket.s3-us-east-1.amazonaws.com/{key}",
  110. "eventID": event.event_id,
  111. },
  112. option=orjson.OPT_UTC_Z,
  113. ).decode(),
  114. )
  115. mock_client.return_value.put_object.assert_called_once_with(
  116. Bucket="my_bucket",
  117. Body=orjson.dumps(
  118. self.plugin.get_event_payload(event), option=orjson.OPT_UTC_Z
  119. ).decode(),
  120. Key=key,
  121. )
  122. @patch("sentry_plugins.amazon_sqs.plugin.logger")
  123. @patch("boto3.client")
  124. @pytest.mark.skip(reason="https://github.com/getsentry/sentry/issues/44858")
  125. def test_invalid_s3_bucket(self, mock_client, logger):
  126. self.plugin.set_option("s3_bucket", "bad_bucket", self.project)
  127. mock_client.return_value.put_object.side_effect = ClientError(
  128. {"Error": {"Code": "NoSuchBucket"}},
  129. "PutObject",
  130. )
  131. self.run_test()
  132. assert len(logger.info.call_args_list) == 2
  133. assert logger.info.call_args_list[1][0][0] == "sentry_plugins.amazon_sqs.s3_bucket_invalid"