test_ec2.py 6.9 KB

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