123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- # -*- coding: utf-8 -*-
- '''
- :codeauthor: Nicole Thomas <nicole@saltstack.com>
- '''
- # Import Python Libs
- from __future__ import absolute_import, print_function, unicode_literals
- import os
- import yaml
- # Import Salt Libs
- from salt.config import cloud_providers_config
- import salt.utils.cloud
- import salt.utils.files
- import salt.utils.yaml
- # Import Salt Testing Libs
- from tests.support.case import ShellCase
- from tests.support.paths import FILES
- from tests.support.helpers import expensiveTest, generate_random_name
- from tests.support.unit import expectedFailure, skipIf
- from tests.support import win_installer
- # Create the cloud instance name to be used throughout the tests
- INSTANCE_NAME = generate_random_name('CLOUD-TEST-')
- PROVIDER_NAME = 'ec2'
- HAS_WINRM = salt.utils.cloud.HAS_WINRM and salt.utils.cloud.HAS_SMB
- TIMEOUT = 1200
- class EC2Test(ShellCase):
- '''
- Integration tests for the EC2 cloud provider in Salt-Cloud
- '''
- def _installer_name(self):
- '''
- Determine the downloaded installer name by searching the files
- directory for the firt file that loosk like an installer.
- '''
- for path, dirs, files in os.walk(FILES):
- for file in files:
- if file.startswith(win_installer.PREFIX):
- return file
- break
- return
- def _fetch_latest_installer(self):
- '''
- Download the latest Windows installer executable
- '''
- name = win_installer.latest_installer_name()
- path = os.path.join(FILES, name)
- with salt.utils.files.fopen(path, 'wb') as fp:
- win_installer.download_and_verify(fp, name)
- return name
- def _ensure_installer(self):
- '''
- Make sure the testing environment has a Windows installer executbale.
- '''
- name = self._installer_name()
- if name:
- return name
- return self._fetch_latest_installer()
- @expensiveTest
- def setUp(self):
- '''
- Sets up the test requirements
- '''
- super(EC2Test, self).setUp()
- # check if appropriate cloud provider and profile files are present
- profile_str = 'ec2-config'
- providers = self.run_cloud('--list-providers')
- if profile_str + ':' not in providers:
- self.skipTest(
- 'Configuration file for {0} was not found. Check {0}.conf files '
- 'in tests/integration/files/conf/cloud.*.d/ to run these tests.'
- .format(PROVIDER_NAME)
- )
- # check if id, key, keyname, securitygroup, private_key, location,
- # and provider are present
- config = cloud_providers_config(
- os.path.join(
- FILES,
- 'conf',
- 'cloud.providers.d',
- PROVIDER_NAME + '.conf'
- )
- )
- id_ = config[profile_str][PROVIDER_NAME]['id']
- key = config[profile_str][PROVIDER_NAME]['key']
- key_name = config[profile_str][PROVIDER_NAME]['keyname']
- sec_group = config[profile_str][PROVIDER_NAME]['securitygroupname'][0]
- private_key = config[profile_str][PROVIDER_NAME]['private_key']
- location = config[profile_str][PROVIDER_NAME]['location']
- conf_items = [id_, key, key_name, sec_group, private_key, location]
- missing_conf_item = []
- for item in conf_items:
- if item == '':
- missing_conf_item.append(item)
- if missing_conf_item:
- self.skipTest(
- 'An id, key, keyname, security group, private key, and location must '
- 'be provided to run these tests. One or more of these elements is '
- 'missing. Check tests/integration/files/conf/cloud.providers.d/{0}.conf'
- .format(PROVIDER_NAME)
- )
- self.INSTALLER = self._ensure_installer()
- def override_profile_config(self, name, data):
- conf_path = os.path.join(self.get_config_dir(), 'cloud.profiles.d', 'ec2.conf')
- with salt.utils.files.fopen(conf_path, 'r') as fp:
- conf = yaml.safe_load(fp)
- conf[name].update(data)
- with salt.utils.files.fopen(conf_path, 'w') as fp:
- salt.utils.yaml.safe_dump(conf, fp)
- def copy_file(self, name):
- '''
- Copy a file from tests/integration/files to a test's temporary
- configuration directory. The path to the file which is created will be
- returned.
- '''
- src = os.path.join(FILES, name)
- dst = os.path.join(self.get_config_dir(), name)
- with salt.utils.files.fopen(src, 'rb') as sfp:
- with salt.utils.files.fopen(dst, 'wb') as dfp:
- dfp.write(sfp.read())
- return dst
- def _test_instance(self, profile='ec2-test', debug=False, timeout=TIMEOUT):
- '''
- Tests creating and deleting an instance on EC2 (classic)
- '''
- # create the instance
- cmd = '-p {0}'.format(profile)
- if debug:
- cmd += ' -l debug'
- cmd += ' {0}'.format(INSTANCE_NAME)
- instance = self.run_cloud(cmd, timeout=timeout)
- ret_str = '{0}:'.format(INSTANCE_NAME)
- # check if instance returned with salt installed
- try:
- self.assertIn(ret_str, instance)
- except AssertionError:
- self.run_cloud('-d {0} --assume-yes'.format(INSTANCE_NAME), timeout=timeout)
- raise
- # delete the instance
- delete = self.run_cloud('-d {0} --assume-yes'.format(INSTANCE_NAME), timeout=timeout)
- ret_str = ' shutting-down'
- # check if deletion was performed appropriately
- try:
- self.assertIn(ret_str, delete)
- except AssertionError:
- raise
- def test_instance_rename(self):
- '''
- Tests creating and renaming an instance on EC2 (classic)
- '''
- # create the instance
- rename = INSTANCE_NAME + '-rename'
- instance = self.run_cloud('-p ec2-test {0} --no-deploy'.format(INSTANCE_NAME), timeout=TIMEOUT)
- ret_str = '{0}:'.format(INSTANCE_NAME)
- # check if instance returned
- try:
- self.assertIn(ret_str, instance)
- except AssertionError:
- self.run_cloud('-d {0} --assume-yes'.format(INSTANCE_NAME), timeout=TIMEOUT)
- raise
- change_name = self.run_cloud('-a rename {0} newname={1} --assume-yes'.format(INSTANCE_NAME, rename), timeout=TIMEOUT)
- check_rename = self.run_cloud('-a show_instance {0} --assume-yes'.format(rename), [rename])
- exp_results = [' {0}:'.format(rename), ' size:',
- ' architecture:']
- try:
- for result in exp_results:
- self.assertIn(result, check_rename[0])
- except AssertionError:
- self.run_cloud('-d {0} --assume-yes'.format(INSTANCE_NAME), timeout=TIMEOUT)
- raise
- # delete the instance
- delete = self.run_cloud('-d {0} --assume-yes'.format(rename), timeout=TIMEOUT)
- ret_str = ' shutting-down'
- # check if deletion was performed appropriately
- self.assertIn(ret_str, delete)
- def test_instance(self):
- '''
- Tests creating and deleting an instance on EC2 (classic)
- '''
- self._test_instance('ec2-test')
- @expectedFailure
- def test_win2012r2_winexe(self):
- '''
- Tests creating and deleting a Windows 2012r2instance on EC2 using
- winexe (classic)
- '''
- # TODO: winexe calls hang and the test fails by timing out. The same
- # same calls succeed when run outside of the test environment.
- self.override_profile_config(
- 'ec2-win2012r2-test',
- {
- 'use_winrm': False,
- 'userdata_file': self.copy_file('windows-firewall-winexe.ps1'),
- 'win_installer': self.copy_file(self.INSTALLER),
- },
- )
- self._test_instance('ec2-win2012r2-test', debug=True, timeout=TIMEOUT)
- @skipIf(not HAS_WINRM, 'Skip when winrm dependencies are missing')
- def test_win2012r2_winrm(self):
- '''
- Tests creating and deleting a Windows 2012r2 instance on EC2 using
- winrm (classic)
- '''
- self.override_profile_config(
- 'ec2-win2012r2-test',
- {
- 'userdata_file': self.copy_file('windows-firewall.ps1'),
- 'win_installer': self.copy_file(self.INSTALLER),
- 'winrm_ssl_verify': False,
- 'use_winrm': True,
- }
- )
- self._test_instance('ec2-win2012r2-test', debug=True, timeout=TIMEOUT)
- @expectedFailure
- def test_win2016_winexe(self):
- '''
- Tests creating and deleting a Windows 2016 instance on EC2 using winrm
- (classic)
- '''
- # TODO: winexe calls hang and the test fails by timing out. The same
- # same calls succeed when run outside of the test environment.
- self.override_profile_config(
- 'ec2-win2016-test',
- {
- 'use_winrm': False,
- 'userdata_file': self.copy_file('windows-firewall-winexe.ps1'),
- 'win_installer': self.copy_file(self.INSTALLER),
- },
- )
- self._test_instance('ec2-win2016-test', debug=True, timeout=TIMEOUT)
- @skipIf(not HAS_WINRM, 'Skip when winrm dependencies are missing')
- def test_win2016_winrm(self):
- '''
- Tests creating and deleting a Windows 2016 instance on EC2 using winrm
- (classic)
- '''
- self.override_profile_config(
- 'ec2-win2016-test',
- {
- 'userdata_file': self.copy_file('windows-firewall.ps1'),
- 'win_installer': self.copy_file(self.INSTALLER),
- 'winrm_ssl_verify': False,
- 'use_winrm': True,
- }
- )
- self._test_instance('ec2-win2016-test', debug=True, timeout=TIMEOUT)
- def tearDown(self):
- '''
- Clean up after tests
- '''
- query = self.run_cloud('--query')
- ret_str = ' {0}:'.format(INSTANCE_NAME)
- # if test instance is still present, delete it
- if ret_str in query:
- self.run_cloud('-d {0} --assume-yes'.format(INSTANCE_NAME), timeout=TIMEOUT)
|