test_boto_elasticsearch_domain.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. # -*- coding: utf-8 -*-
  2. # Import Python libs
  3. from __future__ import absolute_import, print_function, unicode_literals
  4. import copy
  5. import logging
  6. import random
  7. import string
  8. # Import Salt Testing libs
  9. from tests.support.mixins import LoaderModuleMockMixin
  10. from tests.support.unit import skipIf, TestCase
  11. from tests.support.mock import (
  12. MagicMock,
  13. patch
  14. )
  15. # Import Salt libs
  16. from salt.ext import six
  17. import salt.loader
  18. from salt.utils.versions import LooseVersion
  19. import salt.modules.boto_elasticsearch_domain as boto_elasticsearch_domain
  20. # Import 3rd-party libs
  21. # pylint: disable=import-error,no-name-in-module
  22. try:
  23. import boto3
  24. from botocore.exceptions import ClientError
  25. HAS_BOTO = True
  26. except ImportError:
  27. HAS_BOTO = False
  28. from salt.ext.six.moves import range
  29. # pylint: enable=import-error,no-name-in-module
  30. # the boto_elasticsearch_domain module relies on the connect_to_region() method
  31. # which was added in boto 2.8.0
  32. # https://github.com/boto/boto/commit/33ac26b416fbb48a60602542b4ce15dcc7029f12
  33. required_boto3_version = '1.2.1'
  34. def _has_required_boto():
  35. '''
  36. Returns True/False boolean depending on if Boto is installed and correct
  37. version.
  38. '''
  39. if not HAS_BOTO:
  40. return False
  41. elif LooseVersion(boto3.__version__) < LooseVersion(required_boto3_version):
  42. return False
  43. else:
  44. return True
  45. if _has_required_boto():
  46. region = 'us-east-1'
  47. access_key = 'GKTADJGHEIQSXMKKRBJ08H'
  48. secret_key = 'askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs'
  49. conn_parameters = {'region': region, 'key': access_key, 'keyid': secret_key, 'profile': {}}
  50. error_message = 'An error occurred (101) when calling the {0} operation: Test-defined error'
  51. error_content = {
  52. 'Error': {
  53. 'Code': 101,
  54. 'Message': "Test-defined error"
  55. }
  56. }
  57. not_found_error = ClientError({
  58. 'Error': {
  59. 'Code': 'ResourceNotFoundException',
  60. 'Message': "Test-defined error"
  61. }
  62. }, 'msg')
  63. domain_ret = dict(DomainName='testdomain',
  64. ElasticsearchClusterConfig={},
  65. EBSOptions={},
  66. AccessPolicies={},
  67. SnapshotOptions={},
  68. AdvancedOptions={})
  69. log = logging.getLogger(__name__)
  70. class BotoElasticsearchDomainTestCaseBase(TestCase, LoaderModuleMockMixin):
  71. conn = None
  72. def setup_loader_modules(self):
  73. self.opts = salt.config.DEFAULT_MINION_OPTS
  74. utils = salt.loader.utils(
  75. self.opts,
  76. whitelist=['boto3', 'args', 'systemd', 'path', 'platform'],
  77. context={})
  78. return {boto_elasticsearch_domain: {'__utils__': utils}}
  79. def setUp(self):
  80. super(BotoElasticsearchDomainTestCaseBase, self).setUp()
  81. boto_elasticsearch_domain.__init__(self.opts)
  82. del self.opts
  83. # Set up MagicMock to replace the boto3 session
  84. # connections keep getting cached from prior tests, can't find the
  85. # correct context object to clear it. So randomize the cache key, to prevent any
  86. # cache hits
  87. conn_parameters['key'] = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(50))
  88. self.patcher = patch('boto3.session.Session')
  89. self.addCleanup(self.patcher.stop)
  90. self.addCleanup(delattr, self, 'patcher')
  91. mock_session = self.patcher.start()
  92. session_instance = mock_session.return_value
  93. self.conn = MagicMock()
  94. self.addCleanup(delattr, self, 'conn')
  95. session_instance.client.return_value = self.conn
  96. class BotoElasticsearchDomainTestCaseMixin(object):
  97. pass
  98. @skipIf(True, 'Skip these tests while investigating failures')
  99. @skipIf(HAS_BOTO is False, 'The boto module must be installed.')
  100. @skipIf(_has_required_boto() is False, 'The boto3 module must be greater than'
  101. ' or equal to version {0}'
  102. .format(required_boto3_version))
  103. class BotoElasticsearchDomainTestCase(BotoElasticsearchDomainTestCaseBase, BotoElasticsearchDomainTestCaseMixin):
  104. '''
  105. TestCase for salt.modules.boto_elasticsearch_domain module
  106. '''
  107. def test_that_when_checking_if_a_domain_exists_and_a_domain_exists_the_domain_exists_method_returns_true(self):
  108. '''
  109. Tests checking domain existence when the domain already exists
  110. '''
  111. result = boto_elasticsearch_domain.exists(DomainName='testdomain', **conn_parameters)
  112. self.assertTrue(result['exists'])
  113. def test_that_when_checking_if_a_domain_exists_and_a_domain_does_not_exist_the_domain_exists_method_returns_false(self):
  114. '''
  115. Tests checking domain existence when the domain does not exist
  116. '''
  117. self.conn.describe_elasticsearch_domain.side_effect = not_found_error
  118. result = boto_elasticsearch_domain.exists(DomainName='mydomain', **conn_parameters)
  119. self.assertFalse(result['exists'])
  120. def test_that_when_checking_if_a_domain_exists_and_boto3_returns_an_error_the_domain_exists_method_returns_error(self):
  121. '''
  122. Tests checking domain existence when boto returns an error
  123. '''
  124. self.conn.describe_elasticsearch_domain.side_effect = ClientError(error_content, 'list_domains')
  125. result = boto_elasticsearch_domain.exists(DomainName='mydomain', **conn_parameters)
  126. self.assertEqual(result.get('error', {}).get('message'), error_message.format('list_domains'))
  127. def test_that_when_checking_domain_status_and_a_domain_exists_the_domain_status_method_returns_info(self):
  128. '''
  129. Tests checking domain existence when the domain already exists
  130. '''
  131. self.conn.describe_elasticsearch_domain.return_value = {'DomainStatus': domain_ret}
  132. result = boto_elasticsearch_domain.status(DomainName='testdomain', **conn_parameters)
  133. self.assertTrue(result['domain'])
  134. def test_that_when_checking_domain_status_and_boto3_returns_an_error_the_domain_status_method_returns_error(self):
  135. '''
  136. Tests checking domain existence when boto returns an error
  137. '''
  138. self.conn.describe_elasticsearch_domain.side_effect = ClientError(error_content, 'list_domains')
  139. result = boto_elasticsearch_domain.status(DomainName='mydomain', **conn_parameters)
  140. self.assertEqual(result.get('error', {}).get('message'), error_message.format('list_domains'))
  141. def test_that_when_describing_domain_it_returns_the_dict_of_properties_returns_true(self):
  142. '''
  143. Tests describing parameters if domain exists
  144. '''
  145. domainconfig = {}
  146. for k, v in six.iteritems(domain_ret):
  147. if k == 'DomainName':
  148. continue
  149. domainconfig[k] = {'Options': v}
  150. self.conn.describe_elasticsearch_domain_config.return_value = {'DomainConfig': domainconfig}
  151. result = boto_elasticsearch_domain.describe(DomainName=domain_ret['DomainName'], **conn_parameters)
  152. log.warning(result)
  153. desired_ret = copy.copy(domain_ret)
  154. desired_ret.pop('DomainName')
  155. self.assertEqual(result, {'domain': desired_ret})
  156. def test_that_when_describing_domain_on_client_error_it_returns_error(self):
  157. '''
  158. Tests describing parameters failure
  159. '''
  160. self.conn.describe_elasticsearch_domain_config.side_effect = ClientError(error_content, 'list_domains')
  161. result = boto_elasticsearch_domain.describe(DomainName='testdomain', **conn_parameters)
  162. self.assertTrue('error' in result)
  163. def test_that_when_creating_a_domain_succeeds_the_create_domain_method_returns_true(self):
  164. '''
  165. tests True domain created.
  166. '''
  167. self.conn.create_elasticsearch_domain.return_value = {'DomainStatus': domain_ret}
  168. args = copy.copy(domain_ret)
  169. args.update(conn_parameters)
  170. result = boto_elasticsearch_domain.create(**args)
  171. self.assertTrue(result['created'])
  172. def test_that_when_creating_a_domain_fails_the_create_domain_method_returns_error(self):
  173. '''
  174. tests False domain not created.
  175. '''
  176. self.conn.create_elasticsearch_domain.side_effect = ClientError(error_content, 'create_domain')
  177. args = copy.copy(domain_ret)
  178. args.update(conn_parameters)
  179. result = boto_elasticsearch_domain.create(**args)
  180. self.assertEqual(result.get('error', {}).get('message'), error_message.format('create_domain'))
  181. def test_that_when_deleting_a_domain_succeeds_the_delete_domain_method_returns_true(self):
  182. '''
  183. tests True domain deleted.
  184. '''
  185. result = boto_elasticsearch_domain.delete(DomainName='testdomain',
  186. **conn_parameters)
  187. self.assertTrue(result['deleted'])
  188. def test_that_when_deleting_a_domain_fails_the_delete_domain_method_returns_false(self):
  189. '''
  190. tests False domain not deleted.
  191. '''
  192. self.conn.delete_elasticsearch_domain.side_effect = ClientError(error_content, 'delete_domain')
  193. result = boto_elasticsearch_domain.delete(DomainName='testdomain',
  194. **conn_parameters)
  195. self.assertFalse(result['deleted'])
  196. def test_that_when_updating_a_domain_succeeds_the_update_domain_method_returns_true(self):
  197. '''
  198. tests True domain updated.
  199. '''
  200. self.conn.update_elasticsearch_domain_config.return_value = {'DomainConfig': domain_ret}
  201. args = copy.copy(domain_ret)
  202. args.update(conn_parameters)
  203. result = boto_elasticsearch_domain.update(**args)
  204. self.assertTrue(result['updated'])
  205. def test_that_when_updating_a_domain_fails_the_update_domain_method_returns_error(self):
  206. '''
  207. tests False domain not updated.
  208. '''
  209. self.conn.update_elasticsearch_domain_config.side_effect = ClientError(error_content, 'update_domain')
  210. args = copy.copy(domain_ret)
  211. args.update(conn_parameters)
  212. result = boto_elasticsearch_domain.update(**args)
  213. self.assertEqual(result.get('error', {}).get('message'), error_message.format('update_domain'))
  214. def test_that_when_adding_tags_succeeds_the_add_tags_method_returns_true(self):
  215. '''
  216. tests True tags added.
  217. '''
  218. self.conn.describe_elasticsearch_domain.return_value = {'DomainStatus': domain_ret}
  219. result = boto_elasticsearch_domain.add_tags(DomainName='testdomain', a='b', **conn_parameters)
  220. self.assertTrue(result['tagged'])
  221. def test_that_when_adding_tags_fails_the_add_tags_method_returns_false(self):
  222. '''
  223. tests False tags not added.
  224. '''
  225. self.conn.add_tags.side_effect = ClientError(error_content, 'add_tags')
  226. self.conn.describe_elasticsearch_domain.return_value = {'DomainStatus': domain_ret}
  227. result = boto_elasticsearch_domain.add_tags(DomainName=domain_ret['DomainName'], a='b', **conn_parameters)
  228. self.assertFalse(result['tagged'])
  229. def test_that_when_removing_tags_succeeds_the_remove_tags_method_returns_true(self):
  230. '''
  231. tests True tags removed.
  232. '''
  233. self.conn.describe_elasticsearch_domain.return_value = {'DomainStatus': domain_ret}
  234. result = boto_elasticsearch_domain.remove_tags(DomainName=domain_ret['DomainName'], TagKeys=['a'], **conn_parameters)
  235. self.assertTrue(result['tagged'])
  236. def test_that_when_removing_tags_fails_the_remove_tags_method_returns_false(self):
  237. '''
  238. tests False tags not removed.
  239. '''
  240. self.conn.remove_tags.side_effect = ClientError(error_content, 'remove_tags')
  241. self.conn.describe_elasticsearch_domain.return_value = {'DomainStatus': domain_ret}
  242. result = boto_elasticsearch_domain.remove_tags(DomainName=domain_ret['DomainName'], TagKeys=['b'], **conn_parameters)
  243. self.assertFalse(result['tagged'])
  244. def test_that_when_listing_tags_succeeds_the_list_tags_method_returns_true(self):
  245. '''
  246. tests True tags listed.
  247. '''
  248. self.conn.describe_elasticsearch_domain.return_value = {'DomainStatus': domain_ret}
  249. result = boto_elasticsearch_domain.list_tags(DomainName=domain_ret['DomainName'], **conn_parameters)
  250. self.assertEqual(result['tags'], {})
  251. def test_that_when_listing_tags_fails_the_list_tags_method_returns_false(self):
  252. '''
  253. tests False tags not listed.
  254. '''
  255. self.conn.list_tags.side_effect = ClientError(error_content, 'list_tags')
  256. self.conn.describe_elasticsearch_domain.return_value = {'DomainStatus': domain_ret}
  257. result = boto_elasticsearch_domain.list_tags(DomainName=domain_ret['DomainName'], **conn_parameters)
  258. self.assertTrue(result['error'])