test_boto_cloudwatch_event.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. # -*- coding: utf-8 -*-
  2. # Import Python libs
  3. from __future__ import absolute_import, print_function, unicode_literals
  4. import random
  5. import string
  6. import logging
  7. # Import Salt Testing libs
  8. from tests.support.mixins import LoaderModuleMockMixin
  9. from tests.support.unit import skipIf, TestCase
  10. from tests.support.mock import (
  11. MagicMock,
  12. patch
  13. )
  14. # Import Salt libs
  15. import salt.config
  16. import salt.loader
  17. import salt.modules.boto_cloudwatch_event as boto_cloudwatch_event
  18. from salt.ext.six.moves import range # pylint: disable=import-error,redefined-builtin
  19. # Import 3rd-party libs
  20. # pylint: disable=import-error,no-name-in-module,unused-import
  21. try:
  22. import boto
  23. import boto3
  24. from botocore.exceptions import ClientError
  25. from botocore import __version__ as found_botocore_version
  26. HAS_BOTO = True
  27. except ImportError:
  28. HAS_BOTO = False
  29. # pylint: enable=import-error,no-name-in-module,unused-import
  30. log = logging.getLogger(__name__)
  31. def _has_required_boto():
  32. '''
  33. Returns True/False boolean depending on if Boto is installed and correct
  34. version.
  35. '''
  36. if not HAS_BOTO:
  37. return False
  38. else:
  39. return True
  40. if _has_required_boto():
  41. region = 'us-east-1'
  42. access_key = 'GKTADJGHEIQSXMKKRBJ08H'
  43. secret_key = 'askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs'
  44. conn_parameters = {'region': region, 'key': access_key, 'keyid': secret_key, 'profile': {}}
  45. error_message = 'An error occurred (101) when calling the {0} operation: Test-defined error'
  46. not_found_error = ClientError({
  47. 'Error': {
  48. 'Code': 'ResourceNotFoundException',
  49. 'Message': "Test-defined error"
  50. }
  51. }, 'msg')
  52. error_content = {
  53. 'Error': {
  54. 'Code': 101,
  55. 'Message': "Test-defined error"
  56. }
  57. }
  58. rule_name = 'test_thing_type'
  59. rule_desc = 'test_thing_type_desc'
  60. rule_sched = 'rate(20 min)'
  61. rule_arn = 'arn:::::rule/arn'
  62. rule_ret = dict(
  63. Arn=rule_arn,
  64. Description=rule_desc,
  65. EventPattern=None,
  66. Name=rule_name,
  67. RoleArn=None,
  68. ScheduleExpression=rule_sched,
  69. State='ENABLED'
  70. )
  71. create_rule_ret = dict(
  72. Name=rule_name,
  73. )
  74. target_ret = dict(
  75. Id='target1',
  76. )
  77. class BotoCloudWatchEventTestCaseBase(TestCase, LoaderModuleMockMixin):
  78. conn = None
  79. def setup_loader_modules(self):
  80. self.opts = opts = salt.config.DEFAULT_MINION_OPTS
  81. utils = salt.loader.utils(
  82. opts,
  83. whitelist=['boto3', 'args', 'systemd', 'path', 'platform'],
  84. context={})
  85. return {boto_cloudwatch_event: {'__utils__': utils}}
  86. def setUp(self):
  87. super(BotoCloudWatchEventTestCaseBase, self).setUp()
  88. boto_cloudwatch_event.__init__(self.opts)
  89. del self.opts
  90. # Set up MagicMock to replace the boto3 session
  91. # connections keep getting cached from prior tests, can't find the
  92. # correct context object to clear it. So randomize the cache key, to prevent any
  93. # cache hits
  94. conn_parameters['key'] = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(50))
  95. self.patcher = patch('boto3.session.Session')
  96. self.addCleanup(self.patcher.stop)
  97. self.addCleanup(delattr, self, 'patcher')
  98. mock_session = self.patcher.start()
  99. session_instance = mock_session.return_value
  100. self.conn = MagicMock()
  101. self.addCleanup(delattr, self, 'conn')
  102. session_instance.client.return_value = self.conn
  103. class BotoCloudWatchEventTestCaseMixin(object):
  104. pass
  105. @skipIf(HAS_BOTO is False, 'The boto module must be installed.')
  106. class BotoCloudWatchEventTestCase(BotoCloudWatchEventTestCaseBase, BotoCloudWatchEventTestCaseMixin):
  107. '''
  108. TestCase for salt.modules.boto_cloudwatch_event module
  109. '''
  110. def test_that_when_checking_if_a_rule_exists_and_a_rule_exists_the_rule_exists_method_returns_true(self):
  111. '''
  112. Tests checking event existence when the event already exists
  113. '''
  114. self.conn.list_rules.return_value = {'Rules': [rule_ret]}
  115. result = boto_cloudwatch_event.exists(Name=rule_name, **conn_parameters)
  116. self.assertTrue(result['exists'])
  117. def test_that_when_checking_if_a_rule_exists_and_a_rule_does_not_exist_the_exists_method_returns_false(self):
  118. '''
  119. Tests checking rule existence when the rule does not exist
  120. '''
  121. self.conn.list_rules.return_value = {'Rules': []}
  122. result = boto_cloudwatch_event.exists(Name=rule_name, **conn_parameters)
  123. self.assertFalse(result['exists'])
  124. def test_that_when_checking_if_a_rule_exists_and_boto3_returns_an_error_the_rule_exists_method_returns_error(self):
  125. '''
  126. Tests checking rule existence when boto returns an error
  127. '''
  128. self.conn.list_rules.side_effect = ClientError(error_content, 'list_rules')
  129. result = boto_cloudwatch_event.exists(Name=rule_name, **conn_parameters)
  130. self.assertEqual(result.get('error', {}).get('message'), error_message.format('list_rules'))
  131. def test_that_when_describing_rule_and_rule_exists_the_describe_rule_method_returns_rule(self):
  132. '''
  133. Tests describe rule for an existing rule
  134. '''
  135. self.conn.describe_rule.return_value = rule_ret
  136. result = boto_cloudwatch_event.describe(Name=rule_name, **conn_parameters)
  137. self.assertEqual(result.get('rule'), rule_ret)
  138. def test_that_when_describing_rule_and_rule_does_not_exists_the_describe_method_returns_none(self):
  139. '''
  140. Tests describe rule for an non existent rule
  141. '''
  142. self.conn.describe_rule.side_effect = not_found_error
  143. result = boto_cloudwatch_event.describe(Name=rule_name, **conn_parameters)
  144. self.assertNotEqual(result.get('error'), None)
  145. def test_that_when_describing_rule_and_boto3_returns_error_the_describe_method_returns_error(self):
  146. self.conn.describe_rule.side_effect = ClientError(error_content, 'describe_rule')
  147. result = boto_cloudwatch_event.describe(Name=rule_name, **conn_parameters)
  148. self.assertEqual(result.get('error', {}).get('message'), error_message.format('describe_rule'))
  149. def test_that_when_creating_a_rule_succeeds_the_create_rule_method_returns_true(self):
  150. '''
  151. tests True when rule created
  152. '''
  153. self.conn.put_rule.return_value = create_rule_ret
  154. result = boto_cloudwatch_event.create_or_update(Name=rule_name,
  155. Description=rule_desc,
  156. ScheduleExpression=rule_sched,
  157. **conn_parameters)
  158. self.assertTrue(result['created'])
  159. def test_that_when_creating_a_rule_fails_the_create_method_returns_error(self):
  160. '''
  161. tests False when rule not created
  162. '''
  163. self.conn.put_rule.side_effect = ClientError(error_content, 'put_rule')
  164. result = boto_cloudwatch_event.create_or_update(Name=rule_name,
  165. Description=rule_desc,
  166. ScheduleExpression=rule_sched,
  167. **conn_parameters)
  168. self.assertEqual(result.get('error', {}).get('message'), error_message.format('put_rule'))
  169. def test_that_when_deleting_a_rule_succeeds_the_delete_method_returns_true(self):
  170. '''
  171. tests True when delete rule succeeds
  172. '''
  173. self.conn.delete_rule.return_value = {}
  174. result = boto_cloudwatch_event.delete(Name=rule_name, **conn_parameters)
  175. self.assertTrue(result.get('deleted'))
  176. self.assertEqual(result.get('error'), None)
  177. def test_that_when_deleting_a_rule_fails_the_delete_method_returns_error(self):
  178. '''
  179. tests False when delete rule fails
  180. '''
  181. self.conn.delete_rule.side_effect = ClientError(error_content, 'delete_rule')
  182. result = boto_cloudwatch_event.delete(Name=rule_name, **conn_parameters)
  183. self.assertFalse(result.get('deleted'))
  184. self.assertEqual(result.get('error', {}).get('message'), error_message.format('delete_rule'))
  185. def test_that_when_listing_targets_and_rule_exists_the_list_targets_method_returns_targets(self):
  186. '''
  187. Tests listing targets for an existing rule
  188. '''
  189. self.conn.list_targets_by_rule.return_value = {'Targets': [target_ret]}
  190. result = boto_cloudwatch_event.list_targets(Rule=rule_name, **conn_parameters)
  191. self.assertEqual(result.get('targets'), [target_ret])
  192. def test_that_when_listing_targets_and_rule_does_not_exist_the_list_targets_method_returns_error(self):
  193. '''
  194. Tests list targets for an non existent rule
  195. '''
  196. self.conn.list_targets_by_rule.side_effect = not_found_error
  197. result = boto_cloudwatch_event.list_targets(Rule=rule_name, **conn_parameters)
  198. self.assertNotEqual(result.get('error'), None)
  199. def test_that_when_putting_targets_succeeds_the_put_target_method_returns_no_failures(self):
  200. '''
  201. tests None when targets added
  202. '''
  203. self.conn.put_targets.return_value = {'FailedEntryCount': 0}
  204. result = boto_cloudwatch_event.put_targets(Rule=rule_name,
  205. Targets=[],
  206. **conn_parameters)
  207. self.assertIsNone(result['failures'])
  208. def test_that_when_putting_targets_fails_the_put_targets_method_returns_error(self):
  209. '''
  210. tests False when thing type not created
  211. '''
  212. self.conn.put_targets.side_effect = ClientError(error_content, 'put_targets')
  213. result = boto_cloudwatch_event.put_targets(Rule=rule_name,
  214. Targets=[],
  215. **conn_parameters)
  216. self.assertEqual(result.get('error', {}).get('message'), error_message.format('put_targets'))
  217. def test_that_when_removing_targets_succeeds_the_remove_targets_method_returns_true(self):
  218. '''
  219. tests True when remove targets succeeds
  220. '''
  221. self.conn.remove_targets.return_value = {'FailedEntryCount': 0}
  222. result = boto_cloudwatch_event.remove_targets(Rule=rule_name, Ids=[], **conn_parameters)
  223. self.assertIsNone(result['failures'])
  224. self.assertEqual(result.get('error'), None)
  225. def test_that_when_removing_targets_fails_the_remove_targets_method_returns_error(self):
  226. '''
  227. tests False when remove targets fails
  228. '''
  229. self.conn.remove_targets.side_effect = ClientError(error_content, 'remove_targets')
  230. result = boto_cloudwatch_event.remove_targets(Rule=rule_name, Ids=[], **conn_parameters)
  231. self.assertEqual(result.get('error', {}).get('message'), error_message.format('remove_targets'))