Merge "identity: Migrate 'service' commands to SDK"

This commit is contained in:
Zuul 2024-07-12 14:07:22 +00:00 committed by Gerrit Code Review
commit 2733b3413d
8 changed files with 179 additions and 101 deletions

View File

@ -20,6 +20,7 @@ from keystoneclient.v3 import domains
from keystoneclient.v3 import groups from keystoneclient.v3 import groups
from keystoneclient.v3 import projects from keystoneclient.v3 import projects
from keystoneclient.v3 import users from keystoneclient.v3 import users
from openstack import exceptions as sdk_exceptions
from osc_lib import exceptions from osc_lib import exceptions
from osc_lib import utils from osc_lib import utils
@ -73,6 +74,39 @@ def find_service(identity_client, name_type_or_id):
raise exceptions.CommandError(msg % name_type_or_id) raise exceptions.CommandError(msg % name_type_or_id)
def find_service_sdk(identity_client, name_type_or_id):
"""Find a service by id, name or type."""
try:
# search for service name or ID
return identity_client.find_service(
name_type_or_id, ignore_missing=False
)
except sdk_exceptions.ResourceNotFound:
pass
except sdk_exceptions.DuplicateResource as e:
raise exceptions.CommandError(e.message)
# search for service type
services = identity_client.services()
result = None
for service in services:
if name_type_or_id == service.type:
if result:
msg = _(
"Multiple service matches found for '%s', "
"use an ID or name to be more specific."
)
raise exceptions.CommandError(msg % name_type_or_id)
result = service
if result is None:
msg = _("No service with a type, name or ID of '%s' exists.")
raise exceptions.CommandError(msg % name_type_or_id)
return result
def get_resource(manager, name_type_or_id): def get_resource(manager, name_type_or_id):
# NOTE (vishakha): Due to bug #1799153 and for any another related case # NOTE (vishakha): Due to bug #1799153 and for any another related case
# where GET resource API does not support the filter by name, # where GET resource API does not support the filter by name,

View File

@ -28,6 +28,31 @@ from openstackclient.identity import common
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
def _format_service(service):
columns = (
'id',
'name',
'type',
'is_enabled',
'description',
)
column_headers = (
'ID',
'Name',
'Type',
'Enabled',
'Description',
)
return (
column_headers,
utils.get_item_properties(
service,
columns,
),
)
class CreateService(command.ShowOne): class CreateService(command.ShowOne):
_description = _("Create new service") _description = _("Create new service")
@ -66,17 +91,16 @@ class CreateService(command.ShowOne):
return parser return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):
identity_client = self.app.client_manager.identity identity_client = self.app.client_manager.sdk_connection.identity
service = identity_client.services.create( service = identity_client.create_service(
name=parsed_args.name, name=parsed_args.name,
type=parsed_args.type, type=parsed_args.type,
description=parsed_args.description, description=parsed_args.description,
enabled=parsed_args.is_enabled, is_enabled=parsed_args.is_enabled,
) )
service._info.pop('links') return _format_service(service)
return zip(*sorted(service._info.items()))
class DeleteService(command.Command): class DeleteService(command.Command):
@ -93,12 +117,12 @@ class DeleteService(command.Command):
return parser return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):
identity_client = self.app.client_manager.identity identity_client = self.app.client_manager.sdk_connection.identity
result = 0 result = 0
for i in parsed_args.service: for i in parsed_args.service:
try: try:
service = common.find_service(identity_client, i) service = common.find_service_sdk(identity_client, i)
identity_client.services.delete(service.id) identity_client.delete_service(service.id)
except Exception as e: except Exception as e:
result += 1 result += 1
LOG.error( LOG.error(
@ -131,13 +155,19 @@ class ListService(command.Lister):
return parser return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):
identity_client = self.app.client_manager.sdk_connection.identity
if parsed_args.long: if parsed_args.long:
columns = ('ID', 'Name', 'Type', 'Description', 'Enabled') columns = ('id', 'name', 'type', 'description', 'is_enabled')
column_headers = ('ID', 'Name', 'Type', 'Description', 'Enabled')
else: else:
columns = ('ID', 'Name', 'Type') columns = ('id', 'name', 'type')
data = self.app.client_manager.identity.services.list() column_headers = ('ID', 'Name', 'Type')
data = identity_client.services()
return ( return (
columns, column_headers,
(utils.get_item_properties(s, columns) for s in data), (utils.get_item_properties(s, columns) for s in data),
) )
@ -185,9 +215,9 @@ class SetService(command.Command):
return parser return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):
identity_client = self.app.client_manager.identity identity_client = self.app.client_manager.sdk_connection.identity
service = common.find_service(identity_client, parsed_args.service) service = common.find_service_sdk(identity_client, parsed_args.service)
kwargs = {} kwargs = {}
if parsed_args.type: if parsed_args.type:
kwargs['type'] = parsed_args.type kwargs['type'] = parsed_args.type
@ -195,10 +225,9 @@ class SetService(command.Command):
kwargs['name'] = parsed_args.name kwargs['name'] = parsed_args.name
if parsed_args.description: if parsed_args.description:
kwargs['description'] = parsed_args.description kwargs['description'] = parsed_args.description
if parsed_args.is_enabled is not None: kwargs['is_enabled'] = parsed_args.is_enabled
kwargs['enabled'] = parsed_args.is_enabled
identity_client.services.update(service.id, **kwargs) identity_client.update_service(service.id, **kwargs)
class ShowService(command.ShowOne): class ShowService(command.ShowOne):
@ -214,9 +243,8 @@ class ShowService(command.ShowOne):
return parser return parser
def take_action(self, parsed_args): def take_action(self, parsed_args):
identity_client = self.app.client_manager.identity identity_client = self.app.client_manager.sdk_connection.identity
service = common.find_service(identity_client, parsed_args.service) service = common.find_service_sdk(identity_client, parsed_args.service)
service._info.pop('links') return _format_service(service)
return zip(*sorted(service._info.items()))

View File

@ -48,7 +48,7 @@ class IdentityTests(base.TestCase):
'parent_id', 'parent_id',
] ]
ROLE_FIELDS = ['id', 'name', 'domain_id', 'description'] ROLE_FIELDS = ['id', 'name', 'domain_id', 'description']
SERVICE_FIELDS = ['id', 'enabled', 'name', 'type', 'description'] SERVICE_FIELDS = ['ID', 'Enabled', 'Name', 'Type', 'Description']
REGION_FIELDS = ['description', 'enabled', 'parent_region', 'region'] REGION_FIELDS = ['description', 'enabled', 'parent_region', 'region']
ENDPOINT_FIELDS = [ ENDPOINT_FIELDS = [
'id', 'id',
@ -376,7 +376,7 @@ class IdentityTests(base.TestCase):
if add_clean_up: if add_clean_up:
service = self.parse_show_as_object(raw_output) service = self.parse_show_as_object(raw_output)
self.addCleanup( self.addCleanup(
self.openstack, 'service delete %s' % service['id'] self.openstack, 'service delete %s' % service['ID']
) )
items = self.parse_show(raw_output) items = self.parse_show(raw_output)
self.assert_show_fields(items, self.SERVICE_FIELDS) self.assert_show_fields(items, self.SERVICE_FIELDS)

View File

@ -32,7 +32,7 @@ class LimitTestCase(common.IdentityTests):
raw_output = self.openstack('service show %s' % service_id) raw_output = self.openstack('service show %s' % service_id)
items = self.parse_show(raw_output) items = self.parse_show(raw_output)
service_name = self._extract_value_from_items('name', items) service_name = self._extract_value_from_items('Name', items)
project_name = self._create_dummy_project() project_name = self._create_dummy_project()
raw_output = self.openstack('project show %s' % project_name) raw_output = self.openstack('project show %s' % project_name)
@ -73,7 +73,7 @@ class LimitTestCase(common.IdentityTests):
raw_output = self.openstack('service show %s' % service_id) raw_output = self.openstack('service show %s' % service_id)
items = self.parse_show(raw_output) items = self.parse_show(raw_output)
service_name = self._extract_value_from_items('name', items) service_name = self._extract_value_from_items('Name', items)
project_name = self._create_dummy_project() project_name = self._create_dummy_project()

View File

@ -29,7 +29,7 @@ class RegisteredLimitTestCase(common.IdentityTests):
'service show' ' %(service_name)s' % {'service_name': service_name} 'service show' ' %(service_name)s' % {'service_name': service_name}
) )
service_items = self.parse_show(raw_output) service_items = self.parse_show(raw_output)
service_id = self._extract_value_from_items('id', service_items) service_id = self._extract_value_from_items('ID', service_items)
raw_output = self.openstack( raw_output = self.openstack(
'registered limit create' 'registered limit create'

View File

@ -61,9 +61,9 @@ class ServiceTests(common.IdentityTests):
raw_output = self.openstack('service show %s' % new_service_name) raw_output = self.openstack('service show %s' % new_service_name)
# assert service details # assert service details
service = self.parse_show_as_object(raw_output) service = self.parse_show_as_object(raw_output)
self.assertEqual(new_service_type, service['type']) self.assertEqual(new_service_type, service['Type'])
self.assertEqual(new_service_name, service['name']) self.assertEqual(new_service_name, service['Name'])
self.assertEqual(new_service_description, service['description']) self.assertEqual(new_service_description, service['Description'])
def test_service_show(self): def test_service_show(self):
service_name = self._create_dummy_service() service_name = self._create_dummy_service()

View File

@ -13,43 +13,37 @@
# under the License. # under the License.
# #
from keystoneclient import exceptions as identity_exc from openstack import exceptions as sdk_exceptions
from openstack.identity.v3 import service as _service
from openstack.test import fakes as sdk_fakes
from osc_lib import exceptions from osc_lib import exceptions
from openstackclient.identity.v3 import service from openstackclient.identity.v3 import service
from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes
class TestService(identity_fakes.TestIdentityv3): class TestServiceCreate(identity_fakes.TestIdentityv3):
def setUp(self):
super().setUp()
# Get a shortcut to the ServiceManager Mock
self.services_mock = self.identity_client.services
self.services_mock.reset_mock()
class TestServiceCreate(TestService):
columns = ( columns = (
'description', 'ID',
'enabled', 'Name',
'id', 'Type',
'name', 'Enabled',
'type', 'Description',
) )
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.service = identity_fakes.FakeService.create_one_service() self.service = sdk_fakes.generate_fake_resource(_service.Service)
self.datalist = ( self.datalist = (
self.service.description,
True,
self.service.id, self.service.id,
self.service.name, self.service.name,
self.service.type, self.service.type,
True,
self.service.description,
) )
self.services_mock.create.return_value = self.service self.identity_sdk_client.create_service.return_value = self.service
# Get the command object to test # Get the command object to test
self.cmd = service.CreateService(self.app, None) self.cmd = service.CreateService(self.app, None)
@ -73,12 +67,11 @@ class TestServiceCreate(TestService):
# data to be shown. # data to be shown.
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
# ServiceManager.create(name=, type=, enabled=, **kwargs) self.identity_sdk_client.create_service.assert_called_with(
self.services_mock.create.assert_called_with(
name=self.service.name, name=self.service.name,
type=self.service.type, type=self.service.type,
description=None, description=None,
enabled=True, is_enabled=True,
) )
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
@ -103,12 +96,11 @@ class TestServiceCreate(TestService):
# data to be shown. # data to be shown.
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
# ServiceManager.create(name=, type=, enabled=, **kwargs) self.identity_sdk_client.create_service.assert_called_with(
self.services_mock.create.assert_called_with(
name=None, name=None,
type=self.service.type, type=self.service.type,
description=self.service.description, description=self.service.description,
enabled=True, is_enabled=True,
) )
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
@ -132,12 +124,11 @@ class TestServiceCreate(TestService):
# data to be shown. # data to be shown.
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
# ServiceManager.create(name=, type=, enabled=, **kwargs) self.identity_sdk_client.create_service.assert_called_with(
self.services_mock.create.assert_called_with(
name=None, name=None,
type=self.service.type, type=self.service.type,
description=None, description=None,
enabled=True, is_enabled=True,
) )
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
@ -161,27 +152,28 @@ class TestServiceCreate(TestService):
# data to be shown. # data to be shown.
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
# ServiceManager.create(name=, type=, enabled=, **kwargs) self.identity_sdk_client.create_service.assert_called_with(
self.services_mock.create.assert_called_with(
name=None, name=None,
type=self.service.type, type=self.service.type,
description=None, description=None,
enabled=False, is_enabled=False,
) )
self.assertEqual(self.columns, columns) self.assertEqual(self.columns, columns)
self.assertEqual(self.datalist, data) self.assertEqual(self.datalist, data)
class TestServiceDelete(TestService): class TestServiceDelete(identity_fakes.TestIdentityv3):
service = identity_fakes.FakeService.create_one_service() service = sdk_fakes.generate_fake_resource(_service.Service)
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.services_mock.get.side_effect = identity_exc.NotFound(None) self.identity_sdk_client.get_service.side_effect = (
self.services_mock.find.return_value = self.service sdk_exceptions.ResourceNotFound
self.services_mock.delete.return_value = None )
self.identity_sdk_client.find_service.return_value = self.service
self.identity_sdk_client.delete_service.return_value = None
# Get the command object to test # Get the command object to test
self.cmd = service.DeleteService(self.app, None) self.cmd = service.DeleteService(self.app, None)
@ -197,19 +189,19 @@ class TestServiceDelete(TestService):
result = self.cmd.take_action(parsed_args) result = self.cmd.take_action(parsed_args)
self.services_mock.delete.assert_called_with( self.identity_sdk_client.delete_service.assert_called_with(
self.service.id, self.service.id,
) )
self.assertIsNone(result) self.assertIsNone(result)
class TestServiceList(TestService): class TestServiceList(identity_fakes.TestIdentityv3):
service = identity_fakes.FakeService.create_one_service() service = sdk_fakes.generate_fake_resource(_service.Service)
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.services_mock.list.return_value = [self.service] self.identity_sdk_client.services.return_value = [self.service]
# Get the command object to test # Get the command object to test
self.cmd = service.ListService(self.app, None) self.cmd = service.ListService(self.app, None)
@ -224,7 +216,7 @@ class TestServiceList(TestService):
# containing the data to be listed. # containing the data to be listed.
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.services_mock.list.assert_called_with() self.identity_sdk_client.services.assert_called_with()
collist = ('ID', 'Name', 'Type') collist = ('ID', 'Name', 'Type')
self.assertEqual(collist, columns) self.assertEqual(collist, columns)
@ -251,7 +243,7 @@ class TestServiceList(TestService):
# containing the data to be listed. # containing the data to be listed.
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
self.services_mock.list.assert_called_with() self.identity_sdk_client.services.assert_called_with()
collist = ('ID', 'Name', 'Type', 'Description', 'Enabled') collist = ('ID', 'Name', 'Type', 'Description', 'Enabled')
self.assertEqual(collist, columns) self.assertEqual(collist, columns)
@ -267,15 +259,17 @@ class TestServiceList(TestService):
self.assertEqual(datalist, tuple(data)) self.assertEqual(datalist, tuple(data))
class TestServiceSet(TestService): class TestServiceSet(identity_fakes.TestIdentityv3):
service = identity_fakes.FakeService.create_one_service() service = sdk_fakes.generate_fake_resource(_service.Service)
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.services_mock.get.side_effect = identity_exc.NotFound(None) self.identity_sdk_client.get_service.side_effect = (
self.services_mock.find.return_value = self.service sdk_exceptions.ResourceNotFound
self.services_mock.update.return_value = self.service )
self.identity_sdk_client.find_service.return_value = self.service
self.identity_sdk_client.update_service.return_value = self.service
# Get the command object to test # Get the command object to test
self.cmd = service.SetService(self.app, None) self.cmd = service.SetService(self.app, None)
@ -317,9 +311,11 @@ class TestServiceSet(TestService):
# Set expected values # Set expected values
kwargs = { kwargs = {
'type': self.service.type, 'type': self.service.type,
'is_enabled': None,
} }
# ServiceManager.update(service, name=, type=, enabled=, **kwargs) self.identity_sdk_client.update_service.assert_called_with(
self.services_mock.update.assert_called_with(self.service.id, **kwargs) self.service.id, **kwargs
)
self.assertIsNone(result) self.assertIsNone(result)
def test_service_set_name(self): def test_service_set_name(self):
@ -342,9 +338,11 @@ class TestServiceSet(TestService):
# Set expected values # Set expected values
kwargs = { kwargs = {
'name': self.service.name, 'name': self.service.name,
'is_enabled': None,
} }
# ServiceManager.update(service, name=, type=, enabled=, **kwargs) self.identity_sdk_client.update_service.assert_called_with(
self.services_mock.update.assert_called_with(self.service.id, **kwargs) self.service.id, **kwargs
)
self.assertIsNone(result) self.assertIsNone(result)
def test_service_set_description(self): def test_service_set_description(self):
@ -367,9 +365,11 @@ class TestServiceSet(TestService):
# Set expected values # Set expected values
kwargs = { kwargs = {
'description': self.service.description, 'description': self.service.description,
'is_enabled': None,
} }
# ServiceManager.update(service, name=, type=, enabled=, **kwargs) self.identity_sdk_client.update_service.assert_called_with(
self.services_mock.update.assert_called_with(self.service.id, **kwargs) self.service.id, **kwargs
)
self.assertIsNone(result) self.assertIsNone(result)
def test_service_set_enable(self): def test_service_set_enable(self):
@ -390,10 +390,11 @@ class TestServiceSet(TestService):
# Set expected values # Set expected values
kwargs = { kwargs = {
'enabled': True, 'is_enabled': True,
} }
# ServiceManager.update(service, name=, type=, enabled=, **kwargs) self.identity_sdk_client.update_service.assert_called_with(
self.services_mock.update.assert_called_with(self.service.id, **kwargs) self.service.id, **kwargs
)
self.assertIsNone(result) self.assertIsNone(result)
def test_service_set_disable(self): def test_service_set_disable(self):
@ -414,21 +415,24 @@ class TestServiceSet(TestService):
# Set expected values # Set expected values
kwargs = { kwargs = {
'enabled': False, 'is_enabled': False,
} }
# ServiceManager.update(service, name=, type=, enabled=, **kwargs) self.identity_sdk_client.update_service.assert_called_with(
self.services_mock.update.assert_called_with(self.service.id, **kwargs) self.service.id, **kwargs
)
self.assertIsNone(result) self.assertIsNone(result)
class TestServiceShow(TestService): class TestServiceShow(identity_fakes.TestIdentityv3):
service = identity_fakes.FakeService.create_one_service() service = sdk_fakes.generate_fake_resource(_service.Service)
def setUp(self): def setUp(self):
super().setUp() super().setUp()
self.services_mock.get.side_effect = identity_exc.NotFound(None) self.identity_sdk_client.get_service.side_effect = (
self.services_mock.find.return_value = self.service sdk_exceptions.ResourceNotFound
)
self.identity_sdk_client.find_service.return_value = self.service
# Get the command object to test # Get the command object to test
self.cmd = service.ShowService(self.app, None) self.cmd = service.ShowService(self.app, None)
@ -447,22 +451,25 @@ class TestServiceShow(TestService):
# data to be shown. # data to be shown.
columns, data = self.cmd.take_action(parsed_args) columns, data = self.cmd.take_action(parsed_args)
# ServiceManager.get(id) self.identity_sdk_client.find_service.assert_called_with(
self.services_mock.find.assert_called_with(name=self.service.name) self.service.name, ignore_missing=False
)
collist = ('description', 'enabled', 'id', 'name', 'type') collist = ('ID', 'Name', 'Type', 'Enabled', 'Description')
self.assertEqual(collist, columns) self.assertEqual(collist, columns)
datalist = ( datalist = (
self.service.description,
True,
self.service.id, self.service.id,
self.service.name, self.service.name,
self.service.type, self.service.type,
True,
self.service.description,
) )
self.assertEqual(datalist, data) self.assertEqual(datalist, data)
def test_service_show_nounique(self): def test_service_show_nounique(self):
self.services_mock.find.side_effect = identity_exc.NoUniqueMatch(None) self.identity_sdk_client.find_service.side_effect = (
sdk_exceptions.DuplicateResource(None)
)
arglist = [ arglist = [
'nounique_service', 'nounique_service',
] ]
@ -476,7 +483,6 @@ class TestServiceShow(TestService):
self.fail('CommandError should be raised.') self.fail('CommandError should be raised.')
except exceptions.CommandError as e: except exceptions.CommandError as e:
self.assertEqual( self.assertEqual(
"Multiple service matches found for 'nounique_service'," "DuplicateResource",
" use an ID to be more specific.",
str(e), str(e),
) )

View File

@ -0,0 +1,10 @@
---
features:
- |
The following commands have been migrated to SDK:
- ``service create``
- ``service delete``
- ``service set``
- ``service list``
- ``service show``