test_ec2.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. # -*- coding: utf-8 -*-
  2. # Import Python libs
  3. from __future__ import absolute_import, print_function, unicode_literals
  4. import os
  5. import tempfile
  6. import salt.utils.files
  7. # Import Salt Libs
  8. from salt.cloud.clouds import ec2
  9. from salt.exceptions import SaltCloudSystemExit
  10. from tests.support.mixins import LoaderModuleMockMixin
  11. from tests.support.mock import PropertyMock, patch
  12. # Import Salt Testing Libs
  13. from tests.support.runtests import RUNTIME_VARS
  14. from tests.support.unit import TestCase, skipIf
  15. from tests.unit.test_crypt import PRIVKEY_DATA
  16. PASS_DATA = (
  17. b"qOjCKDlBdcNEbJ/J8eRl7sH+bYIIm4cvHHY86gh2NEUnufFlFo0gGVTZR05Fj0cw3n/w7gR"
  18. b"urNXz5JoeSIHVuNI3YTwzL9yEAaC0kuy8EbOlO2yx8yPGdfml9BRwOV7A6b8UFo9co4H7fz"
  19. b"DdScMKU2yzvRYvp6N6Q2cJGBmPsemnXWWusb+1vZVWxcRAQmG3ogF6Z5rZSYAYH0N4rqJgH"
  20. b"mQfzuyb+jrBvV/IOoV1EdO9jGSH9338aS47NjrmNEN/SpnS6eCWZUwwyHbPASuOvWiY4QH/"
  21. b"0YZC6EGccwiUmt0ZOxIynk+tEyVPTkiS0V8RcZK6YKqMWHpKmPtLBzfuoA=="
  22. )
  23. class EC2TestCase(TestCase, LoaderModuleMockMixin):
  24. """
  25. Unit TestCase for salt.cloud.clouds.ec2 module.
  26. """
  27. def setUp(self):
  28. super(EC2TestCase, self).setUp()
  29. with tempfile.NamedTemporaryFile(
  30. dir=RUNTIME_VARS.TMP, suffix=".pem", delete=True
  31. ) as fp:
  32. self.key_file = fp.name
  33. def tearDown(self):
  34. super(EC2TestCase, self).tearDown()
  35. if os.path.exists(self.key_file):
  36. os.remove(self.key_file)
  37. def setup_loader_modules(self):
  38. return {ec2: {"__opts__": {}}}
  39. def test__validate_key_path_and_mode(self):
  40. # Key file exists
  41. with patch("os.path.exists", return_value=True):
  42. with patch("os.stat") as patched_stat:
  43. type(patched_stat.return_value).st_mode = PropertyMock(
  44. return_value=0o644
  45. )
  46. self.assertRaises(
  47. SaltCloudSystemExit, ec2._validate_key_path_and_mode, "key_file"
  48. )
  49. type(patched_stat.return_value).st_mode = PropertyMock(
  50. return_value=0o600
  51. )
  52. self.assertTrue(ec2._validate_key_path_and_mode("key_file"))
  53. type(patched_stat.return_value).st_mode = PropertyMock(
  54. return_value=0o400
  55. )
  56. self.assertTrue(ec2._validate_key_path_and_mode("key_file"))
  57. # Key file does not exist
  58. with patch("os.path.exists", return_value=False):
  59. self.assertRaises(
  60. SaltCloudSystemExit, ec2._validate_key_path_and_mode, "key_file"
  61. )
  62. @skipIf(not ec2.HAS_M2 and not ec2.HAS_PYCRYPTO, "Needs crypto library")
  63. @patch("salt.cloud.clouds.ec2._get_node")
  64. @patch("salt.cloud.clouds.ec2.get_location")
  65. @patch("salt.cloud.clouds.ec2.get_provider")
  66. @patch("salt.utils.aws.query")
  67. def test_get_password_data(self, query, get_provider, get_location, _get_node):
  68. query.return_value = [{"passwordData": PASS_DATA}]
  69. _get_node.return_value = {"instanceId": "i-abcdef"}
  70. get_location.return_value = "us-west2"
  71. get_provider.return_value = "ec2"
  72. with salt.utils.files.fopen(self.key_file, "w") as fp:
  73. fp.write(PRIVKEY_DATA)
  74. ret = ec2.get_password_data(
  75. name="i-abcddef", kwargs={"key_file": self.key_file}, call="action"
  76. )
  77. assert ret["passwordData"] == PASS_DATA
  78. assert ret["password"] == "testp4ss!"
  79. @patch("salt.cloud.clouds.ec2.config.get_cloud_config_value")
  80. @patch("salt.cloud.clouds.ec2.get_location")
  81. @patch("salt.cloud.clouds.ec2.get_provider")
  82. @patch("salt.cloud.clouds.ec2.aws.query")
  83. def test_get_imageid(self, aws_query, get_provider, get_location, config):
  84. """
  85. test querying imageid function
  86. """
  87. vm = {}
  88. ami = "ami-1234"
  89. config.return_value = "test/*"
  90. get_location.return_value = "us-west2"
  91. get_provider.return_value = "ec2"
  92. aws_query.return_value = [{"imageId": ami}]
  93. # test image filter
  94. self.assertEqual(ec2.get_imageid(vm), ami)
  95. # test ami-image
  96. config.return_value = ami
  97. self.assertEqual(ec2.get_imageid(vm), ami)
  98. # we should have only ran aws.query once when testing the aws filter
  99. aws_query.assert_called_once()
  100. @patch("salt.cloud.clouds.ec2.config.get_cloud_config_value")
  101. @patch("salt.cloud.clouds.ec2.get_location")
  102. @patch("salt.cloud.clouds.ec2.get_availability_zone")
  103. @patch("salt.cloud.clouds.ec2.get_provider")
  104. @patch("salt.cloud.clouds.ec2.get_spot_config")
  105. @patch("salt.cloud.clouds.ec2._param_from_config")
  106. @patch("salt.cloud.clouds.ec2.securitygroupid")
  107. def test_termination_protection(
  108. self,
  109. securitygroupid,
  110. _param_from_config,
  111. get_spot_config,
  112. get_provider,
  113. get_availability_zone,
  114. get_location,
  115. config,
  116. ):
  117. """
  118. Verify that `set_termination_protection` updates the right parameters
  119. """
  120. vm = {"name": "taco"}
  121. set_del_root_vol_on_destroy = "yes"
  122. termination_protection = True
  123. config.side_effect = (
  124. [None] * 2
  125. + ["test/*"]
  126. + [None] * 13
  127. + [set_del_root_vol_on_destroy, termination_protection]
  128. )
  129. get_location.return_value = "us-west2"
  130. get_availability_zone.return_value = None
  131. get_provider.return_value = "ec2"
  132. get_spot_config.return_value = None
  133. securitygroupid.return_value = None
  134. self.assertRaises(
  135. salt.exceptions.SaltCloudConfigError, ec2.request_instance, vm
  136. )
  137. _param_from_config.assert_called_once_with("DisableApiTermination", True)
  138. @patch("salt.cloud.clouds.ec2.config.get_cloud_config_value")
  139. @patch("salt.cloud.clouds.ec2.get_location")
  140. @patch("salt.cloud.clouds.ec2.get_availability_zone")
  141. @patch("salt.cloud.clouds.ec2.get_provider")
  142. @patch("salt.cloud.clouds.ec2.get_spot_config")
  143. @patch("salt.cloud.clouds.ec2.securitygroupid")
  144. def test_termination_protection_exception(
  145. self,
  146. securitygroupid,
  147. get_spot_config,
  148. get_provider,
  149. get_availability_zone,
  150. get_location,
  151. config,
  152. ):
  153. """
  154. Verify improper `set_termination_protection` parameters raises an exception
  155. """
  156. vm = {"name": "taco"}
  157. termination_protection = "not a bool"
  158. config.side_effect = (
  159. [None] * 2 + ["test/*"] + [None] * 14 + [termination_protection]
  160. )
  161. get_location.return_value = "us-west2"
  162. get_availability_zone.return_value = None
  163. get_provider.return_value = "ec2"
  164. get_spot_config.return_value = None
  165. securitygroupid.return_value = None
  166. self.assertRaises(
  167. salt.exceptions.SaltCloudConfigError, ec2.request_instance, vm
  168. )