summaryrefslogtreecommitdiff
path: root/openstackclient/tests/unit
diff options
context:
space:
mode:
Diffstat (limited to 'openstackclient/tests/unit')
-rw-r--r--openstackclient/tests/unit/api/test_utils.py115
-rw-r--r--openstackclient/tests/unit/common/test_commandmanager.py107
-rw-r--r--openstackclient/tests/unit/compute/v2/test_server.py447
-rw-r--r--openstackclient/tests/unit/identity/v3/fakes.py62
-rw-r--r--openstackclient/tests/unit/identity/v3/test_endpoint_group.py495
-rw-r--r--openstackclient/tests/unit/image/v1/test_image.py2
-rw-r--r--openstackclient/tests/unit/image/v2/test_image.py2
7 files changed, 1005 insertions, 225 deletions
diff --git a/openstackclient/tests/unit/api/test_utils.py b/openstackclient/tests/unit/api/test_utils.py
deleted file mode 100644
index 1f528558..00000000
--- a/openstackclient/tests/unit/api/test_utils.py
+++ /dev/null
@@ -1,115 +0,0 @@
-# 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.
-#
-
-"""API Utilities Library Tests"""
-
-import copy
-
-from openstackclient.api import api
-from openstackclient.api import utils as api_utils
-from openstackclient.tests.unit.api import fakes as api_fakes
-
-
-class TestBaseAPIFilter(api_fakes.TestSession):
- """The filters can be tested independently"""
-
- def setUp(self):
- super(TestBaseAPIFilter, self).setUp()
- self.api = api.BaseAPI(
- session=self.sess,
- endpoint=self.BASE_URL,
- )
-
- self.input_list = [
- api_fakes.RESP_ITEM_1,
- api_fakes.RESP_ITEM_2,
- api_fakes.RESP_ITEM_3,
- ]
-
- def test_simple_filter_none(self):
- output = api_utils.simple_filter(
- )
- self.assertIsNone(output)
-
- def test_simple_filter_no_attr(self):
- output = api_utils.simple_filter(
- copy.deepcopy(self.input_list),
- )
- self.assertEqual(self.input_list, output)
-
- def test_simple_filter_attr_only(self):
- output = api_utils.simple_filter(
- copy.deepcopy(self.input_list),
- attr='status',
- )
- self.assertEqual(self.input_list, output)
-
- def test_simple_filter_attr_value(self):
- output = api_utils.simple_filter(
- copy.deepcopy(self.input_list),
- attr='status',
- value='',
- )
- self.assertEqual([], output)
-
- output = api_utils.simple_filter(
- copy.deepcopy(self.input_list),
- attr='status',
- value='UP',
- )
- self.assertEqual(
- [api_fakes.RESP_ITEM_1, api_fakes.RESP_ITEM_3],
- output,
- )
-
- output = api_utils.simple_filter(
- copy.deepcopy(self.input_list),
- attr='fred',
- value='UP',
- )
- self.assertEqual([], output)
-
- def test_simple_filter_prop_attr_only(self):
- output = api_utils.simple_filter(
- copy.deepcopy(self.input_list),
- attr='b',
- property_field='props',
- )
- self.assertEqual(self.input_list, output)
-
- output = api_utils.simple_filter(
- copy.deepcopy(self.input_list),
- attr='status',
- property_field='props',
- )
- self.assertEqual(self.input_list, output)
-
- def test_simple_filter_prop_attr_value(self):
- output = api_utils.simple_filter(
- copy.deepcopy(self.input_list),
- attr='b',
- value=2,
- property_field='props',
- )
- self.assertEqual(
- [api_fakes.RESP_ITEM_1, api_fakes.RESP_ITEM_2],
- output,
- )
-
- output = api_utils.simple_filter(
- copy.deepcopy(self.input_list),
- attr='b',
- value=9,
- property_field='props',
- )
- self.assertEqual([], output)
diff --git a/openstackclient/tests/unit/common/test_commandmanager.py b/openstackclient/tests/unit/common/test_commandmanager.py
deleted file mode 100644
index 0c6c99c0..00000000
--- a/openstackclient/tests/unit/common/test_commandmanager.py
+++ /dev/null
@@ -1,107 +0,0 @@
-# Copyright 2012-2013 OpenStack Foundation
-#
-# 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 commandmanager
-from openstackclient.tests.unit import utils
-
-
-class FakeCommand(object):
-
- @classmethod
- def load(cls):
- return cls
-
- def __init__(self):
- return
-
-FAKE_CMD_ONE = FakeCommand
-FAKE_CMD_TWO = FakeCommand
-FAKE_CMD_ALPHA = FakeCommand
-FAKE_CMD_BETA = FakeCommand
-
-
-class FakeCommandManager(commandmanager.CommandManager):
- commands = {}
-
- def load_commands(self, namespace):
- if namespace == 'test':
- self.commands['one'] = FAKE_CMD_ONE
- self.commands['two'] = FAKE_CMD_TWO
- self.group_list.append(namespace)
- elif namespace == 'greek':
- self.commands['alpha'] = FAKE_CMD_ALPHA
- self.commands['beta'] = FAKE_CMD_BETA
- self.group_list.append(namespace)
-
-
-class TestCommandManager(utils.TestCase):
-
- def test_add_command_group(self):
- mgr = FakeCommandManager('test')
-
- # Make sure add_command() still functions
- mock_cmd_one = mock.Mock()
- mgr.add_command('mock', mock_cmd_one)
- cmd_mock, name, args = mgr.find_command(['mock'])
- self.assertEqual(mock_cmd_one, cmd_mock)
-
- # Find a command added in initialization
- cmd_one, name, args = mgr.find_command(['one'])
- self.assertEqual(FAKE_CMD_ONE, cmd_one)
-
- # Load another command group
- mgr.add_command_group('greek')
-
- # Find a new command
- cmd_alpha, name, args = mgr.find_command(['alpha'])
- self.assertEqual(FAKE_CMD_ALPHA, cmd_alpha)
-
- # Ensure that the original commands were not overwritten
- cmd_two, name, args = mgr.find_command(['two'])
- self.assertEqual(FAKE_CMD_TWO, cmd_two)
-
- def test_get_command_groups(self):
- mgr = FakeCommandManager('test')
-
- # Make sure add_command() still functions
- mock_cmd_one = mock.Mock()
- mgr.add_command('mock', mock_cmd_one)
- cmd_mock, name, args = mgr.find_command(['mock'])
- self.assertEqual(mock_cmd_one, cmd_mock)
-
- # Load another command group
- mgr.add_command_group('greek')
-
- gl = mgr.get_command_groups()
- self.assertEqual(['test', 'greek'], gl)
-
- def test_get_command_names(self):
- mock_cmd_one = mock.Mock()
- mock_cmd_one.name = 'one'
- mock_cmd_two = mock.Mock()
- mock_cmd_two.name = 'cmd two'
- mock_pkg_resources = mock.Mock(
- return_value=[mock_cmd_one, mock_cmd_two],
- )
- with mock.patch(
- 'pkg_resources.iter_entry_points',
- mock_pkg_resources,
- ) as iter_entry_points:
- mgr = commandmanager.CommandManager('test')
- iter_entry_points.assert_called_once_with('test')
- cmds = mgr.get_command_names('test')
- self.assertEqual(['one', 'cmd two'], cmds)
diff --git a/openstackclient/tests/unit/compute/v2/test_server.py b/openstackclient/tests/unit/compute/v2/test_server.py
index c30af8fb..4a37a812 100644
--- a/openstackclient/tests/unit/compute/v2/test_server.py
+++ b/openstackclient/tests/unit/compute/v2/test_server.py
@@ -23,6 +23,7 @@ from openstack import exceptions as sdk_exceptions
from osc_lib import exceptions
from osc_lib import utils as common_utils
from oslo_utils import timeutils
+import six
from openstackclient.compute.v2 import server
from openstackclient.tests.unit.compute.v2 import fakes as compute_fakes
@@ -1834,6 +1835,90 @@ class TestServerCreate(TestServer):
self.cmd.take_action,
parsed_args)
+ def test_server_create_with_description_api_newer(self):
+
+ # Description is supported for nova api version 2.19 or above
+ self.app.client_manager.compute.api_version = 2.19
+
+ arglist = [
+ '--image', 'image1',
+ '--flavor', 'flavor1',
+ '--description', 'description1',
+ self.new_server.name,
+ ]
+ verifylist = [
+ ('image', 'image1'),
+ ('flavor', 'flavor1'),
+ ('description', 'description1'),
+ ('config_drive', False),
+ ('server_name', self.new_server.name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ with mock.patch.object(api_versions,
+ 'APIVersion',
+ return_value=2.19):
+ # In base command class ShowOne in cliff, abstract method
+ # take_action() returns a two-part tuple with a tuple of
+ # column names and a tuple of data to be shown.
+ columns, data = self.cmd.take_action(parsed_args)
+
+ # Set expected values
+ kwargs = dict(
+ meta=None,
+ files={},
+ reservation_id=None,
+ min_count=1,
+ max_count=1,
+ security_groups=[],
+ userdata=None,
+ key_name=None,
+ availability_zone=None,
+ block_device_mapping_v2=[],
+ nics='auto',
+ scheduler_hints={},
+ config_drive=None,
+ description='description1',
+ )
+ # ServerManager.create(name, image, flavor, **kwargs)
+ self.servers_mock.create.assert_called_with(
+ self.new_server.name,
+ self.image,
+ self.flavor,
+ **kwargs
+ )
+
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(self.datalist(), data)
+ self.assertFalse(self.images_mock.called)
+ self.assertFalse(self.flavors_mock.called)
+
+ def test_server_create_with_description_api_older(self):
+
+ # Description is not supported for nova api version below 2.19
+ self.app.client_manager.compute.api_version = 2.18
+
+ arglist = [
+ '--image', 'image1',
+ '--flavor', 'flavor1',
+ '--description', 'description1',
+ self.new_server.name,
+ ]
+ verifylist = [
+ ('image', 'image1'),
+ ('flavor', 'flavor1'),
+ ('description', 'description1'),
+ ('config_drive', False),
+ ('server_name', self.new_server.name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ with mock.patch.object(api_versions,
+ 'APIVersion',
+ return_value=2.19):
+ self.assertRaises(exceptions.CommandError, self.cmd.take_action,
+ parsed_args)
+
class TestServerDelete(TestServer):
@@ -1991,6 +2076,7 @@ class TestServerList(TestServer):
'user_id': None,
'deleted': False,
'changes-since': None,
+ 'changes-before': None,
}
# Default params of the core function of the command in the case of no
@@ -2272,6 +2358,71 @@ class TestServerList(TestServer):
'Invalid time value'
)
+ def test_server_list_v266_with_changes_before(self):
+ self.app.client_manager.compute.api_version = (
+ api_versions.APIVersion('2.66'))
+ arglist = [
+ '--changes-before', '2016-03-05T06:27:59Z',
+ '--deleted'
+ ]
+ verifylist = [
+ ('changes_before', '2016-03-05T06:27:59Z'),
+ ('deleted', True),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.search_opts['changes-before'] = '2016-03-05T06:27:59Z'
+ self.search_opts['deleted'] = True
+ self.servers_mock.list.assert_called_with(**self.kwargs)
+
+ self.assertEqual(self.columns, columns)
+ self.assertEqual(tuple(self.data), tuple(data))
+
+ @mock.patch.object(timeutils, 'parse_isotime', side_effect=ValueError)
+ def test_server_list_v266_with_invalid_changes_before(
+ self, mock_parse_isotime):
+ self.app.client_manager.compute.api_version = (
+ api_versions.APIVersion('2.66'))
+
+ arglist = [
+ '--changes-before', 'Invalid time value',
+ ]
+ verifylist = [
+ ('changes_before', 'Invalid time value'),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ try:
+ self.cmd.take_action(parsed_args)
+ self.fail('CommandError should be raised.')
+ except exceptions.CommandError as e:
+ self.assertEqual('Invalid changes-before value: Invalid time '
+ 'value', str(e))
+ mock_parse_isotime.assert_called_once_with(
+ 'Invalid time value'
+ )
+
+ def test_server_with_changes_before_older_version(self):
+ self.app.client_manager.compute.api_version = (
+ api_versions.APIVersion('2.65'))
+
+ arglist = [
+ '--changes-before', '2016-03-05T06:27:59Z',
+ '--deleted'
+ ]
+ verifylist = [
+ ('changes_before', '2016-03-05T06:27:59Z'),
+ ('deleted', True),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.assertRaises(exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args)
+
def test_server_list_v269_with_partial_constructs(self):
self.app.client_manager.compute.api_version = \
api_versions.APIVersion('2.69')
@@ -2415,12 +2566,40 @@ class TestServerMigrate(TestServer):
self.assertNotCalled(self.servers_mock.live_migrate)
self.assertNotCalled(self.servers_mock.migrate)
+ def test_server_migrate_with_host(self):
+ # Tests that --host is not allowed for a cold migration.
+ arglist = [
+ '--host', 'fakehost', self.server.id,
+ ]
+ verifylist = [
+ ('live', None),
+ ('live_migration', False),
+ ('host', 'fakehost'),
+ ('block_migration', False),
+ ('disk_overcommit', False),
+ ('wait', False),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ ex = self.assertRaises(exceptions.CommandError, self.cmd.take_action,
+ parsed_args)
+
+ # Make sure it's the error we expect.
+ self.assertIn("--live-migration must be specified if "
+ "--block-migration, --disk-overcommit or --host is "
+ "specified", six.text_type(ex))
+ self.servers_mock.get.assert_called_with(self.server.id)
+ self.assertNotCalled(self.servers_mock.live_migrate)
+ self.assertNotCalled(self.servers_mock.migrate)
+
def test_server_live_migrate(self):
arglist = [
'--live', 'fakehost', self.server.id,
]
verifylist = [
('live', 'fakehost'),
+ ('live_migration', False),
+ ('host', None),
('block_migration', False),
('disk_overcommit', False),
('wait', False),
@@ -2430,7 +2609,8 @@ class TestServerMigrate(TestServer):
self.app.client_manager.compute.api_version = \
api_versions.APIVersion('2.24')
- result = self.cmd.take_action(parsed_args)
+ with mock.patch.object(self.cmd.log, 'warning') as mock_warning:
+ result = self.cmd.take_action(parsed_args)
self.servers_mock.get.assert_called_with(self.server.id)
self.server.live_migrate.assert_called_with(block_migration=False,
@@ -2438,6 +2618,132 @@ class TestServerMigrate(TestServer):
host='fakehost')
self.assertNotCalled(self.servers_mock.migrate)
self.assertIsNone(result)
+ # A warning should have been logged for using --live.
+ mock_warning.assert_called_once()
+ self.assertIn('The --live option has been deprecated.',
+ six.text_type(mock_warning.call_args[0][0]))
+
+ def test_server_live_migrate_host_pre_2_30(self):
+ # Tests that the --host option is not supported for --live-migration
+ # before microversion 2.30 (the test defaults to 2.1).
+ arglist = [
+ '--live-migration', '--host', 'fakehost', self.server.id,
+ ]
+ verifylist = [
+ ('live', None),
+ ('live_migration', True),
+ ('host', 'fakehost'),
+ ('block_migration', False),
+ ('disk_overcommit', False),
+ ('wait', False),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ ex = self.assertRaises(exceptions.CommandError, self.cmd.take_action,
+ parsed_args)
+
+ # Make sure it's the error we expect.
+ self.assertIn('--os-compute-api-version 2.30 or greater is required '
+ 'when using --host', six.text_type(ex))
+
+ self.servers_mock.get.assert_called_with(self.server.id)
+ self.assertNotCalled(self.servers_mock.live_migrate)
+ self.assertNotCalled(self.servers_mock.migrate)
+
+ def test_server_live_migrate_no_host(self):
+ # Tests the --live-migration option without --host or --live.
+ arglist = [
+ '--live-migration', self.server.id,
+ ]
+ verifylist = [
+ ('live', None),
+ ('live_migration', True),
+ ('host', None),
+ ('block_migration', False),
+ ('disk_overcommit', False),
+ ('wait', False),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ with mock.patch.object(self.cmd.log, 'warning') as mock_warning:
+ result = self.cmd.take_action(parsed_args)
+
+ self.servers_mock.get.assert_called_with(self.server.id)
+ self.server.live_migrate.assert_called_with(block_migration=False,
+ disk_over_commit=False,
+ host=None)
+ self.assertNotCalled(self.servers_mock.migrate)
+ self.assertIsNone(result)
+ # Since --live wasn't used a warning shouldn't have been logged.
+ mock_warning.assert_not_called()
+
+ def test_server_live_migrate_with_host(self):
+ # Tests the --live-migration option with --host but no --live.
+ # This requires --os-compute-api-version >= 2.30 so the test uses 2.30.
+ arglist = [
+ '--live-migration', '--host', 'fakehost', self.server.id,
+ ]
+ verifylist = [
+ ('live', None),
+ ('live_migration', True),
+ ('host', 'fakehost'),
+ ('block_migration', False),
+ ('disk_overcommit', False),
+ ('wait', False),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ self.app.client_manager.compute.api_version = \
+ api_versions.APIVersion('2.30')
+
+ result = self.cmd.take_action(parsed_args)
+
+ self.servers_mock.get.assert_called_with(self.server.id)
+ # No disk_overcommit with microversion >= 2.25.
+ self.server.live_migrate.assert_called_with(block_migration=False,
+ host='fakehost')
+ self.assertNotCalled(self.servers_mock.migrate)
+ self.assertIsNone(result)
+
+ def test_server_live_migrate_without_host_override_live(self):
+ # Tests the --live-migration option without --host and with --live.
+ # The --live-migration option will take precedence and a warning is
+ # logged for using --live.
+ arglist = [
+ '--live', 'fakehost', '--live-migration', self.server.id,
+ ]
+ verifylist = [
+ ('live', 'fakehost'),
+ ('live_migration', True),
+ ('host', None),
+ ('block_migration', False),
+ ('disk_overcommit', False),
+ ('wait', False),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ with mock.patch.object(self.cmd.log, 'warning') as mock_warning:
+ result = self.cmd.take_action(parsed_args)
+
+ self.servers_mock.get.assert_called_with(self.server.id)
+ self.server.live_migrate.assert_called_with(block_migration=False,
+ disk_over_commit=False,
+ host=None)
+ self.assertNotCalled(self.servers_mock.migrate)
+ self.assertIsNone(result)
+ # A warning should have been logged for using --live.
+ mock_warning.assert_called_once()
+ self.assertIn('The --live option has been deprecated.',
+ six.text_type(mock_warning.call_args[0][0]))
+
+ def test_server_live_migrate_live_and_host_mutex(self):
+ # Tests specifying both the --live and --host options which are in a
+ # mutex group so argparse should fail.
+ arglist = [
+ '--live', 'fakehost', '--host', 'fakehost', self.server.id,
+ ]
+ self.assertRaises(utils.ParserException,
+ self.check_parser, self.cmd, arglist, verify_args=[])
def test_server_block_live_migrate(self):
arglist = [
@@ -2663,6 +2969,55 @@ class TestServerRebuild(TestServer):
self.images_mock.get.assert_called_with(self.image.id)
self.server.rebuild.assert_called_with(self.image, password)
+ def test_rebuild_with_description_api_older(self):
+
+ # Description is not supported for nova api version below 2.19
+ self.server.api_version = 2.18
+
+ description = 'description1'
+ arglist = [
+ self.server.id,
+ '--description', description
+ ]
+ verifylist = [
+ ('server', self.server.id),
+ ('description', description)
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ with mock.patch.object(api_versions,
+ 'APIVersion',
+ return_value=2.19):
+ self.assertRaises(exceptions.CommandError, self.cmd.take_action,
+ parsed_args)
+
+ def test_rebuild_with_description_api_newer(self):
+
+ # Description is supported for nova api version 2.19 or above
+ self.server.api_version = 2.19
+
+ description = 'description1'
+ arglist = [
+ self.server.id,
+ '--description', description
+ ]
+ verifylist = [
+ ('server', self.server.id),
+ ('description', description)
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ with mock.patch.object(api_versions,
+ 'APIVersion',
+ return_value=2.19):
+ # Get the command object to test
+ self.cmd.take_action(parsed_args)
+
+ self.servers_mock.get.assert_called_with(self.server.id)
+ self.images_mock.get.assert_called_with(self.image.id)
+ self.server.rebuild.assert_called_with(self.image, None,
+ description=description)
+
@mock.patch.object(common_utils, 'wait_for_status', return_value=True)
def test_rebuild_with_wait_ok(self, mock_wait_for_status):
arglist = [
@@ -3400,6 +3755,10 @@ class TestServerSet(TestServer):
def setUp(self):
super(TestServerSet, self).setUp()
+ self.attrs = {
+ 'api_version': None,
+ }
+
self.methods = {
'update': None,
'reset_state': None,
@@ -3502,6 +3861,48 @@ class TestServerSet(TestServer):
mock.sentinel.fake_pass)
self.assertIsNone(result)
+ def test_server_set_with_description_api_newer(self):
+
+ # Description is supported for nova api version 2.19 or above
+ self.fake_servers[0].api_version = 2.19
+
+ arglist = [
+ '--description', 'foo_description',
+ 'foo_vm',
+ ]
+ verifylist = [
+ ('description', 'foo_description'),
+ ('server', 'foo_vm'),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ with mock.patch.object(api_versions,
+ 'APIVersion',
+ return_value=2.19):
+ result = self.cmd.take_action(parsed_args)
+ self.fake_servers[0].update.assert_called_once_with(
+ description='foo_description')
+ self.assertIsNone(result)
+
+ def test_server_set_with_description_api_older(self):
+
+ # Description is not supported for nova api version below 2.19
+ self.fake_servers[0].api_version = 2.18
+
+ arglist = [
+ '--description', 'foo_description',
+ 'foo_vm',
+ ]
+ verifylist = [
+ ('description', 'foo_description'),
+ ('server', 'foo_vm'),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+ with mock.patch.object(api_versions,
+ 'APIVersion',
+ return_value=2.19):
+ self.assertRaises(exceptions.CommandError, self.cmd.take_action,
+ parsed_args)
+
class TestServerShelve(TestServer):
@@ -3783,6 +4184,50 @@ class TestServerUnset(TestServer):
self.fake_server, ['key1', 'key2'])
self.assertIsNone(result)
+ def test_server_unset_with_description_api_newer(self):
+
+ # Description is supported for nova api version 2.19 or above
+ self.app.client_manager.compute.api_version = 2.19
+
+ arglist = [
+ '--description',
+ 'foo_vm',
+ ]
+ verifylist = [
+ ('description', True),
+ ('server', 'foo_vm'),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ with mock.patch.object(api_versions,
+ 'APIVersion',
+ return_value=2.19):
+ result = self.cmd.take_action(parsed_args)
+ self.servers_mock.update.assert_called_once_with(
+ self.fake_server, description="")
+ self.assertIsNone(result)
+
+ def test_server_unset_with_description_api_older(self):
+
+ # Description is not supported for nova api version below 2.19
+ self.app.client_manager.compute.api_version = 2.18
+
+ arglist = [
+ '--description',
+ 'foo_vm',
+ ]
+ verifylist = [
+ ('description', True),
+ ('server', 'foo_vm'),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ with mock.patch.object(api_versions,
+ 'APIVersion',
+ return_value=2.19):
+ self.assertRaises(exceptions.CommandError, self.cmd.take_action,
+ parsed_args)
+
class TestServerUnshelve(TestServer):
diff --git a/openstackclient/tests/unit/identity/v3/fakes.py b/openstackclient/tests/unit/identity/v3/fakes.py
index 27ee9fd0..e5727a6a 100644
--- a/openstackclient/tests/unit/identity/v3/fakes.py
+++ b/openstackclient/tests/unit/identity/v3/fakes.py
@@ -235,6 +235,10 @@ endpoint_group_filters = {
'service_id': service_id,
'region_id': endpoint_region,
}
+endpoint_group_filters_2 = {
+ 'region_id': endpoint_region,
+}
+endpoint_group_file_path = '/tmp/path/to/file'
ENDPOINT_GROUP = {
'id': endpoint_group_id,
@@ -1044,6 +1048,64 @@ class FakeEndpoint(object):
return endpoint_filter
+class FakeEndpointGroup(object):
+ """Fake one or more endpoint group."""
+
+ @staticmethod
+ def create_one_endpointgroup(attrs=None):
+ """Create a fake endpoint group.
+
+ :param Dictionary attrs:
+ A dictionary with all attributes
+ :return:
+ A FakeResource object, with id, url, and so on
+ """
+
+ attrs = attrs or {}
+
+ # set default attributes.
+ endpointgroup_info = {
+ 'id': 'endpoint-group-id-' + uuid.uuid4().hex,
+ 'name': 'endpoint-group-name-' + uuid.uuid4().hex,
+ 'filters': {
+ 'region': 'region-' + uuid.uuid4().hex,
+ 'service_id': 'service-id-' + uuid.uuid4().hex,
+ },
+ 'description': 'endpoint-group-description-' + uuid.uuid4().hex,
+ 'links': 'links-' + uuid.uuid4().hex,
+ }
+ endpointgroup_info.update(attrs)
+
+ endpoint = fakes.FakeResource(info=copy.deepcopy(endpointgroup_info),
+ loaded=True)
+ return endpoint
+
+ @staticmethod
+ def create_one_endpointgroup_filter(attrs=None):
+ """Create a fake endpoint project relationship.
+
+ :param Dictionary attrs:
+ A dictionary with all attributes of endpointgroup filter
+ :return:
+ A FakeResource object with project, endpointgroup and so on
+ """
+ attrs = attrs or {}
+
+ # Set default attribute
+ endpointgroup_filter_info = {
+ 'project': 'project-id-' + uuid.uuid4().hex,
+ 'endpointgroup': 'endpointgroup-id-' + uuid.uuid4().hex,
+ }
+
+ # Overwrite default attributes if there are some attributes set
+ endpointgroup_filter_info.update(attrs)
+
+ endpointgroup_filter = fakes.FakeModel(
+ copy.deepcopy(endpointgroup_filter_info))
+
+ return endpointgroup_filter
+
+
class FakeService(object):
"""Fake one or more service."""
diff --git a/openstackclient/tests/unit/identity/v3/test_endpoint_group.py b/openstackclient/tests/unit/identity/v3/test_endpoint_group.py
new file mode 100644
index 00000000..6e9da9c7
--- /dev/null
+++ b/openstackclient/tests/unit/identity/v3/test_endpoint_group.py
@@ -0,0 +1,495 @@
+# 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.identity.v3 import endpoint_group
+from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
+
+
+class TestEndpointGroup(identity_fakes.TestIdentityv3):
+
+ def setUp(self):
+ super(TestEndpointGroup, self).setUp()
+
+ # Get a shortcut to the EndpointManager Mock
+ self.endpoint_groups_mock = (
+ self.app.client_manager.identity.endpoint_groups
+ )
+ self.endpoint_groups_mock.reset_mock()
+ self.epf_mock = (
+ self.app.client_manager.identity.endpoint_filter
+ )
+ self.epf_mock.reset_mock()
+
+ # Get a shortcut to the ServiceManager Mock
+ self.services_mock = self.app.client_manager.identity.services
+ self.services_mock.reset_mock()
+
+ # Get a shortcut to the DomainManager Mock
+ self.domains_mock = self.app.client_manager.identity.domains
+ self.domains_mock.reset_mock()
+
+ # Get a shortcut to the ProjectManager Mock
+ self.projects_mock = self.app.client_manager.identity.projects
+ self.projects_mock.reset_mock()
+
+
+class TestEndpointGroupCreate(TestEndpointGroup):
+
+ columns = (
+ 'description',
+ 'filters',
+ 'id',
+ 'name',
+ )
+
+ def setUp(self):
+ super(TestEndpointGroupCreate, self).setUp()
+
+ self.endpoint_group = (
+ identity_fakes.FakeEndpointGroup.create_one_endpointgroup(
+ attrs={'filters': identity_fakes.endpoint_group_filters}))
+
+ self.endpoint_groups_mock.create.return_value = self.endpoint_group
+
+ # Get the command object to test
+ self.cmd = endpoint_group.CreateEndpointGroup(self.app, None)
+
+ def test_endpointgroup_create_no_options(self):
+ arglist = [
+ '--description', self.endpoint_group.description,
+ self.endpoint_group.name,
+ identity_fakes.endpoint_group_file_path,
+ ]
+ verifylist = [
+ ('name', self.endpoint_group.name),
+ ('filters', identity_fakes.endpoint_group_file_path),
+ ('description', self.endpoint_group.description),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ mocker = mock.Mock()
+ mocker.return_value = identity_fakes.endpoint_group_filters
+ with mock.patch("openstackclient.identity.v3.endpoint_group."
+ "CreateEndpointGroup._read_filters", mocker):
+ columns, data = self.cmd.take_action(parsed_args)
+
+ # Set expected values
+ kwargs = {
+ 'name': self.endpoint_group.name,
+ 'filters': identity_fakes.endpoint_group_filters,
+ 'description': self.endpoint_group.description,
+ }
+
+ self.endpoint_groups_mock.create.assert_called_with(
+ **kwargs
+ )
+
+ self.assertEqual(self.columns, columns)
+ datalist = (
+ self.endpoint_group.description,
+ identity_fakes.endpoint_group_filters,
+ self.endpoint_group.id,
+ self.endpoint_group.name,
+ )
+ self.assertEqual(datalist, data)
+
+
+class TestEndpointGroupDelete(TestEndpointGroup):
+
+ endpoint_group = (
+ identity_fakes.FakeEndpointGroup.create_one_endpointgroup())
+
+ def setUp(self):
+ super(TestEndpointGroupDelete, self).setUp()
+
+ # This is the return value for utils.find_resource(endpoint)
+ self.endpoint_groups_mock.get.return_value = self.endpoint_group
+ self.endpoint_groups_mock.delete.return_value = None
+
+ # Get the command object to test
+ self.cmd = endpoint_group.DeleteEndpointGroup(self.app, None)
+
+ def test_endpointgroup_delete(self):
+ arglist = [
+ self.endpoint_group.id,
+ ]
+ verifylist = [
+ ('endpointgroup', [self.endpoint_group.id]),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ self.endpoint_groups_mock.delete.assert_called_with(
+ self.endpoint_group.id,
+ )
+ self.assertIsNone(result)
+
+
+class TestEndpointGroupList(TestEndpointGroup):
+
+ endpoint_group = (
+ identity_fakes.FakeEndpointGroup.create_one_endpointgroup())
+ project = identity_fakes.FakeProject.create_one_project()
+ domain = identity_fakes.FakeDomain.create_one_domain()
+
+ columns = (
+ 'ID',
+ 'Name',
+ 'Description',
+ )
+
+ def setUp(self):
+ super(TestEndpointGroupList, self).setUp()
+
+ self.endpoint_groups_mock.list.return_value = [self.endpoint_group]
+ self.endpoint_groups_mock.get.return_value = self.endpoint_group
+ self.epf_mock.list_projects_for_endpoint_group.return_value = [
+ self.project]
+ self.epf_mock.list_endpoint_groups_for_project.return_value = [
+ self.endpoint_group]
+
+ # Get the command object to test
+ self.cmd = endpoint_group.ListEndpointGroup(self.app, None)
+
+ def test_endpoint_group_list_no_options(self):
+ arglist = []
+ verifylist = []
+ 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)
+ self.endpoint_groups_mock.list.assert_called_with()
+
+ self.assertEqual(self.columns, columns)
+ datalist = (
+ (
+ self.endpoint_group.id,
+ self.endpoint_group.name,
+ self.endpoint_group.description,
+ ),
+ )
+ self.assertEqual(datalist, tuple(data))
+
+ def test_endpoint_group_list_projects_by_endpoint_group(self):
+ arglist = [
+ '--endpointgroup', self.endpoint_group.id,
+ ]
+ verifylist = [
+ ('endpointgroup', self.endpoint_group.id),
+ ]
+ 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)
+ self.epf_mock.list_projects_for_endpoint_group.assert_called_with(
+ endpoint_group=self.endpoint_group.id
+ )
+
+ self.assertEqual(self.columns, columns)
+ datalist = (
+ (
+ self.project.id,
+ self.project.name,
+ self.project.description,
+ ),
+ )
+ self.assertEqual(datalist, tuple(data))
+
+ def test_endpoint_group_list_by_project(self):
+ self.epf_mock.list_endpoints_for_project.return_value = [
+ self.endpoint_group
+ ]
+ self.projects_mock.get.return_value = self.project
+
+ arglist = [
+ '--project', self.project.name,
+ '--domain', self.domain.name
+ ]
+ verifylist = [
+ ('project', self.project.name),
+ ('domain', self.domain.name),
+ ]
+ 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)
+ self.epf_mock.list_endpoint_groups_for_project.assert_called_with(
+ project=self.project.id
+ )
+
+ self.assertEqual(self.columns, columns)
+ datalist = (
+ (
+ self.endpoint_group.id,
+ self.endpoint_group.name,
+ self.endpoint_group.description,
+ ),
+ )
+ self.assertEqual(datalist, tuple(data))
+
+
+class TestEndpointGroupSet(TestEndpointGroup):
+
+ endpoint_group = (
+ identity_fakes.FakeEndpointGroup.create_one_endpointgroup())
+
+ def setUp(self):
+ super(TestEndpointGroupSet, self).setUp()
+
+ # This is the return value for utils.find_resource(endpoint)
+ self.endpoint_groups_mock.get.return_value = self.endpoint_group
+
+ self.endpoint_groups_mock.update.return_value = self.endpoint_group
+
+ # Get the command object to test
+ self.cmd = endpoint_group.SetEndpointGroup(self.app, None)
+
+ def test_endpoint_group_set_no_options(self):
+ arglist = [
+ self.endpoint_group.id,
+ ]
+ verifylist = [
+ ('endpointgroup', self.endpoint_group.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ kwargs = {
+ 'name': None,
+ 'filters': None,
+ 'description': ''
+ }
+ self.endpoint_groups_mock.update.assert_called_with(
+ self.endpoint_group.id,
+ **kwargs
+ )
+ self.assertIsNone(result)
+
+ def test_endpoint_group_set_name(self):
+ arglist = [
+ '--name', 'qwerty',
+ self.endpoint_group.id
+ ]
+ verifylist = [
+ ('name', 'qwerty'),
+ ('endpointgroup', self.endpoint_group.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ # Set expected values
+ kwargs = {
+ 'name': 'qwerty',
+ 'filters': None,
+ 'description': ''
+ }
+ self.endpoint_groups_mock.update.assert_called_with(
+ self.endpoint_group.id,
+ **kwargs
+ )
+ self.assertIsNone(result)
+
+ def test_endpoint_group_set_filters(self):
+ arglist = [
+ '--filters', identity_fakes.endpoint_group_file_path,
+ self.endpoint_group.id,
+ ]
+ verifylist = [
+ ('filters', identity_fakes.endpoint_group_file_path),
+ ('endpointgroup', self.endpoint_group.id),
+ ]
+
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ mocker = mock.Mock()
+ mocker.return_value = identity_fakes.endpoint_group_filters_2
+ with mock.patch("openstackclient.identity.v3.endpoint_group."
+ "SetEndpointGroup._read_filters", mocker):
+ result = self.cmd.take_action(parsed_args)
+
+ # Set expected values
+ kwargs = {
+ 'name': None,
+ 'filters': identity_fakes.endpoint_group_filters_2,
+ 'description': '',
+ }
+
+ self.endpoint_groups_mock.update.assert_called_with(
+ self.endpoint_group.id,
+ **kwargs
+ )
+
+ self.assertIsNone(result)
+
+ def test_endpoint_group_set_description(self):
+ arglist = [
+ '--description', 'qwerty',
+ self.endpoint_group.id
+ ]
+ verifylist = [
+ ('description', 'qwerty'),
+ ('endpointgroup', self.endpoint_group.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ # Set expected values
+ kwargs = {
+ 'name': None,
+ 'filters': None,
+ 'description': 'qwerty',
+ }
+ self.endpoint_groups_mock.update.assert_called_with(
+ self.endpoint_group.id,
+ **kwargs
+ )
+ self.assertIsNone(result)
+
+
+class TestAddProjectToEndpointGroup(TestEndpointGroup):
+
+ project = identity_fakes.FakeProject.create_one_project()
+ domain = identity_fakes.FakeDomain.create_one_domain()
+ endpoint_group = (
+ identity_fakes.FakeEndpointGroup.create_one_endpointgroup())
+
+ new_ep_filter = (
+ identity_fakes.FakeEndpointGroup.create_one_endpointgroup_filter(
+ attrs={'endpointgroup': endpoint_group.id,
+ 'project': project.id}))
+
+ def setUp(self):
+ super(TestAddProjectToEndpointGroup, self).setUp()
+
+ # This is the return value for utils.find_resource()
+ self.endpoint_groups_mock.get.return_value = self.endpoint_group
+
+ # Update the image_id in the MEMBER dict
+ self.epf_mock.create.return_value = self.new_ep_filter
+ self.projects_mock.get.return_value = self.project
+ self.domains_mock.get.return_value = self.domain
+
+ # Get the command object to test
+ self.cmd = endpoint_group.AddProjectToEndpointGroup(self.app, None)
+
+ def test_add_project_to_endpoint_no_option(self):
+ arglist = [
+ self.endpoint_group.id,
+ self.project.id,
+ ]
+ verifylist = [
+ ('endpointgroup', self.endpoint_group.id),
+ ('project', self.project.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+ self.epf_mock.add_endpoint_group_to_project.assert_called_with(
+ project=self.project.id,
+ endpoint_group=self.endpoint_group.id,
+ )
+ self.assertIsNone(result)
+
+ def test_add_project_to_endpoint_with_option(self):
+ arglist = [
+ self.endpoint_group.id,
+ self.project.id,
+ '--project-domain', self.domain.id,
+ ]
+ verifylist = [
+ ('endpointgroup', self.endpoint_group.id),
+ ('project', self.project.id),
+ ('project_domain', self.domain.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+ self.epf_mock.add_endpoint_group_to_project.assert_called_with(
+ project=self.project.id,
+ endpoint_group=self.endpoint_group.id,
+ )
+ self.assertIsNone(result)
+
+
+class TestRemoveProjectEndpointGroup(TestEndpointGroup):
+
+ project = identity_fakes.FakeProject.create_one_project()
+ domain = identity_fakes.FakeDomain.create_one_domain()
+ endpoint_group = (
+ identity_fakes.FakeEndpointGroup.create_one_endpointgroup())
+
+ def setUp(self):
+ super(TestRemoveProjectEndpointGroup, self).setUp()
+
+ # This is the return value for utils.find_resource()
+ self.endpoint_groups_mock.get.return_value = self.endpoint_group
+
+ self.projects_mock.get.return_value = self.project
+ self.domains_mock.get.return_value = self.domain
+ self.epf_mock.delete.return_value = None
+
+ # Get the command object to test
+ self.cmd = endpoint_group.RemoveProjectFromEndpointGroup(
+ self.app, None)
+
+ def test_remove_project_endpoint_no_options(self):
+ arglist = [
+ self.endpoint_group.id,
+ self.project.id,
+ ]
+ verifylist = [
+ ('endpointgroup', self.endpoint_group.id),
+ ('project', self.project.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ self.epf_mock.delete_endpoint_group_from_project.assert_called_with(
+ project=self.project.id,
+ endpoint_group=self.endpoint_group.id,
+ )
+ self.assertIsNone(result)
+
+ def test_remove_project_endpoint_with_options(self):
+ arglist = [
+ self.endpoint_group.id,
+ self.project.id,
+ '--project-domain', self.domain.id,
+ ]
+ verifylist = [
+ ('endpointgroup', self.endpoint_group.id),
+ ('project', self.project.id),
+ ('project_domain', self.domain.id),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ result = self.cmd.take_action(parsed_args)
+
+ self.epf_mock.delete_endpoint_group_from_project.assert_called_with(
+ project=self.project.id,
+ endpoint_group=self.endpoint_group.id,
+ )
+ self.assertIsNone(result)
diff --git a/openstackclient/tests/unit/image/v1/test_image.py b/openstackclient/tests/unit/image/v1/test_image.py
index ae578d91..6babd4ff 100644
--- a/openstackclient/tests/unit/image/v1/test_image.py
+++ b/openstackclient/tests/unit/image/v1/test_image.py
@@ -417,7 +417,7 @@ class TestImageList(TestImage):
), )
self.assertEqual(datalist, tuple(data))
- @mock.patch('openstackclient.api.utils.simple_filter')
+ @mock.patch('osc_lib.api.utils.simple_filter')
def test_image_list_property_option(self, sf_mock):
sf_mock.side_effect = [
[self.image_info], [],
diff --git a/openstackclient/tests/unit/image/v2/test_image.py b/openstackclient/tests/unit/image/v2/test_image.py
index 16a393df..4cc8f448 100644
--- a/openstackclient/tests/unit/image/v2/test_image.py
+++ b/openstackclient/tests/unit/image/v2/test_image.py
@@ -734,7 +734,7 @@ class TestImageList(TestImage):
), )
self.assertEqual(datalist, tuple(data))
- @mock.patch('openstackclient.api.utils.simple_filter')
+ @mock.patch('osc_lib.api.utils.simple_filter')
def test_image_list_property_option(self, sf_mock):
sf_mock.return_value = [copy.deepcopy(self._image)]