test_ec2.py 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. # -*- coding: utf-8 -*-
  2. """
  3. :codeauthor: Nicole Thomas <nicole@saltstack.com>
  4. """
  5. from __future__ import absolute_import, print_function, unicode_literals
  6. import os
  7. import salt.utils.cloud
  8. import salt.utils.files
  9. import salt.utils.yaml
  10. import yaml
  11. from tests.integration.cloud.helpers.cloud_test_base import CloudTest
  12. from tests.support import win_installer
  13. from tests.support.runtests import RUNTIME_VARS
  14. from tests.support.unit import skipIf
  15. HAS_WINRM = salt.utils.cloud.HAS_WINRM and salt.utils.cloud.HAS_SMB
  16. # THis test needs a longer timeout than other cloud tests
  17. TIMEOUT = 1200
  18. class EC2Test(CloudTest):
  19. """
  20. Integration tests for the EC2 cloud provider in Salt-Cloud
  21. """
  22. PROVIDER = "ec2"
  23. REQUIRED_PROVIDER_CONFIG_ITEMS = ("id", "key", "keyname", "private_key", "location")
  24. @staticmethod
  25. def __fetch_installer():
  26. # Determine the downloaded installer name by searching the files
  27. # directory for the first file that looks like an installer.
  28. for path, dirs, files in os.walk(RUNTIME_VARS.FILES):
  29. for file in files:
  30. if file.startswith(win_installer.PREFIX):
  31. return file
  32. # If the installer wasn't found in the previous steps, download the latest Windows installer executable
  33. name = win_installer.latest_installer_name()
  34. path = os.path.join(RUNTIME_VARS.FILES, name)
  35. with salt.utils.files.fopen(path, "wb") as fp:
  36. win_installer.download_and_verify(fp, name)
  37. return name
  38. @property
  39. def installer(self):
  40. """
  41. Make sure the testing environment has a Windows installer executable.
  42. """
  43. if not hasattr(self, "_installer"):
  44. self._installer = self.__fetch_installer()
  45. return self._installer
  46. def setUp(self):
  47. """
  48. Sets up the test requirements
  49. """
  50. group_or_subnet = self.provider_config.get("securitygroup")
  51. if not group_or_subnet:
  52. group_or_subnet = self.provider_config.get("subnetid")
  53. if not group_or_subnet:
  54. self.skipTest(
  55. "securitygroup or subnetid missing for {} config".format(self.PROVIDER)
  56. )
  57. super(EC2Test, self).setUp()
  58. def override_profile_config(self, name, data):
  59. conf_path = os.path.join(
  60. RUNTIME_VARS.TMP_CONF_DIR, "cloud.profiles.d", "ec2.conf"
  61. )
  62. with salt.utils.files.fopen(conf_path, "r") as fp:
  63. conf = yaml.safe_load(fp)
  64. conf[name].update(data)
  65. with salt.utils.files.fopen(conf_path, "w") as fp:
  66. salt.utils.yaml.safe_dump(conf, fp)
  67. def copy_file(self, name):
  68. """
  69. Copy a file from tests/integration/files to a test's temporary
  70. configuration directory. The path to the file which is created will be
  71. returned.
  72. """
  73. src = os.path.join(RUNTIME_VARS.FILES, name)
  74. dst = os.path.join(RUNTIME_VARS.TMP_CONF_DIR, name)
  75. with salt.utils.files.fopen(src, "rb") as sfp:
  76. with salt.utils.files.fopen(dst, "wb") as dfp:
  77. dfp.write(sfp.read())
  78. return dst
  79. def _test_instance(self, profile, debug):
  80. """
  81. Tests creating and deleting an instance on EC2 (classic)
  82. """
  83. # create the instance
  84. cmd = ["-p", profile]
  85. if debug:
  86. cmd.extend(["-l", "debug"])
  87. cmd.append(self.instance_name)
  88. ret_val = self.run_cloud(" ".join(cmd), timeout=TIMEOUT)
  89. # check if instance returned with salt installed
  90. self.assertInstanceExists(ret_val)
  91. self.assertDestroyInstance()
  92. def test_instance_rename(self):
  93. """
  94. Tests creating and renaming an instance on EC2 (classic)
  95. """
  96. # create the instance
  97. ret_val = self.run_cloud(
  98. "-p ec2-test {0} --no-deploy".format(self.instance_name), timeout=TIMEOUT
  99. )
  100. # check if instance returned
  101. self.assertInstanceExists(ret_val)
  102. changed_name = self.instance_name + "-changed"
  103. rename_result = self.run_cloud(
  104. "-a rename {0} newname={1} --assume-yes".format(
  105. self.instance_name, changed_name
  106. ),
  107. timeout=TIMEOUT,
  108. )
  109. self.assertFalse(
  110. self._instance_exists(),
  111. "Instance wasn't renamed: |\n{}".format(rename_result),
  112. )
  113. self.assertInstanceExists(instance_name=changed_name)
  114. self.assertDestroyInstance(changed_name)
  115. def test_instance(self):
  116. """
  117. Tests creating and deleting an instance on EC2 (classic)
  118. """
  119. self._test_instance("ec2-test", debug=False)
  120. def test_win2012r2_psexec(self):
  121. """
  122. Tests creating and deleting a Windows 2012r2instance on EC2 using
  123. psexec (classic)
  124. """
  125. # TODO: psexec calls hang and the test fails by timing out. The same
  126. # same calls succeed when run outside of the test environment.
  127. # FIXME? Does this override need to be undone at the end of the test?
  128. self.override_profile_config(
  129. "ec2-win2012r2-test",
  130. {
  131. "use_winrm": False,
  132. "userdata_file": self.copy_file("windows-firewall-winexe.ps1"),
  133. "win_installer": self.copy_file(self.installer),
  134. },
  135. )
  136. self._test_instance("ec2-win2012r2-test", debug=True)
  137. @skipIf(not HAS_WINRM, "Skip when winrm dependencies are missing")
  138. def test_win2012r2_winrm(self):
  139. """
  140. Tests creating and deleting a Windows 2012r2 instance on EC2 using
  141. winrm (classic)
  142. """
  143. self.override_profile_config(
  144. "ec2-win2012r2-test",
  145. {
  146. "userdata_file": self.copy_file("windows-firewall.ps1"),
  147. "win_installer": self.copy_file(self.installer),
  148. "winrm_ssl_verify": False,
  149. "use_winrm": True,
  150. },
  151. )
  152. self._test_instance("ec2-win2012r2-test", debug=True)
  153. def test_win2016_psexec(self):
  154. """
  155. Tests creating and deleting a Windows 2016 instance on EC2 using winrm
  156. (classic)
  157. """
  158. # TODO: winexe calls hang and the test fails by timing out. The
  159. # same calls succeed when run outside of the test environment.
  160. self.override_profile_config(
  161. "ec2-win2016-test",
  162. {
  163. "use_winrm": False,
  164. "userdata_file": self.copy_file("windows-firewall-winexe.ps1"),
  165. "win_installer": self.copy_file(self.installer),
  166. },
  167. )
  168. self._test_instance("ec2-win2016-test", debug=True)
  169. @skipIf(not HAS_WINRM, "Skip when winrm dependencies are missing")
  170. def test_win2016_winrm(self):
  171. """
  172. Tests creating and deleting a Windows 2016 instance on EC2 using winrm
  173. (classic)
  174. """
  175. self.override_profile_config(
  176. "ec2-win2016-test",
  177. {
  178. "userdata_file": self.copy_file("windows-firewall.ps1"),
  179. "win_installer": self.copy_file(self.installer),
  180. "winrm_ssl_verify": False,
  181. "use_winrm": True,
  182. },
  183. )
  184. self._test_instance("ec2-win2016-test", debug=True)