test_ec2.py 6.6 KB

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