diff options
Diffstat (limited to 'openstackclient/tests')
19 files changed, 1229 insertions, 149 deletions
diff --git a/openstackclient/tests/common/test_quota.py b/openstackclient/tests/common/test_quota.py index edf29c9b..ba7ee469 100644 --- a/openstackclient/tests/common/test_quota.py +++ b/openstackclient/tests/common/test_quota.py @@ -59,6 +59,7 @@ class TestQuota(compute_fakes.TestComputev2): self.service_catalog_mock = \ self.app.client_manager.auth_ref.service_catalog self.service_catalog_mock.reset_mock() + self.app.client_manager.auth_ref.project_id = identity_fakes.project_id class TestQuotaSet(TestQuota): @@ -304,3 +305,13 @@ class TestQuotaShow(TestQuota): identity_fakes.project_id) self.volume_quotas_class_mock.get.assert_called_with( identity_fakes.project_id) + + def test_quota_show_no_project(self): + parsed_args = self.check_parser(self.cmd, [], []) + + self.cmd.take_action(parsed_args) + + self.quotas_mock.get.assert_called_with(identity_fakes.project_id) + self.volume_quotas_mock.get.assert_called_with( + identity_fakes.project_id) + self.network.get_quota.assert_called_with(identity_fakes.project_id) diff --git a/openstackclient/tests/compute/v2/fakes.py b/openstackclient/tests/compute/v2/fakes.py index 7f39bad0..b3f3fb49 100644 --- a/openstackclient/tests/compute/v2/fakes.py +++ b/openstackclient/tests/compute/v2/fakes.py @@ -100,8 +100,7 @@ class FakeAggregate(object): :return: A FakeResource object, with id and other attributes """ - if attrs is None: - attrs = {} + attrs = attrs or {} # Set default attribute aggregate_info = { @@ -177,6 +176,9 @@ class FakeComputev2Client(object): self.hosts = mock.Mock() self.hosts.resource_class = fakes.FakeResource(None, {}) + self.server_groups = mock.Mock() + self.server_groups.resource_class = fakes.FakeResource(None, {}) + self.auth_token = kwargs['token'] self.management_url = kwargs['endpoint'] @@ -217,7 +219,7 @@ class FakeHypervisor(object): """Fake one or more hypervisor.""" @staticmethod - def create_one_hypervisor(attrs={}): + def create_one_hypervisor(attrs=None): """Create a fake hypervisor. :param Dictionary attrs: @@ -225,6 +227,8 @@ class FakeHypervisor(object): :return: A FakeResource object, with id, hypervisor_hostname, and so on """ + attrs = attrs or {} + # Set default attributes. hypervisor_info = { 'id': 'hypervisor-id-' + uuid.uuid4().hex, @@ -263,7 +267,7 @@ class FakeHypervisor(object): return hypervisor @staticmethod - def create_hypervisors(attrs={}, count=2): + def create_hypervisors(attrs=None, count=2): """Create multiple fake hypervisors. :param Dictionary attrs: @@ -284,7 +288,7 @@ class FakeHypervisorStats(object): """Fake one or more hypervisor stats.""" @staticmethod - def create_one_hypervisor_stats(attrs={}): + def create_one_hypervisor_stats(attrs=None): """Create a fake hypervisor stats. :param Dictionary attrs: @@ -292,6 +296,8 @@ class FakeHypervisorStats(object): :return: A FakeResource object, with id, hypervisor_hostname, and so on """ + attrs = attrs or {} + # Set default attributes. stats_info = { 'count': 2, @@ -319,7 +325,7 @@ class FakeHypervisorStats(object): return hypervisor_stats @staticmethod - def create_hypervisors_stats(attrs={}, count=2): + def create_hypervisors_stats(attrs=None, count=2): """Create multiple fake hypervisors stats. :param Dictionary attrs: @@ -349,8 +355,7 @@ class FakeSecurityGroup(object): :return: A FakeResource object, with id, name, etc. """ - if attrs is None: - attrs = {} + attrs = attrs or {} # Set default attributes. security_group_attrs = { @@ -400,8 +405,7 @@ class FakeSecurityGroupRule(object): :return: A FakeResource object, with id, etc. """ - if attrs is None: - attrs = {} + attrs = attrs or {} # Set default attributes. security_group_rule_attrs = { @@ -445,7 +449,7 @@ class FakeServer(object): """Fake one or more compute servers.""" @staticmethod - def create_one_server(attrs={}, methods={}): + def create_one_server(attrs=None, methods=None): """Create a fake server. :param Dictionary attrs: @@ -455,6 +459,9 @@ class FakeServer(object): :return: A FakeResource object, with id, name, metadata """ + attrs = attrs or {} + methods = methods or {} + # Set default attributes. server_info = { 'id': 'server-id-' + uuid.uuid4().hex, @@ -465,7 +472,8 @@ class FakeServer(object): }, 'flavor': { 'id': 'flavor-id-' + uuid.uuid4().hex, - } + }, + 'OS-EXT-STS:power_state': 1, } # Overwrite default attributes. @@ -477,7 +485,7 @@ class FakeServer(object): return server @staticmethod - def create_servers(attrs={}, methods={}, count=2): + def create_servers(attrs=None, methods=None, count=2): """Create multiple fake servers. :param Dictionary attrs: @@ -527,8 +535,7 @@ class FakeFlavor(object): :return: A FakeResource object, with id, name, ram, vcpus, properties """ - if attrs is None: - attrs = {} + attrs = attrs or {} # Set default attributes. flavor_info = { @@ -537,8 +544,8 @@ class FakeFlavor(object): 'ram': 8192, 'vcpus': 4, 'disk': 128, - 'swap': '', - 'rxtx_factor': '1.0', + 'swap': 0, + 'rxtx_factor': 1.0, 'OS-FLV-DISABLED:disabled': False, 'os-flavor-access:is_public': True, 'OS-FLV-EXT-DATA:ephemeral': 0, @@ -566,7 +573,7 @@ class FakeFlavor(object): return flavor @staticmethod - def create_flavors(attrs={}, count=2): + def create_flavors(attrs=None, count=2): """Create multiple fake flavors. :param Dictionary attrs: @@ -614,10 +621,9 @@ class FakeKeypair(object): :return: A FakeResource """ - # Set default attributes. - if attrs is None: - attrs = {} + attrs = attrs or {} + # Set default attributes. keypair_info = { 'name': 'keypair-name-' + uuid.uuid4().hex, 'fingerprint': 'dummy', @@ -658,7 +664,7 @@ class FakeAvailabilityZone(object): """Fake one or more compute availability zones (AZs).""" @staticmethod - def create_one_availability_zone(attrs={}): + def create_one_availability_zone(attrs=None): """Create a fake AZ. :param Dictionary attrs: @@ -666,6 +672,8 @@ class FakeAvailabilityZone(object): :return: A FakeResource object with zoneName, zoneState, etc. """ + attrs = attrs or {} + # Set default attributes. host_name = uuid.uuid4().hex service_name = uuid.uuid4().hex @@ -689,7 +697,7 @@ class FakeAvailabilityZone(object): return availability_zone @staticmethod - def create_availability_zones(attrs={}, count=2): + def create_availability_zones(attrs=None, count=2): """Create multiple fake AZs. :param Dictionary attrs: @@ -712,7 +720,7 @@ class FakeFloatingIP(object): """Fake one or more floating ip.""" @staticmethod - def create_one_floating_ip(attrs={}): + def create_one_floating_ip(attrs=None): """Create a fake floating ip. :param Dictionary attrs: @@ -720,6 +728,8 @@ class FakeFloatingIP(object): :return: A FakeResource object, with id, ip, and so on """ + attrs = attrs or {} + # Set default attributes. floating_ip_attrs = { 'id': 'floating-ip-id-' + uuid.uuid4().hex, @@ -739,7 +749,7 @@ class FakeFloatingIP(object): return floating_ip @staticmethod - def create_floating_ips(attrs={}, count=2): + def create_floating_ips(attrs=None, count=2): """Create multiple fake floating ips. :param Dictionary attrs: @@ -778,7 +788,7 @@ class FakeNetwork(object): """Fake one or more networks.""" @staticmethod - def create_one_network(attrs={}): + def create_one_network(attrs=None): """Create a fake network. :param Dictionary attrs: @@ -786,6 +796,8 @@ class FakeNetwork(object): :return: A FakeResource object, with id, label, cidr and so on """ + attrs = attrs or {} + # Set default attributes. network_attrs = { 'bridge': 'br100', @@ -831,7 +843,7 @@ class FakeNetwork(object): return network @staticmethod - def create_networks(attrs={}, count=2): + def create_networks(attrs=None, count=2): """Create multiple fake networks. :param Dictionary attrs: @@ -860,8 +872,7 @@ class FakeHost(object): :return: A FakeResource object, with id and other attributes """ - if attrs is None: - attrs = {} + attrs = attrs or {} # Set default attributes. host_info = { @@ -899,3 +910,34 @@ class FakeHost(object): info=copy.deepcopy(host_info), loaded=True) return host + + +class FakeServerGroup(object): + """Fake one server group""" + + @staticmethod + def create_one_server_group(attrs=None): + """Create a fake server group + + :param Dictionary attrs: + A dictionary with all attributes + :return: + A FakeResource object, with id and other attributes + """ + if attrs is None: + attrs = {} + + server_group_info = { + 'id': 'server-group-id-' + uuid.uuid4().hex, + 'members': [], + 'metadata': {}, + 'name': 'server-group-name-' + uuid.uuid4().hex, + 'policies': [], + 'project_id': 'server-group-project-id-' + uuid.uuid4().hex, + 'user_id': 'server-group-user-id-' + uuid.uuid4().hex, + } + server_group_info.update(attrs) + server_group = fakes.FakeResource( + info=copy.deepcopy(server_group_info), + loaded=True) + return server_group diff --git a/openstackclient/tests/compute/v2/test_flavor.py b/openstackclient/tests/compute/v2/test_flavor.py index 03ca8807..6f507b16 100644 --- a/openstackclient/tests/compute/v2/test_flavor.py +++ b/openstackclient/tests/compute/v2/test_flavor.py @@ -30,6 +30,166 @@ class TestFlavor(compute_fakes.TestComputev2): self.flavors_mock.reset_mock() +class TestFlavorCreate(TestFlavor): + + flavor = compute_fakes.FakeFlavor.create_one_flavor( + attrs={'links': 'flavor-links'}) + + columns = ( + 'OS-FLV-DISABLED:disabled', + 'OS-FLV-EXT-DATA:ephemeral', + 'disk', + 'id', + 'name', + 'os-flavor-access:is_public', + 'ram', + 'rxtx_factor', + 'swap', + 'vcpus', + ) + data = ( + flavor.disabled, + flavor.ephemeral, + flavor.disk, + flavor.id, + flavor.name, + flavor.is_public, + flavor.ram, + flavor.rxtx_factor, + flavor.swap, + flavor.vcpus, + ) + + def setUp(self): + super(TestFlavorCreate, self).setUp() + + self.flavors_mock.create.return_value = self.flavor + self.cmd = flavor.CreateFlavor(self.app, None) + + def test_flavor_create_default_options(self): + + arglist = [ + self.flavor.name + ] + verifylist = [ + ('name', self.flavor.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + default_args = ( + self.flavor.name, + 256, + 1, + 0, + 'auto', + 0, + 0, + 1.0, + True + ) + columns, data = self.cmd.take_action(parsed_args) + self.flavors_mock.create.assert_called_once_with(*default_args) + + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + def test_flavor_create_all_options(self): + + arglist = [ + self.flavor.name, + '--id', self.flavor.id, + '--ram', str(self.flavor.ram), + '--disk', str(self.flavor.disk), + '--ephemeral', str(self.flavor.ephemeral), + '--swap', str(self.flavor.swap), + '--vcpus', str(self.flavor.vcpus), + '--rxtx-factor', str(self.flavor.rxtx_factor), + '--public', + ] + verifylist = [ + ('name', self.flavor.name), + ('id', self.flavor.id), + ('ram', self.flavor.ram), + ('disk', self.flavor.disk), + ('ephemeral', self.flavor.ephemeral), + ('swap', self.flavor.swap), + ('vcpus', self.flavor.vcpus), + ('rxtx_factor', self.flavor.rxtx_factor), + ('public', True), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + args = ( + self.flavor.name, + self.flavor.ram, + self.flavor.vcpus, + self.flavor.disk, + self.flavor.id, + self.flavor.ephemeral, + self.flavor.swap, + self.flavor.rxtx_factor, + self.flavor.is_public, + ) + columns, data = self.cmd.take_action(parsed_args) + self.flavors_mock.create.assert_called_once_with(*args) + + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + def test_flavor_create_other_options(self): + + self.flavor.is_public = False + arglist = [ + self.flavor.name, + '--id', self.flavor.id, + '--ram', str(self.flavor.ram), + '--disk', str(self.flavor.disk), + '--ephemeral', str(self.flavor.ephemeral), + '--swap', str(self.flavor.swap), + '--vcpus', str(self.flavor.vcpus), + '--rxtx-factor', str(self.flavor.rxtx_factor), + '--private', + ] + verifylist = [ + ('name', self.flavor.name), + ('id', self.flavor.id), + ('ram', self.flavor.ram), + ('disk', self.flavor.disk), + ('ephemeral', self.flavor.ephemeral), + ('swap', self.flavor.swap), + ('vcpus', self.flavor.vcpus), + ('rxtx_factor', self.flavor.rxtx_factor), + ('public', False), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + args = ( + self.flavor.name, + self.flavor.ram, + self.flavor.vcpus, + self.flavor.disk, + self.flavor.id, + self.flavor.ephemeral, + self.flavor.swap, + self.flavor.rxtx_factor, + self.flavor.is_public, + ) + columns, data = self.cmd.take_action(parsed_args) + self.flavors_mock.create.assert_called_once_with(*args) + + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + def test_flavor_create_no_options(self): + arglist = [] + verifylist = None + self.assertRaises(tests_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist) + + class TestFlavorDelete(TestFlavor): flavor = compute_fakes.FakeFlavor.create_one_flavor() @@ -273,7 +433,7 @@ class TestFlavorSet(TestFlavor): super(TestFlavorSet, self).setUp() self.flavors_mock.find.return_value = self.flavor - + self.flavors_mock.get.side_effect = exceptions.NotFound(None) self.cmd = flavor.SetFlavor(self.app, None) def test_flavor_set(self): @@ -288,8 +448,8 @@ class TestFlavorSet(TestFlavor): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - - self.flavors_mock.find.assert_called_with(name='baremetal') + self.flavors_mock.find.assert_called_with(name=parsed_args.flavor, + is_public=None) self.assertIsNone(result) @@ -329,9 +489,9 @@ class TestFlavorShow(TestFlavor): def setUp(self): super(TestFlavorShow, self).setUp() - # Return value of utils.find_resource() - self.flavors_mock.get.return_value = self.flavor - + # Return value of _find_resource() + self.flavors_mock.find.return_value = self.flavor + self.flavors_mock.get.side_effect = exceptions.NotFound(None) self.cmd = flavor.ShowFlavor(self.app, None) def test_show_no_options(self): @@ -367,7 +527,7 @@ class TestFlavorUnset(TestFlavor): super(TestFlavorUnset, self).setUp() self.flavors_mock.find.return_value = self.flavor - + self.flavors_mock.get.side_effect = exceptions.NotFound(None) self.cmd = flavor.UnsetFlavor(self.app, None) def test_flavor_unset(self): @@ -382,6 +542,6 @@ class TestFlavorUnset(TestFlavor): parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) - - self.flavors_mock.find.assert_called_with(name='baremetal') + self.flavors_mock.find.assert_called_with(name=parsed_args.flavor, + is_public=None) self.assertIsNone(result) diff --git a/openstackclient/tests/compute/v2/test_server.py b/openstackclient/tests/compute/v2/test_server.py index 17681672..903d0bff 100644 --- a/openstackclient/tests/compute/v2/test_server.py +++ b/openstackclient/tests/compute/v2/test_server.py @@ -89,6 +89,7 @@ class TestServer(compute_fakes.TestComputev2): class TestServerCreate(TestServer): columns = ( + 'OS-EXT-STS:power_state', 'addresses', 'flavor', 'id', @@ -100,6 +101,8 @@ class TestServerCreate(TestServer): def datalist(self): datalist = ( + server._format_servers_list_power_state( + getattr(self.new_server, 'OS-EXT-STS:power_state')), '', self.flavor.name + ' (' + self.new_server.flavor.get('id') + ')', self.new_server.id, @@ -146,7 +149,6 @@ class TestServerCreate(TestServer): ('server_name', self.new_server.name), ] - # Missing required args should bail here self.assertRaises(utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) @@ -1476,6 +1478,8 @@ class TestServerGeneral(TestServer): 'image': u'%s (%s)' % (_image.name, _image.id), 'project_id': u'tenant-id-xxx', 'properties': '', + 'OS-EXT-STS:power_state': server._format_servers_list_power_state( + getattr(_server, 'OS-EXT-STS:power_state')), } # Call _prep_server_detail(). diff --git a/openstackclient/tests/compute/v2/test_server_group.py b/openstackclient/tests/compute/v2/test_server_group.py new file mode 100644 index 00000000..70ff23f9 --- /dev/null +++ b/openstackclient/tests/compute/v2/test_server_group.py @@ -0,0 +1,283 @@ +# Copyright 2016 Huawei, Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + +import mock + +from openstackclient.common import exceptions +from openstackclient.common import utils +from openstackclient.compute.v2 import server_group +from openstackclient.tests.compute.v2 import fakes as compute_fakes +from openstackclient.tests import utils as tests_utils + + +class TestServerGroup(compute_fakes.TestComputev2): + + fake_server_group = compute_fakes.FakeServerGroup.create_one_server_group() + + columns = ( + 'id', + 'members', + 'name', + 'policies', + 'project_id', + 'user_id', + ) + + data = ( + fake_server_group.id, + utils.format_list(fake_server_group.members), + fake_server_group.name, + utils.format_list(fake_server_group.policies), + fake_server_group.project_id, + fake_server_group.user_id, + ) + + def setUp(self): + super(TestServerGroup, self).setUp() + + # Get a shortcut to the ServerGroupsManager Mock + self.server_groups_mock = self.app.client_manager.compute.server_groups + self.server_groups_mock.reset_mock() + + +class TestServerGroupCreate(TestServerGroup): + + def setUp(self): + super(TestServerGroupCreate, self).setUp() + + self.server_groups_mock.create.return_value = self.fake_server_group + self.cmd = server_group.CreateServerGroup(self.app, None) + + def test_server_group_create(self): + arglist = [ + '--policy', 'affinity', + 'affinity_group', + ] + verifylist = [ + ('policy', ['affinity']), + ('name', 'affinity_group'), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + self.server_groups_mock.create.assert_called_once_with( + name=parsed_args.name, + policies=parsed_args.policy, + ) + + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + def test_server_group_create_with_multiple_policies(self): + arglist = [ + '--policy', 'affinity', + '--policy', 'soft-affinity', + 'affinity_group', + ] + verifylist = [ + ('policy', ['affinity', 'soft-affinity']), + ('name', 'affinity_group'), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + self.server_groups_mock.create.assert_called_once_with( + name=parsed_args.name, + policies=parsed_args.policy, + ) + + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + + def test_server_group_create_no_policy(self): + arglist = [ + 'affinity_group', + ] + verifylist = None + self.assertRaises(tests_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist) + + +class TestServerGroupDelete(TestServerGroup): + + def setUp(self): + super(TestServerGroupDelete, self).setUp() + + self.server_groups_mock.get.return_value = self.fake_server_group + self.cmd = server_group.DeleteServerGroup(self.app, None) + + def test_server_group_delete(self): + arglist = [ + 'affinity_group', + ] + verifylist = [ + ('server_group', ['affinity_group']), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + self.server_groups_mock.get.assert_called_once_with('affinity_group') + self.server_groups_mock.delete.assert_called_once_with( + self.fake_server_group.id + ) + self.assertIsNone(result) + + def test_server_group_multiple_delete(self): + arglist = [ + 'affinity_group', + 'anti_affinity_group' + ] + verifylist = [ + ('server_group', ['affinity_group', 'anti_affinity_group']), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + result = self.cmd.take_action(parsed_args) + self.server_groups_mock.get.assert_any_call('affinity_group') + self.server_groups_mock.get.assert_any_call('anti_affinity_group') + self.server_groups_mock.delete.assert_called_with( + self.fake_server_group.id + ) + self.assertEqual(2, self.server_groups_mock.get.call_count) + self.assertEqual(2, self.server_groups_mock.delete.call_count) + self.assertIsNone(result) + + def test_server_group_delete_no_input(self): + arglist = [] + verifylist = None + self.assertRaises(tests_utils.ParserException, + self.check_parser, + self.cmd, + arglist, + verifylist) + + def test_server_group_multiple_delete_with_exception(self): + arglist = [ + 'affinity_group', + 'anti_affinity_group' + ] + verifylist = [ + ('server_group', ['affinity_group', 'anti_affinity_group']), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + find_mock_result = [self.fake_server_group, exceptions.CommandError] + with mock.patch.object(utils, 'find_resource', + side_effect=find_mock_result) as find_mock: + try: + self.cmd.take_action(parsed_args) + self.fail('CommandError should be raised.') + except exceptions.CommandError as e: + self.assertEqual('1 of 2 server groups failed to delete.', + str(e)) + + find_mock.assert_any_call(self.server_groups_mock, + 'affinity_group') + find_mock.assert_any_call(self.server_groups_mock, + 'anti_affinity_group') + + self.assertEqual(2, find_mock.call_count) + self.server_groups_mock.delete.assert_called_once_with( + self.fake_server_group.id + ) + + +class TestServerGroupList(TestServerGroup): + + list_columns = ( + 'ID', + 'Name', + 'Policies', + ) + + list_columns_long = ( + 'ID', + 'Name', + 'Policies', + 'Members', + 'Project Id', + 'User Id', + ) + + list_data = (( + TestServerGroup.fake_server_group.id, + TestServerGroup.fake_server_group.name, + utils.format_list(TestServerGroup.fake_server_group.policies), + ),) + + list_data_long = (( + TestServerGroup.fake_server_group.id, + TestServerGroup.fake_server_group.name, + utils.format_list(TestServerGroup.fake_server_group.policies), + utils.format_list(TestServerGroup.fake_server_group.members), + TestServerGroup.fake_server_group.project_id, + TestServerGroup.fake_server_group.user_id, + ),) + + def setUp(self): + super(TestServerGroupList, self).setUp() + + self.server_groups_mock.list.return_value = [self.fake_server_group] + self.cmd = server_group.ListServerGroup(self.app, None) + + def test_server_group_list(self): + arglist = [] + verifylist = [ + ('all_projects', False), + ('long', False), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + self.server_groups_mock.list.assert_called_once_with(False) + + self.assertEqual(self.list_columns, columns) + self.assertEqual(self.list_data, tuple(data)) + + def test_server_group_list_with_all_projects_and_long(self): + arglist = [ + '--all-projects', + '--long', + ] + verifylist = [ + ('all_projects', True), + ('long', True), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + self.server_groups_mock.list.assert_called_once_with(True) + + self.assertEqual(self.list_columns_long, columns) + self.assertEqual(self.list_data_long, tuple(data)) + + +class TestServerGroupShow(TestServerGroup): + + def setUp(self): + super(TestServerGroupShow, self).setUp() + + self.server_groups_mock.get.return_value = self.fake_server_group + self.cmd = server_group.ShowServerGroup(self.app, None) + + def test_server_group_show(self): + arglist = [ + 'affinity_group', + ] + verifylist = [ + ('server_group', 'affinity_group'), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + columns, data = self.cmd.take_action(parsed_args) + + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) diff --git a/openstackclient/tests/fakes.py b/openstackclient/tests/fakes.py index f0cebb06..46f983dc 100644 --- a/openstackclient/tests/fakes.py +++ b/openstackclient/tests/fakes.py @@ -142,7 +142,7 @@ class FakeModule(object): class FakeResource(object): - def __init__(self, manager=None, info={}, loaded=False, methods={}): + def __init__(self, manager=None, info=None, loaded=False, methods=None): """Set attributes and methods for a resource. :param manager: @@ -154,6 +154,9 @@ class FakeResource(object): :param Dictionary methods: A dictionary with all methods """ + info = info or {} + methods = methods or {} + self.__name__ = type(self).__name__ self.manager = manager self._info = info @@ -189,9 +192,12 @@ class FakeResource(object): class FakeResponse(requests.Response): - def __init__(self, headers={}, status_code=200, data=None, encoding=None): + def __init__(self, headers=None, status_code=200, + data=None, encoding=None): super(FakeResponse, self).__init__() + headers = headers or {} + self.status_code = status_code self.headers.update(headers) diff --git a/openstackclient/tests/image/v2/fakes.py b/openstackclient/tests/image/v2/fakes.py index 3555d2d4..f90d846d 100644 --- a/openstackclient/tests/image/v2/fakes.py +++ b/openstackclient/tests/image/v2/fakes.py @@ -181,7 +181,7 @@ class FakeImage(object): """ @staticmethod - def create_one_image(attrs={}): + def create_one_image(attrs=None): """Create a fake image. :param Dictionary attrs: @@ -190,6 +190,8 @@ class FakeImage(object): A FakeResource object with id, name, owner, protected, visibility and tags attrs """ + attrs = attrs or {} + # Set default attribute image_info = { 'id': 'image-id' + uuid.uuid4().hex, @@ -210,7 +212,7 @@ class FakeImage(object): return image @staticmethod - def create_images(attrs={}, count=2): + def create_images(attrs=None, count=2): """Create multiple fake images. :param Dictionary attrs: diff --git a/openstackclient/tests/network/v2/fakes.py b/openstackclient/tests/network/v2/fakes.py index 413ec7d2..7c4604bd 100644 --- a/openstackclient/tests/network/v2/fakes.py +++ b/openstackclient/tests/network/v2/fakes.py @@ -83,8 +83,7 @@ class FakeAddressScope(object): :return: A FakeResource object with name, id, etc. """ - if attrs is None: - attrs = {} + attrs = attrs or {} # Set default attributes. address_scope_attrs = { @@ -130,7 +129,7 @@ class FakeAvailabilityZone(object): """Fake one or more network availability zones (AZs).""" @staticmethod - def create_one_availability_zone(attrs={}): + def create_one_availability_zone(attrs=None): """Create a fake AZ. :param Dictionary attrs: @@ -138,6 +137,8 @@ class FakeAvailabilityZone(object): :return: A FakeResource object with name, state, etc. """ + attrs = attrs or {} + # Set default attributes. availability_zone = { 'name': uuid.uuid4().hex, @@ -154,7 +155,7 @@ class FakeAvailabilityZone(object): return availability_zone @staticmethod - def create_availability_zones(attrs={}, count=2): + def create_availability_zones(attrs=None, count=2): """Create multiple fake AZs. :param Dictionary attrs: @@ -177,7 +178,7 @@ class FakeNetwork(object): """Fake one or more networks.""" @staticmethod - def create_one_network(attrs={}): + def create_one_network(attrs=None): """Create a fake network. :param Dictionary attrs: @@ -186,6 +187,8 @@ class FakeNetwork(object): A FakeResource object, with id, name, admin_state_up, router_external, status, subnets, tenant_id """ + attrs = attrs or {} + # Set default attributes. network_attrs = { 'id': 'network-id-' + uuid.uuid4().hex, @@ -214,7 +217,7 @@ class FakeNetwork(object): return network @staticmethod - def create_networks(attrs={}, count=2): + def create_networks(attrs=None, count=2): """Create multiple fake networks. :param Dictionary attrs: @@ -254,16 +257,16 @@ class FakePort(object): """Fake one or more ports.""" @staticmethod - def create_one_port(attrs={}): + def create_one_port(attrs=None): """Create a fake port. :param Dictionary attrs: A dictionary with all attributes - :param Dictionary methods: - A dictionary with all methods :return: A FakeResource object, with id, name, etc. """ + attrs = attrs or {} + # Set default attributes. port_attrs = { 'admin_state_up': True, @@ -306,7 +309,7 @@ class FakePort(object): return port @staticmethod - def create_ports(attrs={}, count=2): + def create_ports(attrs=None, count=2): """Create multiple fake ports. :param Dictionary attrs: @@ -346,7 +349,7 @@ class FakeRouter(object): """Fake one or more routers.""" @staticmethod - def create_one_router(attrs={}): + def create_one_router(attrs=None): """Create a fake router. :param Dictionary attrs: @@ -355,6 +358,8 @@ class FakeRouter(object): A FakeResource object, with id, name, admin_state_up, status, tenant_id """ + attrs = attrs or {} + # Set default attributes. router_attrs = { 'id': 'router-id-' + uuid.uuid4().hex, @@ -382,7 +387,7 @@ class FakeRouter(object): return router @staticmethod - def create_routers(attrs={}, count=2): + def create_routers(attrs=None, count=2): """Create multiple fake routers. :param Dictionary attrs: @@ -430,8 +435,7 @@ class FakeSecurityGroup(object): :return: A FakeResource object, with id, name, etc. """ - if attrs is None: - attrs = {} + attrs = attrs or {} # Set default attributes. security_group_attrs = { @@ -485,8 +489,7 @@ class FakeSecurityGroupRule(object): :return: A FakeResource object, with id, etc. """ - if attrs is None: - attrs = {} + attrs = attrs or {} # Set default attributes. security_group_rule_attrs = { @@ -537,7 +540,7 @@ class FakeSubnet(object): """Fake one or more subnets.""" @staticmethod - def create_one_subnet(attrs={}): + def create_one_subnet(attrs=None): """Create a fake subnet. :param Dictionary attrs: @@ -545,6 +548,8 @@ class FakeSubnet(object): :return: A FakeResource object faking the subnet """ + attrs = attrs or {} + # Set default attributes. project_id = 'project-id-' + uuid.uuid4().hex subnet_attrs = { @@ -569,13 +574,14 @@ class FakeSubnet(object): subnet = fakes.FakeResource(info=copy.deepcopy(subnet_attrs), loaded=True) + # Set attributes with special mappings in OpenStack SDK. subnet.project_id = subnet_attrs['tenant_id'] return subnet @staticmethod - def create_subnets(attrs={}, count=2): + def create_subnets(attrs=None, count=2): """Create multiple fake subnets. :param Dictionary attrs: @@ -596,7 +602,7 @@ class FakeFloatingIP(object): """Fake one or more floating ip.""" @staticmethod - def create_one_floating_ip(attrs={}): + def create_one_floating_ip(attrs=None): """Create a fake floating ip. :param Dictionary attrs: @@ -604,6 +610,8 @@ class FakeFloatingIP(object): :return: A FakeResource object, with id, ip, and so on """ + attrs = attrs or {} + # Set default attributes. floating_ip_attrs = { 'id': 'floating-ip-id-' + uuid.uuid4().hex, @@ -632,7 +640,7 @@ class FakeFloatingIP(object): return floating_ip @staticmethod - def create_floating_ips(attrs={}, count=2): + def create_floating_ips(attrs=None, count=2): """Create multiple fake floating ips. :param Dictionary attrs: @@ -671,7 +679,7 @@ class FakeSubnetPool(object): """Fake one or more subnet pools.""" @staticmethod - def create_one_subnet_pool(attrs={}): + def create_one_subnet_pool(attrs=None): """Create a fake subnet pool. :param Dictionary attrs: @@ -679,6 +687,8 @@ class FakeSubnetPool(object): :return: A FakeResource object faking the subnet pool """ + attrs = attrs or {} + # Set default attributes. subnet_pool_attrs = { 'id': 'subnet-pool-id-' + uuid.uuid4().hex, @@ -709,7 +719,7 @@ class FakeSubnetPool(object): return subnet_pool @staticmethod - def create_subnet_pools(attrs={}, count=2): + def create_subnet_pools(attrs=None, count=2): """Create multiple fake subnet pools. :param Dictionary attrs: diff --git a/openstackclient/tests/network/v2/test_floating_ip.py b/openstackclient/tests/network/v2/test_floating_ip.py index 3e261fb5..f9ccfe1c 100644 --- a/openstackclient/tests/network/v2/test_floating_ip.py +++ b/openstackclient/tests/network/v2/test_floating_ip.py @@ -88,7 +88,6 @@ class TestCreateFloatingIPNetwork(TestFloatingIPNetwork): arglist = [] verifylist = [] - # Missing required args should bail here self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) @@ -314,7 +313,6 @@ class TestCreateFloatingIPCompute(TestFloatingIPCompute): arglist = [] verifylist = [] - # Missing required args should bail here self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) diff --git a/openstackclient/tests/network/v2/test_network.py b/openstackclient/tests/network/v2/test_network.py index a1b0aec9..1269b0a1 100644 --- a/openstackclient/tests/network/v2/test_network.py +++ b/openstackclient/tests/network/v2/test_network.py @@ -112,7 +112,6 @@ class TestCreateNetworkIdentityV3(TestNetwork): arglist = [] verifylist = [] - # Missing required args should bail here self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) @@ -599,7 +598,6 @@ class TestShowNetwork(TestNetwork): arglist = [] verifylist = [] - # Missing required args should bail here self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) @@ -617,8 +615,8 @@ class TestShowNetwork(TestNetwork): self.network.find_network.assert_called_once_with( self._network.name, ignore_missing=False) - self.assertEqual(tuple(self.columns), columns) - self.assertEqual(list(self.data), list(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) # Tests for Nova network @@ -916,7 +914,6 @@ class TestShowNetworkCompute(TestNetworkCompute): arglist = [] verifylist = [] - # Missing required args should bail here self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) @@ -931,5 +928,5 @@ class TestShowNetworkCompute(TestNetworkCompute): parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) - self.assertEqual(self.columns, tuple(columns)) + self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) diff --git a/openstackclient/tests/network/v2/test_router.py b/openstackclient/tests/network/v2/test_router.py index e8041498..655e86c9 100644 --- a/openstackclient/tests/network/v2/test_router.py +++ b/openstackclient/tests/network/v2/test_router.py @@ -47,7 +47,6 @@ class TestAddPortToRouter(TestRouter): arglist = [] verifylist = [] - # Missing required args should bail here self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) @@ -88,7 +87,6 @@ class TestAddSubnetToRouter(TestRouter): arglist = [] verifylist = [] - # Missing required args should bail here self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) @@ -138,7 +136,7 @@ class TestCreateRouter(TestRouter): new_router.id, new_router.name, new_router.tenant_id, - new_router.routes, + router._format_routes(new_router.routes), new_router.status, ) @@ -154,7 +152,6 @@ class TestCreateRouter(TestRouter): arglist = [] verifylist = [] - # Missing required args should bail here self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) @@ -268,7 +265,7 @@ class TestListRouter(TestRouter): r = routers[i] data_long.append( data[i] + ( - r.routes, + router._format_routes(r.routes), router._format_external_gateway_info(r.external_gateway_info), osc_utils.format_list(r.availability_zones), ) @@ -335,7 +332,6 @@ class TestRemovePortFromRouter(TestRouter): arglist = [] verifylist = [] - # Missing required args should bail here self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) @@ -375,7 +371,6 @@ class TestRemoveSubnetFromRouter(TestRouter): arglist = [] verifylist = [] - # Missing required args should bail here self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) @@ -399,7 +394,10 @@ class TestRemoveSubnetFromRouter(TestRouter): class TestSetRouter(TestRouter): # The router to set. - _router = network_fakes.FakeRouter.create_one_router() + _default_route = {'destination': '10.20.20.0/24', 'nexthop': '10.20.30.1'} + _router = network_fakes.FakeRouter.create_one_router( + attrs={'routes': [_default_route]} + ) def setUp(self): super(TestSetRouter, self).setUp() @@ -472,7 +470,6 @@ class TestSetRouter(TestRouter): ('distributed', False), ] - # Missing required args should bail here self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) @@ -491,8 +488,8 @@ class TestSetRouter(TestRouter): result = self.cmd.take_action(parsed_args) attrs = { - 'routes': [{'destination': '10.20.30.0/24', - 'gateway': '10.20.30.1'}], + 'routes': self._router.routes + [{'destination': '10.20.30.0/24', + 'nexthop': '10.20.30.1'}], } self.network.update_router.assert_called_once_with( self._router, **attrs) @@ -531,7 +528,6 @@ class TestSetRouter(TestRouter): ('clear_routes', True), ] - # Argument parse failing should bail here self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) @@ -572,7 +568,7 @@ class TestShowRouter(TestRouter): _router.id, _router.name, _router.tenant_id, - _router.routes, + router._format_routes(_router.routes), _router.status, ) @@ -588,7 +584,6 @@ class TestShowRouter(TestRouter): arglist = [] verifylist = [] - # Missing required args should bail here self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) @@ -605,5 +600,5 @@ class TestShowRouter(TestRouter): self.network.find_router.assert_called_once_with( self._router.name, ignore_missing=False) - self.assertEqual(tuple(self.columns), columns) + self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) diff --git a/openstackclient/tests/network/v2/test_security_group.py b/openstackclient/tests/network/v2/test_security_group.py index dd6a3d41..213367a4 100644 --- a/openstackclient/tests/network/v2/test_security_group.py +++ b/openstackclient/tests/network/v2/test_security_group.py @@ -114,7 +114,7 @@ class TestCreateSecurityGroupNetwork(TestSecurityGroupNetwork): 'description': self._security_group.name, 'name': self._security_group.name, }) - self.assertEqual(tuple(self.columns), columns) + self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) def test_create_all_options(self): @@ -139,7 +139,7 @@ class TestCreateSecurityGroupNetwork(TestSecurityGroupNetwork): 'name': self._security_group.name, 'tenant_id': identity_fakes.project_id, }) - self.assertEqual(tuple(self.columns), columns) + self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) @@ -296,28 +296,30 @@ class TestDeleteSecurityGroupCompute(TestSecurityGroupCompute): class TestListSecurityGroupNetwork(TestSecurityGroupNetwork): # The security group to be listed. - _security_group = \ - network_fakes.FakeSecurityGroup.create_one_security_group() + _security_groups = \ + network_fakes.FakeSecurityGroup.create_security_groups(count=3) - expected_columns = ( + columns = ( 'ID', 'Name', 'Description', 'Project', ) - expected_data = (( - _security_group.id, - _security_group.name, - _security_group.description, - _security_group.tenant_id, - ),) + data = [] + for grp in _security_groups: + data.append(( + grp.id, + grp.name, + grp.description, + grp.tenant_id, + )) def setUp(self): super(TestListSecurityGroupNetwork, self).setUp() self.network.security_groups = mock.Mock( - return_value=[self._security_group]) + return_value=self._security_groups) # Get the command object to test self.cmd = security_group.ListSecurityGroup(self.app, self.namespace) @@ -332,8 +334,8 @@ class TestListSecurityGroupNetwork(TestSecurityGroupNetwork): columns, data = self.cmd.take_action(parsed_args) self.network.security_groups.assert_called_once_with() - self.assertEqual(self.expected_columns, columns) - self.assertEqual(self.expected_data, tuple(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, list(data)) def test_security_group_list_all_projects(self): arglist = [ @@ -347,45 +349,49 @@ class TestListSecurityGroupNetwork(TestSecurityGroupNetwork): columns, data = self.cmd.take_action(parsed_args) self.network.security_groups.assert_called_once_with() - self.assertEqual(self.expected_columns, columns) - self.assertEqual(self.expected_data, tuple(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, list(data)) class TestListSecurityGroupCompute(TestSecurityGroupCompute): # The security group to be listed. - _security_group = \ - compute_fakes.FakeSecurityGroup.create_one_security_group() + _security_groups = \ + compute_fakes.FakeSecurityGroup.create_security_groups(count=3) - expected_columns = ( + columns = ( 'ID', 'Name', 'Description', ) - expected_columns_all_projects = ( + columns_all_projects = ( 'ID', 'Name', 'Description', 'Project', ) - expected_data = (( - _security_group.id, - _security_group.name, - _security_group.description, - ),) - expected_data_all_projects = (( - _security_group.id, - _security_group.name, - _security_group.description, - _security_group.tenant_id, - ),) + data = [] + for grp in _security_groups: + data.append(( + grp.id, + grp.name, + grp.description, + )) + data_all_projects = [] + for grp in _security_groups: + data_all_projects.append(( + grp.id, + grp.name, + grp.description, + grp.tenant_id, + )) def setUp(self): super(TestListSecurityGroupCompute, self).setUp() self.app.client_manager.network_endpoint_enabled = False - self.compute.security_groups.list.return_value = [self._security_group] + self.compute.security_groups.list.return_value = self._security_groups # Get the command object to test self.cmd = security_group.ListSecurityGroup(self.app, None) @@ -401,8 +407,8 @@ class TestListSecurityGroupCompute(TestSecurityGroupCompute): kwargs = {'search_opts': {'all_tenants': False}} self.compute.security_groups.list.assert_called_once_with(**kwargs) - self.assertEqual(self.expected_columns, columns) - self.assertEqual(self.expected_data, tuple(data)) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, list(data)) def test_security_group_list_all_projects(self): arglist = [ @@ -417,8 +423,8 @@ class TestListSecurityGroupCompute(TestSecurityGroupCompute): kwargs = {'search_opts': {'all_tenants': True}} self.compute.security_groups.list.assert_called_once_with(**kwargs) - self.assertEqual(self.expected_columns_all_projects, columns) - self.assertEqual(self.expected_data_all_projects, tuple(data)) + self.assertEqual(self.columns_all_projects, columns) + self.assertEqual(self.data_all_projects, list(data)) class TestSetSecurityGroupNetwork(TestSecurityGroupNetwork): diff --git a/openstackclient/tests/network/v2/test_security_group_rule.py b/openstackclient/tests/network/v2/test_security_group_rule.py index df7414aa..bd903f9e 100644 --- a/openstackclient/tests/network/v2/test_security_group_rule.py +++ b/openstackclient/tests/network/v2/test_security_group_rule.py @@ -174,7 +174,7 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): 'remote_ip_prefix': self._security_group_rule.remote_ip_prefix, 'security_group_id': self._security_group.id, }) - self.assertEqual(tuple(self.expected_columns), columns) + self.assertEqual(self.expected_columns, columns) self.assertEqual(self.expected_data, data) def test_create_source_group(self): @@ -209,7 +209,7 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): 'remote_group_id': self._security_group_rule.remote_group_id, 'security_group_id': self._security_group.id, }) - self.assertEqual(tuple(self.expected_columns), columns) + self.assertEqual(self.expected_columns, columns) self.assertEqual(self.expected_data, data) def test_create_source_ip(self): @@ -240,7 +240,7 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): 'remote_ip_prefix': self._security_group_rule.remote_ip_prefix, 'security_group_id': self._security_group.id, }) - self.assertEqual(tuple(self.expected_columns), columns) + self.assertEqual(self.expected_columns, columns) self.assertEqual(self.expected_data, data) def test_create_network_options(self): @@ -282,7 +282,7 @@ class TestCreateSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): 'security_group_id': self._security_group.id, 'tenant_id': identity_fakes.project_id, }) - self.assertEqual(tuple(self.expected_columns), columns) + self.assertEqual(self.expected_columns, columns) self.assertEqual(self.expected_data, data) @@ -816,7 +816,7 @@ class TestShowSecurityGroupRuleNetwork(TestSecurityGroupRuleNetwork): self.network.find_security_group_rule.assert_called_once_with( self._security_group_rule.id, ignore_missing=False) - self.assertEqual(tuple(self.columns), columns) + self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) diff --git a/openstackclient/tests/network/v2/test_subnet.py b/openstackclient/tests/network/v2/test_subnet.py index ede37416..1923286d 100644 --- a/openstackclient/tests/network/v2/test_subnet.py +++ b/openstackclient/tests/network/v2/test_subnet.py @@ -627,4 +627,4 @@ class TestShowSubnet(TestSubnet): self._subnet.name, ignore_missing=False) self.assertEqual(self.columns, columns) - self.assertEqual(list(self.data), list(data)) + self.assertEqual(self.data, data) diff --git a/openstackclient/tests/network/v2/test_subnet_pool.py b/openstackclient/tests/network/v2/test_subnet_pool.py index cbb32fc3..de12c9e9 100644 --- a/openstackclient/tests/network/v2/test_subnet_pool.py +++ b/openstackclient/tests/network/v2/test_subnet_pool.py @@ -109,7 +109,17 @@ class TestCreateSubnetPool(TestSubnetPool): arglist = [] verifylist = [] - # Missing required args should bail here + self.assertRaises(tests_utils.ParserException, self.check_parser, + self.cmd, arglist, verifylist) + + def test_create_no_pool_prefix(self): + """Make sure --pool-prefix is a required argument""" + arglist = [ + self._subnet_pool.name, + ] + verifylist = [ + ('name', self._subnet_pool.name), + ] self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) @@ -138,23 +148,26 @@ class TestCreateSubnetPool(TestSubnetPool): '--default-prefix-length', self._subnet_pool.default_prefixlen, '--max-prefix-length', self._subnet_pool.max_prefixlen, '--min-prefix-length', self._subnet_pool.min_prefixlen, + '--pool-prefix', '10.0.10.0/24', self._subnet_pool.name, ] verifylist = [ - ('default_prefix_length', self._subnet_pool.default_prefixlen), - ('max_prefix_length', self._subnet_pool.max_prefixlen), - ('min_prefix_length', self._subnet_pool.min_prefixlen), + ('default_prefix_length', + int(self._subnet_pool.default_prefixlen)), + ('max_prefix_length', int(self._subnet_pool.max_prefixlen)), + ('min_prefix_length', int(self._subnet_pool.min_prefixlen)), ('name', self._subnet_pool.name), + ('prefixes', ['10.0.10.0/24']), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = (self.cmd.take_action(parsed_args)) self.network.create_subnet_pool.assert_called_once_with(**{ - 'default_prefixlen': self._subnet_pool.default_prefixlen, - 'max_prefixlen': self._subnet_pool.max_prefixlen, - 'min_prefixlen': self._subnet_pool.min_prefixlen, - 'prefixes': [], + 'default_prefixlen': int(self._subnet_pool.default_prefixlen), + 'max_prefixlen': int(self._subnet_pool.max_prefixlen), + 'min_prefixlen': int(self._subnet_pool.min_prefixlen), + 'prefixes': ['10.0.10.0/24'], 'name': self._subnet_pool.name, }) self.assertEqual(self.columns, columns) @@ -221,6 +234,32 @@ class TestCreateSubnetPool(TestSubnetPool): self.assertEqual(self.columns, columns) self.assertEqual(self.data, data) + def test_create_default_and_shared_options(self): + arglist = [ + '--pool-prefix', '10.0.10.0/24', + '--default', + '--share', + self._subnet_pool.name, + ] + verifylist = [ + ('prefixes', ['10.0.10.0/24']), + ('default', True), + ('share', True), + ('name', self._subnet_pool.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + columns, data = (self.cmd.take_action(parsed_args)) + + self.network.create_subnet_pool.assert_called_once_with(**{ + 'is_default': True, + 'name': self._subnet_pool.name, + 'prefixes': ['10.0.10.0/24'], + 'shared': True, + }) + self.assertEqual(self.columns, columns) + self.assertEqual(self.data, data) + class TestDeleteSubnetPool(TestSubnetPool): @@ -267,6 +306,8 @@ class TestListSubnetPool(TestSubnetPool): columns_long = columns + ( 'Default Prefix Length', 'Address Scope', + 'Default Subnet Pool', + 'Shared', ) data = [] @@ -285,6 +326,8 @@ class TestListSubnetPool(TestSubnetPool): utils.format_list(pool.prefixes), pool.default_prefixlen, pool.address_scope_id, + pool.is_default, + pool.shared, )) def setUp(self): @@ -354,8 +397,8 @@ class TestSetSubnetPool(TestSubnetPool): ] verifylist = [ ('name', 'noob'), - ('default_prefix_length', '8'), - ('min_prefix_length', '8'), + ('default_prefix_length', 8), + ('min_prefix_length', 8), ('subnet_pool', self._subnet_pool.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -364,8 +407,8 @@ class TestSetSubnetPool(TestSubnetPool): attrs = { 'name': 'noob', - 'default_prefixlen': '8', - 'min_prefixlen': '8', + 'default_prefixlen': 8, + 'min_prefixlen': 8, } self.network.update_subnet_pool.assert_called_once_with( self._subnet_pool, **attrs) @@ -380,7 +423,7 @@ class TestSetSubnetPool(TestSubnetPool): ] verifylist = [ ('prefixes', ['10.0.1.0/24', '10.0.2.0/24']), - ('max_prefix_length', '16'), + ('max_prefix_length', 16), ('subnet_pool', self._subnet_pool.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) @@ -391,7 +434,7 @@ class TestSetSubnetPool(TestSubnetPool): prefixes.extend(self._subnet_pool.prefixes) attrs = { 'prefixes': prefixes, - 'max_prefixlen': '16', + 'max_prefixlen': 16, } self.network.update_subnet_pool.assert_called_once_with( self._subnet_pool, **attrs) @@ -474,6 +517,62 @@ class TestSetSubnetPool(TestSubnetPool): self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) + def test_set_default(self): + arglist = [ + '--default', + self._subnet_pool.name, + ] + verifylist = [ + ('default', True), + ('subnet_pool', self._subnet_pool.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + + attrs = { + 'is_default': True + } + self.network.update_subnet_pool.assert_called_once_with( + self._subnet_pool, **attrs) + self.assertIsNone(result) + + def test_set_no_default(self): + arglist = [ + '--no-default', + self._subnet_pool.name, + ] + verifylist = [ + ('no_default', True), + ('subnet_pool', self._subnet_pool.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + + attrs = { + 'is_default': False, + } + self.network.update_subnet_pool.assert_called_once_with( + self._subnet_pool, **attrs) + self.assertIsNone(result) + + def test_set_no_default_conflict(self): + arglist = [ + '--default', + '--no-default', + self._subnet_pool.name, + ] + verifylist = [ + ('default', True), + ('no_default', True), + ('subnet_pool', self._subnet_pool.name), + ] + + # Exclusive arguments will conflict here. + self.assertRaises(tests_utils.ParserException, self.check_parser, + self.cmd, arglist, verifylist) + class TestShowSubnetPool(TestSubnetPool): @@ -524,7 +623,6 @@ class TestShowSubnetPool(TestSubnetPool): arglist = [] verifylist = [] - # Missing required args should bail here self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) diff --git a/openstackclient/tests/volume/v1/fakes.py b/openstackclient/tests/volume/v1/fakes.py index 42673efa..d6c46439 100644 --- a/openstackclient/tests/volume/v1/fakes.py +++ b/openstackclient/tests/volume/v1/fakes.py @@ -129,6 +129,97 @@ QOS_WITH_ASSOCIATIONS = { } +class FakeServiceClient(object): + + def __init__(self, **kwargs): + self.services = mock.Mock() + self.services.resource_class = fakes.FakeResource(None, {}) + + +class TestService(utils.TestCommand): + + def setUp(self): + super(TestService, self).setUp() + + self.app.client_manager.volume = FakeServiceClient( + endpoint=fakes.AUTH_URL, + token=fakes.AUTH_TOKEN + ) + + +class FakeService(object): + """Fake one or more Services.""" + + @staticmethod + def create_one_service(attrs=None): + """Create a fake service. + + :param Dictionary attrs: + A dictionary with all attributes of service + :retrun: + A FakeResource object with host, status, etc. + """ + # Set default attribute + service_info = { + 'host': 'host_test', + 'binary': 'cinder_test', + 'status': 'enabled', + 'disabled_reason': 'LongHoliday-GoldenWeek', + 'zone': 'fake_zone', + 'updated_at': 'fake_date', + 'state': 'fake_state', + } + + # Overwrite default attributes if there are some attributes set + if attrs is None: + attrs = {} + service_info.update(attrs) + + service = fakes.FakeResource( + None, + service_info, + loaded=True) + + return service + + @staticmethod + def create_services(attrs=None, count=2): + """Create multiple fake services. + + :param Dictionary attrs: + A dictionary with all attributes of service + :param Integer count: + The number of services to be faked + :return: + A list of FakeResource objects + """ + services = [] + for n in range(0, count): + services.append(FakeService.create_one_service(attrs)) + + return services + + @staticmethod + def get_services(services=None, count=2): + """Get an iterable MagicMock object with a list of faked services. + + If services list is provided, then initialize the Mock object with the + list. Otherwise create one. + + :param List services: + A list of FakeResource objects faking services + :param Integer count: + The number of services to be faked + :return + An iterable Mock object with side_effect set to a list of faked + services + """ + if services is None: + services = FakeService.create_services(count) + + return mock.MagicMock(side_effect=services) + + class FakeImagev1Client(object): def __init__(self, **kwargs): diff --git a/openstackclient/tests/volume/v1/test_service.py b/openstackclient/tests/volume/v1/test_service.py new file mode 100644 index 00000000..71684344 --- /dev/null +++ b/openstackclient/tests/volume/v1/test_service.py @@ -0,0 +1,141 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + + +from openstackclient.tests.volume.v1 import fakes as service_fakes +from openstackclient.volume.v1 import service + + +class TestService(service_fakes.TestService): + + def setUp(self): + super(TestService, self).setUp() + + # Get a shortcut to the ServiceManager Mock + self.service_mock = self.app.client_manager.volume.services + self.service_mock.reset_mock() + + +class TestServiceList(TestService): + + # The service to be listed + services = service_fakes.FakeService.create_one_service() + + def setUp(self): + super(TestServiceList, self).setUp() + + self.service_mock.list.return_value = [self.services] + + # Get the command object to test + self.cmd = service.ListService(self.app, None) + + def test_service_list(self): + arglist = [ + '--host', self.services.host, + '--service', self.services.binary, + ] + verifylist = [ + ('host', self.services.host), + ('service', self.services.binary), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # In base command class Lister in cliff, abstract method take_action() + # returns a tuple containing the column names and an iterable + # containing the data to be listed. + columns, data = self.cmd.take_action(parsed_args) + + expected_columns = [ + 'Binary', + 'Host', + 'Zone', + 'Status', + 'State', + 'Updated At', + ] + + # confirming if all expected columns are present in the result. + self.assertEqual(expected_columns, columns) + + datalist = (( + self.services.binary, + self.services.host, + self.services.zone, + self.services.status, + self.services.state, + self.services.updated_at, + ), ) + + # confirming if all expected values are present in the result. + self.assertEqual(datalist, tuple(data)) + + # checking if proper call was made to list services + self.service_mock.list.assert_called_with( + self.services.host, + self.services.binary, + ) + + # checking if prohibited columns are present in output + self.assertNotIn("Disabled Reason", columns) + self.assertNotIn(self.services.disabled_reason, + tuple(data)) + + def test_service_list_with_long_option(self): + arglist = [ + '--host', self.services.host, + '--service', self.services.binary, + '--long' + ] + verifylist = [ + ('host', self.services.host), + ('service', self.services.binary), + ('long', True) + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # In base command class Lister in cliff, abstract method take_action() + # returns a tuple containing the column names and an iterable + # containing the data to be listed. + columns, data = self.cmd.take_action(parsed_args) + + expected_columns = [ + 'Binary', + 'Host', + 'Zone', + 'Status', + 'State', + 'Updated At', + 'Disabled Reason' + ] + + # confirming if all expected columns are present in the result. + self.assertEqual(expected_columns, columns) + + datalist = (( + self.services.binary, + self.services.host, + self.services.zone, + self.services.status, + self.services.state, + self.services.updated_at, + self.services.disabled_reason, + ), ) + + # confirming if all expected values are present in the result. + self.assertEqual(datalist, tuple(data)) + + self.service_mock.list.assert_called_with( + self.services.host, + self.services.binary, + ) diff --git a/openstackclient/tests/volume/v2/fakes.py b/openstackclient/tests/volume/v2/fakes.py index 6e631c41..120666a0 100644 --- a/openstackclient/tests/volume/v2/fakes.py +++ b/openstackclient/tests/volume/v2/fakes.py @@ -232,6 +232,97 @@ EXTENSION = { } +class FakeServiceClient(object): + + def __init__(self, **kwargs): + self.services = mock.Mock() + self.services.resource_class = fakes.FakeResource(None, {}) + + +class TestService(utils.TestCommand): + + def setUp(self): + super(TestService, self).setUp() + + self.app.client_manager.volume = FakeServiceClient( + endpoint=fakes.AUTH_URL, + token=fakes.AUTH_TOKEN + ) + + +class FakeService(object): + """Fake one or more Services.""" + + @staticmethod + def create_one_service(attrs=None): + """Create a fake service. + + :param Dictionary attrs: + A dictionary with all attributes of service + :retrun: + A FakeResource object with host, status, etc. + """ + # Set default attribute + service_info = { + 'host': 'host_test', + 'binary': 'cinder_test', + 'status': 'enabled', + 'disabled_reason': 'LongHoliday-GoldenWeek', + 'zone': 'fake_zone', + 'updated_at': 'fake_date', + 'state': 'fake_state', + } + + # Overwrite default attributes if there are some attributes set + if attrs is None: + attrs = {} + service_info.update(attrs) + + service = fakes.FakeResource( + None, + service_info, + loaded=True) + + return service + + @staticmethod + def create_services(attrs=None, count=2): + """Create multiple fake services. + + :param Dictionary attrs: + A dictionary with all attributes of service + :param Integer count: + The number of services to be faked + :return: + A list of FakeResource objects + """ + services = [] + for n in range(0, count): + services.append(FakeService.create_one_service(attrs)) + + return services + + @staticmethod + def get_services(services=None, count=2): + """Get an iterable MagicMock object with a list of faked services. + + If services list is provided, then initialize the Mock object with the + list. Otherwise create one. + + :param List services: + A list of FakeResource objects faking services + :param Integer count: + The number of services to be faked + :return + An iterable Mock object with side_effect set to a list of faked + services + """ + if services is None: + services = FakeService.create_services(count) + + return mock.MagicMock(side_effect=services) + + class FakeVolumeClient(object): def __init__(self, **kwargs): @@ -281,7 +372,7 @@ class FakeVolume(object): """ @staticmethod - def create_one_volume(attrs={}): + def create_one_volume(attrs=None): """Create a fake volume. :param Dictionary attrs: @@ -289,6 +380,8 @@ class FakeVolume(object): :retrun: A FakeResource object with id, name, status, etc. """ + attrs = attrs or {} + # Set default attribute volume_info = { 'id': 'volume-id' + uuid.uuid4().hex, @@ -320,7 +413,7 @@ class FakeVolume(object): return volume @staticmethod - def create_volumes(attrs={}, count=2): + def create_volumes(attrs=None, count=2): """Create multiple fake volumes. :param Dictionary attrs: @@ -361,7 +454,7 @@ class FakeAvailabilityZone(object): """Fake one or more volume availability zones (AZs).""" @staticmethod - def create_one_availability_zone(attrs={}): + def create_one_availability_zone(attrs=None): """Create a fake AZ. :param Dictionary attrs: @@ -369,6 +462,8 @@ class FakeAvailabilityZone(object): :return: A FakeResource object with zoneName, zoneState, etc. """ + attrs = attrs or {} + # Set default attributes. availability_zone = { 'zoneName': uuid.uuid4().hex, @@ -384,7 +479,7 @@ class FakeAvailabilityZone(object): return availability_zone @staticmethod - def create_availability_zones(attrs={}, count=2): + def create_availability_zones(attrs=None, count=2): """Create multiple fake AZs. :param Dictionary attrs: diff --git a/openstackclient/tests/volume/v2/test_service.py b/openstackclient/tests/volume/v2/test_service.py new file mode 100644 index 00000000..ba2e1b32 --- /dev/null +++ b/openstackclient/tests/volume/v2/test_service.py @@ -0,0 +1,141 @@ +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# + + +from openstackclient.tests.volume.v2 import fakes as service_fakes +from openstackclient.volume.v2 import service + + +class TestService(service_fakes.TestService): + + def setUp(self): + super(TestService, self).setUp() + + # Get a shortcut to the ServiceManager Mock + self.service_mock = self.app.client_manager.volume.services + self.service_mock.reset_mock() + + +class TestServiceList(TestService): + + # The service to be listed + services = service_fakes.FakeService.create_one_service() + + def setUp(self): + super(TestServiceList, self).setUp() + + self.service_mock.list.return_value = [self.services] + + # Get the command object to test + self.cmd = service.ListService(self.app, None) + + def test_service_list(self): + arglist = [ + '--host', self.services.host, + '--service', self.services.binary, + ] + verifylist = [ + ('host', self.services.host), + ('service', self.services.binary), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # In base command class Lister in cliff, abstract method take_action() + # returns a tuple containing the column names and an iterable + # containing the data to be listed. + columns, data = self.cmd.take_action(parsed_args) + + expected_columns = [ + 'Binary', + 'Host', + 'Zone', + 'Status', + 'State', + 'Updated At', + ] + + # confirming if all expected columns are present in the result. + self.assertEqual(expected_columns, columns) + + datalist = (( + self.services.binary, + self.services.host, + self.services.zone, + self.services.status, + self.services.state, + self.services.updated_at, + ), ) + + # confirming if all expected values are present in the result. + self.assertEqual(datalist, tuple(data)) + + # checking if proper call was made to list services + self.service_mock.list.assert_called_with( + self.services.host, + self.services.binary, + ) + + # checking if prohibited columns are present in output + self.assertNotIn("Disabled Reason", columns) + self.assertNotIn(self.services.disabled_reason, + tuple(data)) + + def test_service_list_with_long_option(self): + arglist = [ + '--host', self.services.host, + '--service', self.services.binary, + '--long' + ] + verifylist = [ + ('host', self.services.host), + ('service', self.services.binary), + ('long', True) + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + # In base command class Lister in cliff, abstract method take_action() + # returns a tuple containing the column names and an iterable + # containing the data to be listed. + columns, data = self.cmd.take_action(parsed_args) + + expected_columns = [ + 'Binary', + 'Host', + 'Zone', + 'Status', + 'State', + 'Updated At', + 'Disabled Reason' + ] + + # confirming if all expected columns are present in the result. + self.assertEqual(expected_columns, columns) + + datalist = (( + self.services.binary, + self.services.host, + self.services.zone, + self.services.status, + self.services.state, + self.services.updated_at, + self.services.disabled_reason, + ), ) + + # confirming if all expected values are present in the result. + self.assertEqual(datalist, tuple(data)) + + self.service_mock.list.assert_called_with( + self.services.host, + self.services.binary, + ) |
