test_boto_sns.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. # -*- coding: utf-8 -*-
  2. """
  3. Tests for the boto_sns state
  4. """
  5. # Import Python libs
  6. from __future__ import absolute_import, print_function, unicode_literals
  7. import re
  8. # Import Salt Testing libs
  9. from tests.support.case import ModuleCase
  10. from tests.support.unit import skipIf
  11. from tests.support.mixins import SaltReturnAssertsMixin
  12. # Import 3rd-party libs
  13. try:
  14. import boto
  15. NO_BOTO_MODULE = False
  16. except ImportError:
  17. NO_BOTO_MODULE = True
  18. @skipIf(
  19. NO_BOTO_MODULE,
  20. 'Please install the boto library before running boto integration tests.'
  21. )
  22. class BotoSNSTest(ModuleCase, SaltReturnAssertsMixin):
  23. def setUp(self):
  24. try:
  25. boto.connect_iam()
  26. except boto.exception.NoAuthHandlerFound:
  27. self.skipTest('Please setup boto AWS credentials before running boto integration tests.')
  28. # The name of the topic you want to create.
  29. # Constraints: Topic names must be made up of only uppercase and
  30. # lowercase ASCII letters, numbers, underscores, and hyphens,
  31. # and must be between 1 and 256 characters long.
  32. # http://docs.aws.amazon.com/sns/latest/api/API_CreateTopic.html
  33. self.topic_name = re.sub(r'[^a-zA-Z_-]', '_', self.id())[0:256]
  34. self.run_function('boto_sns.delete', name=self.topic_name)
  35. def tearDown(self):
  36. self.run_function('boto_sns.delete', name=self.topic_name)
  37. def test_present_new_topic_no_subscriptions(self):
  38. ret = self.run_state('boto_sns.present',
  39. name=self.topic_name)
  40. self.assertSaltTrueReturn(ret)
  41. self.assertInSaltReturn(self.topic_name, ret, 'name')
  42. self.assertInSaltComment(
  43. 'AWS SNS topic {0} created.'.format(self.topic_name),
  44. ret
  45. )
  46. self.assertSaltStateChangesEqual(ret,
  47. {'old': None, 'new': {'topic': self.topic_name, 'subscriptions': []}})
  48. def test_present_new_topic_with_subscriptions(self):
  49. ret = self.run_state(
  50. 'boto_sns.present',
  51. name=self.topic_name,
  52. subscriptions=[
  53. {'protocol': 'https',
  54. 'endpoint': 'https://www.example.com/sns/endpoint'
  55. },
  56. {'protocol': 'https',
  57. 'endpoint': 'https://www.example.com/sns/endpoint-2'
  58. }
  59. ]
  60. )
  61. self.assertSaltTrueReturn(ret)
  62. self.assertSaltStateChangesEqual(
  63. ret,
  64. {'old': None,
  65. 'new': {
  66. 'topic': self.topic_name,
  67. 'subscriptions': [
  68. {'protocol': 'https',
  69. 'endpoint': 'https://www.example.com/sns/endpoint'
  70. },
  71. {'protocol': 'https',
  72. 'endpoint': 'https://www.example.com/sns/endpoint-2'
  73. }
  74. ]
  75. }
  76. }
  77. )
  78. self.assertInSaltComment(
  79. 'AWS SNS subscription https:https://www.example.com/sns/endpoint set on topic {0}.'
  80. .format(self.topic_name),
  81. ret
  82. )
  83. self.assertInSaltComment(
  84. 'AWS SNS subscription https:https://www.example.com/sns/endpoint-2 set on topic {0}.'
  85. .format(self.topic_name),
  86. ret
  87. )
  88. self.assertSubscriptionInTopic({
  89. 'Protocol': 'https',
  90. 'Endpoint': 'https://www.example.com/sns/endpoint'
  91. }, self.topic_name)
  92. self.assertSubscriptionInTopic({
  93. 'Protocol': 'https',
  94. 'Endpoint': 'https://www.example.com/sns/endpoint-2'
  95. }, self.topic_name)
  96. def test_present_is_idempotent(self):
  97. self.run_state(
  98. 'boto_sns.present',
  99. name=self.topic_name,
  100. subscriptions=[
  101. {'protocol': 'https',
  102. 'endpoint': 'https://www.example.com/sns/endpoint'
  103. }
  104. ]
  105. )
  106. ret = self.run_state(
  107. 'boto_sns.present',
  108. name=self.topic_name,
  109. subscriptions=[
  110. {'protocol': 'https',
  111. 'endpoint': 'https://www.example.com/sns/endpoint'
  112. }
  113. ]
  114. )
  115. self.assertSaltTrueReturn(ret)
  116. self.assertInSaltReturn(self.topic_name, ret, 'name')
  117. self.assertInSaltComment(
  118. 'AWS SNS topic {0} present.'.format(self.topic_name),
  119. ret
  120. )
  121. self.assertInSaltComment(
  122. 'AWS SNS subscription https:https://www.example.com/sns/endpoint already set on topic {0}.'
  123. .format(self.topic_name),
  124. ret
  125. )
  126. self.assertSaltStateChangesEqual(ret, {})
  127. def test_present_add_subscription_to_existing_topic_with_no_subscription(self):
  128. self.run_state('boto_sns.present', name=self.topic_name)
  129. ret = self.run_state(
  130. 'boto_sns.present',
  131. name=self.topic_name,
  132. subscriptions=[
  133. {'protocol': 'https',
  134. 'endpoint': 'https://www.example.com/sns/endpoint'
  135. }
  136. ]
  137. )
  138. self.assertSaltTrueReturn(ret)
  139. self.assertSaltStateChangesEqual(
  140. ret,
  141. {'old': None,
  142. 'new': {'subscriptions': [
  143. {'protocol': 'https',
  144. 'endpoint': 'https://www.example.com/sns/endpoint'
  145. }
  146. ]
  147. }
  148. }
  149. )
  150. self.assertInSaltComment(
  151. 'AWS SNS subscription https:https://www.example.com/sns/endpoint set on topic {0}.'
  152. .format(self.topic_name),
  153. ret
  154. )
  155. self.assertSubscriptionInTopic({
  156. 'Protocol': 'https',
  157. 'Endpoint': 'https://www.example.com/sns/endpoint'
  158. }, self.topic_name)
  159. def test_present_add_new_subscription_to_existing_topic_with_subscriptions(self):
  160. self.run_state(
  161. 'boto_sns.present',
  162. name=self.topic_name,
  163. subscriptions=[
  164. {'protocol': 'https',
  165. 'endpoint': 'https://www.example.com/sns/endpoint'
  166. }
  167. ]
  168. )
  169. ret = self.run_state(
  170. 'boto_sns.present',
  171. name=self.topic_name,
  172. subscriptions=[
  173. {'protocol': 'https',
  174. 'endpoint': 'https://www.example.com/sns/endpoint-2'
  175. }
  176. ]
  177. )
  178. self.assertSaltTrueReturn(ret)
  179. self.assertSaltStateChangesEqual(
  180. ret,
  181. {'old': None,
  182. 'new': {
  183. 'subscriptions': [
  184. {'protocol': 'https',
  185. 'endpoint': 'https://www.example.com/sns/endpoint-2'
  186. }
  187. ]
  188. }
  189. }
  190. )
  191. self.assertInSaltComment(
  192. 'AWS SNS subscription https:https://www.example.com/sns/endpoint-2 set on topic {0}.'
  193. .format(self.topic_name),
  194. ret
  195. )
  196. self.assertSubscriptionInTopic({
  197. 'Protocol': 'https',
  198. 'Endpoint': 'https://www.example.com/sns/endpoint'
  199. }, self.topic_name)
  200. self.assertSubscriptionInTopic({
  201. 'Protocol': 'https',
  202. 'Endpoint': 'https://www.example.com/sns/endpoint-2'
  203. }, self.topic_name)
  204. def test_present_test_mode_no_subscriptions(self):
  205. ret = self.run_state('boto_sns.present',
  206. name=self.topic_name,
  207. test=True)
  208. self.assertSaltNoneReturn(ret)
  209. self.assertInSaltReturn(self.topic_name, ret, 'name')
  210. self.assertInSaltComment(
  211. 'AWS SNS topic {0} is set to be created.'.format(self.topic_name),
  212. ret
  213. )
  214. self.assertSaltStateChangesEqual(ret, {})
  215. ret = self.run_function('boto_sns.exists', name=self.topic_name)
  216. self.assertFalse(ret)
  217. def test_present_test_mode_with_subscriptions(self):
  218. self.run_state('boto_sns.present', name=self.topic_name)
  219. ret = self.run_state(
  220. 'boto_sns.present',
  221. name=self.topic_name,
  222. subscriptions=[
  223. {'protocol': 'https',
  224. 'endpoint': 'https://www.example.com/sns/endpoint'
  225. }
  226. ],
  227. test=True
  228. )
  229. self.assertSaltNoneReturn(ret)
  230. self.assertSaltStateChangesEqual(ret, {})
  231. self.assertInSaltComment(
  232. 'AWS SNS subscription https:https://www.example.com/sns/endpoint to be set on topic {0}.'
  233. .format(self.topic_name),
  234. ret
  235. )
  236. ret = self.run_function(
  237. 'boto_sns.get_all_subscriptions_by_topic',
  238. name=self.topic_name
  239. )
  240. self.assertEqual([], ret)
  241. def test_absent_not_exist(self):
  242. ret = self.run_state('boto_sns.absent',
  243. name=self.topic_name)
  244. self.assertSaltTrueReturn(ret)
  245. self.assertInSaltReturn(self.topic_name, ret, 'name')
  246. self.assertInSaltComment(
  247. 'AWS SNS topic {0} does not exist.'.format(self.topic_name),
  248. ret
  249. )
  250. self.assertSaltStateChangesEqual(ret, {})
  251. def test_absent_already_exists(self):
  252. self.run_state('boto_sns.present',
  253. name=self.topic_name)
  254. ret = self.run_state('boto_sns.absent',
  255. name=self.topic_name)
  256. self.assertSaltTrueReturn(ret)
  257. self.assertInSaltReturn(self.topic_name, ret, 'name')
  258. self.assertInSaltComment(
  259. 'AWS SNS topic {0} does not exist.'.format(self.topic_name),
  260. ret
  261. )
  262. self.assertSaltStateChangesEqual(
  263. ret, {'new': None, 'old': {'topic': self.topic_name}})
  264. def test_absent_test_mode(self):
  265. self.run_state('boto_sns.present', name=self.topic_name)
  266. ret = self.run_state('boto_sns.absent',
  267. name=self.topic_name,
  268. test=True)
  269. self.assertSaltNoneReturn(ret)
  270. self.assertInSaltReturn(self.topic_name, ret, 'name')
  271. self.assertInSaltComment(
  272. 'AWS SNS topic {0} is set to be removed.'.format(self.topic_name),
  273. ret
  274. )
  275. self.assertSaltStateChangesEqual(ret, {})
  276. ret = self.run_function('boto_sns.exists', name=self.topic_name)
  277. self.assertTrue(ret)
  278. def assertSubscriptionInTopic(self, subscription, topic_name):
  279. ret = self.run_function(
  280. 'boto_sns.get_all_subscriptions_by_topic',
  281. name=topic_name
  282. )
  283. for _subscription in ret:
  284. try:
  285. self.assertDictContainsSubset(subscription, _subscription)
  286. return True
  287. except AssertionError:
  288. continue
  289. raise self.failureException(
  290. 'Subscription {0} not found in topic {1} subscriptions: {2}'
  291. .format(subscription, topic_name, ret)
  292. )