# Copyright 2015 Symantec Corporation # # 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 unittest import mock from openstack.compute.v2 import flavor as _flavor from openstack import exceptions as sdk_exceptions from openstack import utils as sdk_utils from osc_lib.cli import format_columns from osc_lib import exceptions from openstackclient.compute.v2 import flavor from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes from openstackclient.tests.unit import utils as tests_utils class TestFlavor(compute_fakes.TestComputev2): def setUp(self): super(TestFlavor, self).setUp() # SDK mock self.app.client_manager.sdk_connection = mock.Mock() self.app.client_manager.sdk_connection.compute = mock.Mock() self.sdk_client = self.app.client_manager.sdk_connection.compute self.sdk_client.flavors = mock.Mock() self.sdk_client.find_flavor = mock.Mock() self.sdk_client.delete_flavor = mock.Mock() self.sdk_client.update_flavor = mock.Mock() self.sdk_client.flavor_add_tenant_access = mock.Mock() self.sdk_client.flavor_remove_tenant_access = mock.Mock() self.sdk_client.create_flavor_extra_specs = mock.Mock() self.sdk_client.update_flavor_extra_specs_property = mock.Mock() self.sdk_client.delete_flavor_extra_specs_property = mock.Mock() self.projects_mock = self.app.client_manager.identity.projects self.projects_mock.reset_mock() class TestFlavorCreate(TestFlavor): flavor = compute_fakes.FakeFlavor.create_one_flavor( attrs={'links': 'flavor-links'}) project = identity_fakes.FakeProject.create_one_project() columns = ( 'OS-FLV-DISABLED:disabled', 'OS-FLV-EXT-DATA:ephemeral', 'description', 'disk', 'id', 'name', 'os-flavor-access:is_public', 'properties', 'ram', 'rxtx_factor', 'swap', 'vcpus' ) data = ( flavor.is_disabled, flavor.ephemeral, flavor.description, flavor.disk, flavor.id, flavor.name, flavor.is_public, format_columns.DictColumn(flavor.extra_specs), flavor.ram, flavor.rxtx_factor, flavor.swap, flavor.vcpus, ) data_private = ( flavor.is_disabled, flavor.ephemeral, flavor.description, flavor.disk, flavor.id, flavor.name, False, format_columns.DictColumn(flavor.extra_specs), flavor.ram, flavor.rxtx_factor, flavor.swap, flavor.vcpus, ) def setUp(self): super(TestFlavorCreate, self).setUp() # Return a project self.projects_mock.get.return_value = self.project self.sdk_client.create_flavor.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 = { 'name': self.flavor.name, 'ram': 256, 'vcpus': 1, 'disk': 0, 'id': None, 'ephemeral': 0, 'swap': 0, 'rxtx_factor': 1.0, 'is_public': True, } columns, data = self.cmd.take_action(parsed_args) self.sdk_client.create_flavor.assert_called_once_with(**default_args) self.assertEqual(self.columns, columns) self.assertItemEqual(self.data, data) def test_flavor_create_all_options(self): arglist = [ '--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', '--description', str(self.flavor.description), '--property', 'property=value', self.flavor.name, ] verifylist = [ ('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), ('description', self.flavor.description), ('property', {'property': 'value'}), ('name', self.flavor.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) args = { 'name': self.flavor.name, 'ram': self.flavor.ram, 'vcpus': self.flavor.vcpus, 'disk': self.flavor.disk, 'id': self.flavor.id, 'ephemeral': self.flavor.ephemeral, 'swap': self.flavor.swap, 'rxtx_factor': self.flavor.rxtx_factor, 'is_public': self.flavor.is_public, 'description': self.flavor.description } props = {'property': 'value'} # SDK updates the flavor object instance. In order to make the # verification clear and preciese let's create new flavor and change # expected props this way create_flavor = _flavor.Flavor(**self.flavor) expected_flavor = _flavor.Flavor(**self.flavor) expected_flavor.extra_specs = props # convert expected data tuple to list to be able to modify it cmp_data = list(self.data) cmp_data[7] = format_columns.DictColumn(props) self.sdk_client.create_flavor.return_value = create_flavor self.sdk_client.create_flavor_extra_specs.return_value = \ expected_flavor with mock.patch.object(sdk_utils, 'supports_microversion', return_value=True): columns, data = self.cmd.take_action(parsed_args) self.sdk_client.create_flavor.assert_called_once_with(**args) self.sdk_client.create_flavor_extra_specs.assert_called_once_with( create_flavor, props) self.sdk_client.get_flavor_access.assert_not_called() self.assertEqual(self.columns, columns) self.assertItemEqual(tuple(cmp_data), data) def test_flavor_create_other_options(self): self.flavor.is_public = False arglist = [ '--id', 'auto', '--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', '--description', str(self.flavor.description), '--project', self.project.id, '--property', 'key1=value1', '--property', 'key2=value2', self.flavor.name, ] verifylist = [ ('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), ('description', 'description'), ('project', self.project.id), ('property', {'key1': 'value1', 'key2': 'value2'}), ('name', self.flavor.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) args = { 'name': self.flavor.name, 'ram': self.flavor.ram, 'vcpus': self.flavor.vcpus, 'disk': self.flavor.disk, 'id': 'auto', 'ephemeral': self.flavor.ephemeral, 'swap': self.flavor.swap, 'rxtx_factor': self.flavor.rxtx_factor, 'is_public': False, 'description': self.flavor.description } props = {'key1': 'value1', 'key2': 'value2'} # SDK updates the flavor object instance. In order to make the # verification clear and preciese let's create new flavor and change # expected props this way create_flavor = _flavor.Flavor(**self.flavor) expected_flavor = _flavor.Flavor(**self.flavor) expected_flavor.extra_specs = props expected_flavor.is_public = False # convert expected data tuple to list to be able to modify it cmp_data = list(self.data_private) cmp_data[7] = format_columns.DictColumn(props) self.sdk_client.create_flavor.return_value = create_flavor self.sdk_client.create_flavor_extra_specs.return_value = \ expected_flavor with mock.patch.object(sdk_utils, 'supports_microversion', return_value=True): columns, data = self.cmd.take_action(parsed_args) self.sdk_client.create_flavor.assert_called_once_with(**args) self.sdk_client.flavor_add_tenant_access.assert_called_with( self.flavor.id, self.project.id, ) self.sdk_client.create_flavor_extra_specs.assert_called_with( create_flavor, props) self.assertEqual(self.columns, columns) self.assertItemEqual(cmp_data, data) def test_public_flavor_create_with_project(self): arglist = [ '--project', self.project.id, self.flavor.name, ] verifylist = [ ('project', self.project.id), ('name', self.flavor.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) def test_flavor_create_no_options(self): arglist = [] verifylist = None self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_flavor_create_with_description_api_newer(self): arglist = [ '--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', '--description', 'fake description', self.flavor.name, ] verifylist = [ ('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), ('description', 'fake description'), ('name', self.flavor.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch.object(sdk_utils, 'supports_microversion', return_value=True): columns, data = self.cmd.take_action(parsed_args) args = { 'name': self.flavor.name, 'ram': self.flavor.ram, 'vcpus': self.flavor.vcpus, 'disk': self.flavor.disk, 'id': self.flavor.id, 'ephemeral': self.flavor.ephemeral, 'swap': self.flavor.swap, 'rxtx_factor': self.flavor.rxtx_factor, 'is_public': self.flavor.is_public, 'description': 'fake description' } self.sdk_client.create_flavor.assert_called_once_with(**args) self.assertEqual(self.columns, columns) self.assertItemEqual(self.data_private, data) def test_flavor_create_with_description_api_older(self): arglist = [ '--id', self.flavor.id, '--ram', str(self.flavor.ram), '--vcpus', str(self.flavor.vcpus), '--description', 'description', self.flavor.name, ] verifylist = [ ('ram', self.flavor.ram), ('vcpus', self.flavor.vcpus), ('description', 'description'), ('name', self.flavor.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) with mock.patch.object(sdk_utils, 'supports_microversion', return_value=False): self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) class TestFlavorDelete(TestFlavor): flavors = compute_fakes.FakeFlavor.create_flavors(count=2) def setUp(self): super(TestFlavorDelete, self).setUp() self.sdk_client.delete_flavor.return_value = None self.cmd = flavor.DeleteFlavor(self.app, None) def test_flavor_delete(self): arglist = [ self.flavors[0].id ] verifylist = [ ('flavor', [self.flavors[0].id]), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.sdk_client.find_flavor.return_value = self.flavors[0] result = self.cmd.take_action(parsed_args) self.sdk_client.find_flavor.assert_called_with(self.flavors[0].id, ignore_missing=False) self.sdk_client.delete_flavor.assert_called_with(self.flavors[0].id) self.assertIsNone(result) def test_delete_multiple_flavors(self): arglist = [] for f in self.flavors: arglist.append(f.id) verifylist = [ ('flavor', arglist), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.sdk_client.find_flavor.side_effect = self.flavors result = self.cmd.take_action(parsed_args) find_calls = [ mock.call(i.id, ignore_missing=False) for i in self.flavors ] delete_calls = [mock.call(i.id) for i in self.flavors] self.sdk_client.find_flavor.assert_has_calls(find_calls) self.sdk_client.delete_flavor.assert_has_calls(delete_calls) self.assertIsNone(result) def test_multi_flavors_delete_with_exception(self): arglist = [ self.flavors[0].id, 'unexist_flavor', ] verifylist = [ ('flavor', [self.flavors[0].id, 'unexist_flavor']) ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.sdk_client.find_flavor.side_effect = [ self.flavors[0], sdk_exceptions.ResourceNotFound ] try: self.cmd.take_action(parsed_args) self.fail('CommandError should be raised.') except exceptions.CommandError as e: self.assertEqual('1 of 2 flavors failed to delete.', str(e)) find_calls = [ mock.call(self.flavors[0].id, ignore_missing=False), mock.call('unexist_flavor', ignore_missing=False), ] delete_calls = [mock.call(self.flavors[0].id)] self.sdk_client.find_flavor.assert_has_calls(find_calls) self.sdk_client.delete_flavor.assert_has_calls(delete_calls) class TestFlavorList(TestFlavor): _flavor = compute_fakes.FakeFlavor.create_one_flavor() columns = ( 'ID', 'Name', 'RAM', 'Disk', 'Ephemeral', 'VCPUs', 'Is Public', ) columns_long = columns + ( 'Swap', 'RXTX Factor', 'Properties' ) data = (( _flavor.id, _flavor.name, _flavor.ram, _flavor.disk, _flavor.ephemeral, _flavor.vcpus, _flavor.is_public, ),) data_long = (data[0] + ( _flavor.swap, _flavor.rxtx_factor, format_columns.DictColumn(_flavor.extra_specs) ), ) def setUp(self): super(TestFlavorList, self).setUp() self.api_mock = mock.Mock() self.api_mock.side_effect = [[self._flavor], [], ] self.sdk_client.flavors = self.api_mock # Get the command object to test self.cmd = flavor.ListFlavor(self.app, None) def test_flavor_list_no_options(self): arglist = [] verifylist = [ ('public', True), ('all', False), ('long', False), ] 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) # Set expected values kwargs = { 'is_public': True, } self.sdk_client.flavors.assert_called_with( **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.data, tuple(data)) def test_flavor_list_all_flavors(self): arglist = [ '--all', ] verifylist = [ ('all', 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) # Set expected values kwargs = { 'is_public': None, } self.sdk_client.flavors.assert_called_with( **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.data, tuple(data)) def test_flavor_list_private_flavors(self): arglist = [ '--private', ] verifylist = [ ('public', False), ] 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) # Set expected values kwargs = { 'is_public': False, } self.sdk_client.flavors.assert_called_with( **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.data, tuple(data)) def test_flavor_list_public_flavors(self): arglist = [ '--public', ] verifylist = [ ('public', 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) # Set expected values kwargs = { 'is_public': True, } self.sdk_client.flavors.assert_called_with( **kwargs ) self.assertEqual(self.columns, columns) self.assertEqual(self.data, tuple(data)) def test_flavor_list_long(self): arglist = [ '--long', ] verifylist = [ ('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) # Set expected values kwargs = { 'is_public': True, } self.sdk_client.flavors.assert_called_with( **kwargs ) self.assertEqual(self.columns_long, columns) self.assertListItemEqual(self.data_long, tuple(data)) class TestFlavorSet(TestFlavor): # Return value of self.sdk_client.find_flavor(). flavor = compute_fakes.FakeFlavor.create_one_flavor( attrs={'os-flavor-access:is_public': False}) project = identity_fakes.FakeProject.create_one_project() def setUp(self): super(TestFlavorSet, self).setUp() self.sdk_client.find_flavor.return_value = self.flavor # Return a project self.projects_mock.get.return_value = self.project self.cmd = flavor.SetFlavor(self.app, None) def test_flavor_set_property(self): arglist = [ '--property', 'FOO="B A R"', 'baremetal' ] verifylist = [ ('property', {'FOO': '"B A R"'}), ('flavor', 'baremetal') ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.sdk_client.find_flavor.assert_called_with( parsed_args.flavor, get_extra_specs=True, ignore_missing=False ) self.sdk_client.create_flavor_extra_specs.assert_called_with( self.flavor.id, {'FOO': '"B A R"'}) self.assertIsNone(result) def test_flavor_set_no_property(self): arglist = [ '--no-property', 'baremetal' ] verifylist = [ ('no_property', True), ('flavor', 'baremetal') ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.sdk_client.find_flavor.assert_called_with( parsed_args.flavor, get_extra_specs=True, ignore_missing=False ) self.sdk_client.delete_flavor_extra_specs_property.assert_called_with( self.flavor.id, 'property') self.assertIsNone(result) def test_flavor_set_project(self): arglist = [ '--project', self.project.id, self.flavor.id, ] verifylist = [ ('project', self.project.id), ('flavor', self.flavor.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.sdk_client.find_flavor.assert_called_with( parsed_args.flavor, get_extra_specs=True, ignore_missing=False ) self.sdk_client.flavor_add_tenant_access.assert_called_with( self.flavor.id, self.project.id, ) self.sdk_client.create_flavor_extra_specs.assert_not_called() self.assertIsNone(result) def test_flavor_set_no_project(self): arglist = [ '--project', self.flavor.id, ] verifylist = [ ('project', None), ('flavor', self.flavor.id), ] self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_flavor_set_no_flavor(self): arglist = [ '--project', self.project.id, ] verifylist = [ ('project', self.project.id), ] self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_flavor_set_with_unexist_flavor(self): self.sdk_client.find_flavor.side_effect = [ sdk_exceptions.ResourceNotFound() ] arglist = [ '--project', self.project.id, 'unexist_flavor', ] verifylist = [ ('project', self.project.id), ('flavor', 'unexist_flavor'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) def test_flavor_set_nothing(self): arglist = [ self.flavor.id, ] verifylist = [ ('flavor', self.flavor.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.sdk_client.find_flavor.assert_called_with( parsed_args.flavor, get_extra_specs=True, ignore_missing=False ) self.sdk_client.flavor_add_tenant_access.assert_not_called() self.assertIsNone(result) def test_flavor_set_description_api_newer(self): arglist = [ '--description', 'description', self.flavor.id, ] verifylist = [ ('description', 'description'), ('flavor', self.flavor.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.app.client_manager.compute.api_version = 2.55 with mock.patch.object(sdk_utils, 'supports_microversion', return_value=True): result = self.cmd.take_action(parsed_args) self.sdk_client.update_flavor.assert_called_with( flavor=self.flavor.id, description='description') self.assertIsNone(result) def test_flavor_set_description_api_older(self): arglist = [ '--description', 'description', self.flavor.id, ] verifylist = [ ('description', 'description'), ('flavor', self.flavor.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.app.client_manager.compute.api_version = 2.54 with mock.patch.object(sdk_utils, 'supports_microversion', return_value=False): self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) def test_flavor_set_description_using_name_api_newer(self): arglist = [ '--description', 'description', self.flavor.name, ] verifylist = [ ('description', 'description'), ('flavor', self.flavor.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.app.client_manager.compute.api_version = 2.55 with mock.patch.object(sdk_utils, 'supports_microversion', return_value=True): result = self.cmd.take_action(parsed_args) self.sdk_client.update_flavor.assert_called_with( flavor=self.flavor.id, description='description') self.assertIsNone(result) def test_flavor_set_description_using_name_api_older(self): arglist = [ '--description', 'description', self.flavor.name, ] verifylist = [ ('description', 'description'), ('flavor', self.flavor.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.app.client_manager.compute.api_version = 2.54 with mock.patch.object(sdk_utils, 'supports_microversion', return_value=False): self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) class TestFlavorShow(TestFlavor): # Return value of self.sdk_client.find_flavor(). flavor_access = compute_fakes.FakeFlavorAccess.create_one_flavor_access() flavor = compute_fakes.FakeFlavor.create_one_flavor() columns = ( 'OS-FLV-DISABLED:disabled', 'OS-FLV-EXT-DATA:ephemeral', 'access_project_ids', 'description', 'disk', 'id', 'name', 'os-flavor-access:is_public', 'properties', 'ram', 'rxtx_factor', 'swap', 'vcpus' ) data = ( flavor.is_disabled, flavor.ephemeral, None, flavor.description, flavor.disk, flavor.id, flavor.name, flavor.is_public, format_columns.DictColumn(flavor.extra_specs), flavor.ram, flavor.rxtx_factor, flavor.swap, flavor.vcpus, ) def setUp(self): super(TestFlavorShow, self).setUp() # Return value of _find_resource() self.sdk_client.find_flavor.return_value = self.flavor self.sdk_client.get_flavor_access.return_value = [self.flavor_access] self.cmd = flavor.ShowFlavor(self.app, None) def test_show_no_options(self): arglist = [] verifylist = [] # Missing required args should boil here self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_public_flavor_show(self): arglist = [ self.flavor.name, ] verifylist = [ ('flavor', self.flavor.name), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.assertEqual(self.columns, columns) self.assertItemEqual(self.data, data) def test_private_flavor_show(self): private_flavor = compute_fakes.FakeFlavor.create_one_flavor( attrs={ 'os-flavor-access:is_public': False, } ) self.sdk_client.find_flavor.return_value = private_flavor arglist = [ private_flavor.name, ] verifylist = [ ('flavor', private_flavor.name), ] data_with_project = ( private_flavor.is_disabled, private_flavor.ephemeral, [self.flavor_access.tenant_id], private_flavor.description, private_flavor.disk, private_flavor.id, private_flavor.name, private_flavor.is_public, format_columns.DictColumn(private_flavor.extra_specs), private_flavor.ram, private_flavor.rxtx_factor, private_flavor.swap, private_flavor.vcpus, ) parsed_args = self.check_parser(self.cmd, arglist, verifylist) columns, data = self.cmd.take_action(parsed_args) self.sdk_client.get_flavor_access.assert_called_with( flavor=private_flavor.id) self.assertEqual(self.columns, columns) self.assertItemEqual(data_with_project, data) class TestFlavorUnset(TestFlavor): # Return value of self.sdk_client.find_flavor(). flavor = compute_fakes.FakeFlavor.create_one_flavor( attrs={'os-flavor-access:is_public': False}) project = identity_fakes.FakeProject.create_one_project() def setUp(self): super(TestFlavorUnset, self).setUp() self.sdk_client.find_flavor.return_value = self.flavor # Return a project self.projects_mock.get.return_value = self.project self.cmd = flavor.UnsetFlavor(self.app, None) self.mock_shortcut = self.sdk_client.delete_flavor_extra_specs_property def test_flavor_unset_property(self): arglist = [ '--property', 'property', 'baremetal' ] verifylist = [ ('property', ['property']), ('flavor', 'baremetal'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.sdk_client.find_flavor.assert_called_with( parsed_args.flavor, get_extra_specs=True, ignore_missing=False) self.mock_shortcut.assert_called_with( self.flavor.id, 'property') self.sdk_client.flavor_remove_tenant_access.assert_not_called() self.assertIsNone(result) def test_flavor_unset_properties(self): arglist = [ '--property', 'property1', '--property', 'property2', 'baremetal' ] verifylist = [ ('property', ['property1', 'property2']), ('flavor', 'baremetal'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) self.sdk_client.find_flavor.assert_called_with( parsed_args.flavor, get_extra_specs=True, ignore_missing=False) calls = [ mock.call(self.flavor.id, 'property1'), mock.call(self.flavor.id, 'property2') ] self.mock_shortcut.assert_has_calls( calls) # A bit tricky way to ensure we do not unset other properties calls.append(mock.call(self.flavor.id, 'property')) self.assertRaises( AssertionError, self.mock_shortcut.assert_has_calls, calls ) self.sdk_client.flavor_remove_tenant_access.assert_not_called() def test_flavor_unset_project(self): arglist = [ '--project', self.project.id, self.flavor.id, ] verifylist = [ ('project', self.project.id), ('flavor', self.flavor.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.assertIsNone(result) self.sdk_client.find_flavor.assert_called_with( parsed_args.flavor, get_extra_specs=True, ignore_missing=False) self.sdk_client.flavor_remove_tenant_access.assert_called_with( self.flavor.id, self.project.id, ) self.sdk_client.delete_flavor_extra_specs_proerty.assert_not_called() self.assertIsNone(result) def test_flavor_unset_no_project(self): arglist = [ '--project', self.flavor.id, ] verifylist = [ ('project', None), ('flavor', self.flavor.id), ] self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_flavor_unset_no_flavor(self): arglist = [ '--project', self.project.id, ] verifylist = [ ('project', self.project.id), ] self.assertRaises(tests_utils.ParserException, self.check_parser, self.cmd, arglist, verifylist) def test_flavor_unset_with_unexist_flavor(self): self.sdk_client.find_flavor.side_effect = [ sdk_exceptions.ResourceNotFound ] arglist = [ '--project', self.project.id, 'unexist_flavor', ] verifylist = [ ('project', self.project.id), ('flavor', 'unexist_flavor'), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.assertRaises(exceptions.CommandError, self.cmd.take_action, parsed_args) def test_flavor_unset_nothing(self): arglist = [ self.flavor.id, ] verifylist = [ ('flavor', self.flavor.id), ] parsed_args = self.check_parser(self.cmd, arglist, verifylist) result = self.cmd.take_action(parsed_args) self.assertIsNone(result) self.sdk_client.flavor_remove_tenant_access.assert_not_called()