# -*- coding: utf-8 -*- ''' :codeauthor: `Anthony Shaw ` tests.unit.cloud.clouds.dimensiondata_test ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ''' # Import Python libs from __future__ import absolute_import, print_function, unicode_literals try: import libcloud.security HAS_LIBCLOUD = True except ImportError: HAS_LIBCLOUD = False # Import Salt Libs from salt.cloud.clouds import dimensiondata from salt.exceptions import SaltCloudSystemExit from salt.utils.versions import LooseVersion # Import Salt Testing Libs from tests.support.mixins import LoaderModuleMockMixin from tests.support.unit import TestCase, skipIf from tests.support.mock import MagicMock, patch, __version__ as mock_version from tests.unit.cloud.clouds import _preferred_ip VM_NAME = 'winterfell' # Use certifi if installed try: if HAS_LIBCLOUD: # This work-around for Issue #32743 is no longer needed for libcloud >= # 1.4.0. However, older versions of libcloud must still be supported # with this work-around. This work-around can be removed when the # required minimum version of libcloud is 2.0.0 (See PR #40837 - which # is implemented in Salt 2018.3.0). if LooseVersion(libcloud.__version__) < LooseVersion('1.4.0'): import certifi libcloud.security.CA_CERTS_PATH.append(certifi.where()) except (ImportError, NameError): pass class ExtendedTestCase(TestCase): ''' Extended TestCase class containing additional helper methods. ''' def assertRaisesWithMessage(self, exc_type, exc_msg, func, *args, **kwargs): try: func(*args, **kwargs) self.assertFail() except Exception as exc: self.assertEqual(type(exc), exc_type) self.assertEqual(exc.message, exc_msg) class DimensionDataTestCase(ExtendedTestCase, LoaderModuleMockMixin): ''' Unit TestCase for salt.cloud.clouds.dimensiondata module. ''' def setup_loader_modules(self): return { dimensiondata: { '__virtual__': MagicMock(return_value='dimensiondata'), '__active_provider_name__': '', '__opts__': { 'providers': { 'my-dimensiondata-cloud': { 'dimensiondata': { 'driver': 'dimensiondata', 'region': 'dd-au', 'user_id': 'jon_snow', 'key': 'IKnowNothing' } } } } } } def test_avail_images_call(self): ''' Tests that a SaltCloudSystemExit is raised when trying to call avail_images with --action or -a. ''' self.assertRaises( SaltCloudSystemExit, dimensiondata.avail_images, call='action' ) def test_avail_locations_call(self): ''' Tests that a SaltCloudSystemExit is raised when trying to call avail_locations with --action or -a. ''' self.assertRaises( SaltCloudSystemExit, dimensiondata.avail_locations, call='action' ) def test_avail_sizes_call(self): ''' Tests that a SaltCloudSystemExit is raised when trying to call avail_sizes with --action or -a. ''' self.assertRaises( SaltCloudSystemExit, dimensiondata.avail_sizes, call='action' ) def test_list_nodes_call(self): ''' Tests that a SaltCloudSystemExit is raised when trying to call list_nodes with --action or -a. ''' self.assertRaises( SaltCloudSystemExit, dimensiondata.list_nodes, call='action' ) def test_destroy_call(self): ''' Tests that a SaltCloudSystemExit is raised when trying to call destroy with --function or -f. ''' self.assertRaises( SaltCloudSystemExit, dimensiondata.destroy, name=VM_NAME, call='function' ) @skipIf(HAS_LIBCLOUD is False, "Install 'libcloud' to be able to run this unit test.") def test_avail_sizes(self): ''' Tests that avail_sizes returns an empty dictionary. ''' sizes = dimensiondata.avail_sizes(call='foo') self.assertEqual( len(sizes), 1 ) self.assertEqual( sizes['default']['name'], 'default' ) def test_import(self): """ Test that the module picks up installed deps """ with patch('salt.config.check_driver_dependencies', return_value=True) as p: get_deps = dimensiondata.get_dependencies() self.assertEqual(get_deps, True) if LooseVersion(mock_version) >= LooseVersion('2.0.0'): self.assertTrue(p.call_count >= 1) def test_provider_matches(self): """ Test that the first configured instance of a dimensiondata driver is matched """ p = dimensiondata.get_configured_provider() self.assertNotEqual(p, None) def test_query_node_data_filter_preferred_ip_addresses(self): ''' Test if query node data is filtering out unpreferred IP addresses. ''' zero_ip = '0.0.0.0' private_ips = [zero_ip, '1.1.1.1', '2.2.2.2'] vm = {'name': None} data = MagicMock() data.public_ips = [] dimensiondata.NodeState = MagicMock() # pylint: disable=blacklisted-unmocked-patching dimensiondata.NodeState.RUNNING = True with patch('salt.cloud.clouds.dimensiondata.show_instance', MagicMock(return_value={'state': True, 'name': 'foo', 'public_ips': [], 'private_ips': private_ips})): with patch('salt.cloud.clouds.dimensiondata.preferred_ip', _preferred_ip(private_ips, [zero_ip])): with patch('salt.cloud.clouds.dimensiondata.ssh_interface', MagicMock(return_value='private_ips')): self.assertEqual(dimensiondata._query_node_data(vm, data).public_ips, [zero_ip])