Don't use name of a service as a key
Name of a service shouldn't be used as a key in structures as the name is a user-facing name and it's not intended to be machine-parseable: https://docs.openstack.org/keystone/stein/contributor/service-catalog.html#services Story: 2006892 Task: 37526 Change-Id: I9621aee957e8a043f6ac251b96abafd80ef167f1
This commit is contained in:
parent
b84544cf0a
commit
6a616e5db2
@ -19,8 +19,8 @@ from config_tempest.services.base import Service
|
||||
class AlarmingService(Service):
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
return ['aodh']
|
||||
def get_service_type():
|
||||
return ['alarming']
|
||||
|
||||
@staticmethod
|
||||
def get_codename():
|
||||
|
@ -22,7 +22,7 @@ class Ec2Service(Service):
|
||||
conf.set('aws', 'ec2_url', self.service_url)
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
def get_service_type():
|
||||
return ['ec2']
|
||||
|
||||
|
||||
@ -32,5 +32,5 @@ class S3Service(Service):
|
||||
conf.set('aws', 's3_url', self.service_url)
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
def get_service_type():
|
||||
return ['s3']
|
||||
|
@ -19,8 +19,8 @@ from config_tempest.services.base import Service
|
||||
class BaremetalService(Service):
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
return ['ironic']
|
||||
def get_service_type():
|
||||
return ['baremetal']
|
||||
|
||||
@staticmethod
|
||||
def get_codename():
|
||||
|
@ -89,11 +89,11 @@ class Service(object):
|
||||
return self.extensions
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
"""Return the service name.
|
||||
def get_service_type():
|
||||
"""Return the service type.
|
||||
|
||||
This returns a list because you can have different services for the
|
||||
same type, like volume, volumev2, volumev3
|
||||
This returns a list because you can have services with more types,
|
||||
like volume, volumev2, volumev3.
|
||||
"""
|
||||
return []
|
||||
|
||||
|
@ -34,8 +34,8 @@ class MeteringService(Service):
|
||||
conf.set('service_available', 'ceilometer', 'True')
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
return ['ceilometer']
|
||||
def get_service_type():
|
||||
return ['metering']
|
||||
|
||||
@staticmethod
|
||||
def get_codename():
|
||||
|
@ -62,8 +62,8 @@ class ComputeService(VersionedService):
|
||||
str(is_service(**{'type': 'key-manager'})))
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
return ['nova']
|
||||
def get_service_type():
|
||||
return ['compute']
|
||||
|
||||
@staticmethod
|
||||
def get_codename():
|
||||
|
@ -19,8 +19,8 @@ from config_tempest.services.base import Service
|
||||
class DataProcessingService(Service):
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
return ['sahara']
|
||||
def get_service_type():
|
||||
return ['data-processing']
|
||||
|
||||
@staticmethod
|
||||
def get_codename():
|
||||
|
@ -19,8 +19,8 @@ from config_tempest.services.base import Service
|
||||
class DatabaseService(Service):
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
return ['trove']
|
||||
def get_service_type():
|
||||
return ['database']
|
||||
|
||||
@staticmethod
|
||||
def get_codename():
|
||||
|
@ -19,8 +19,8 @@ from config_tempest.services.base import Service
|
||||
class DnsService(Service):
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
return ['designate']
|
||||
def get_service_type():
|
||||
return ['dns']
|
||||
|
||||
@staticmethod
|
||||
def get_codename():
|
||||
|
@ -19,8 +19,8 @@ from config_tempest.services.base import Service
|
||||
class EventService(Service):
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
return ['panko']
|
||||
def get_service_type():
|
||||
return ['event']
|
||||
|
||||
@staticmethod
|
||||
def get_codename():
|
||||
|
@ -61,8 +61,8 @@ class IdentityService(VersionedService):
|
||||
return ['v2', 'v3']
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
return ['keystone']
|
||||
def get_service_type():
|
||||
return ['identity']
|
||||
|
||||
def set_identity_v3_extensions(self):
|
||||
"""Returns discovered identity v3 extensions
|
||||
|
@ -74,8 +74,8 @@ class ImageService(VersionedService):
|
||||
return ['v1', 'v2']
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
return ['glance']
|
||||
def get_service_type():
|
||||
return ['image']
|
||||
|
||||
@staticmethod
|
||||
def get_codename():
|
||||
|
@ -19,8 +19,8 @@ from config_tempest.services.base import Service
|
||||
class MessagingService(Service):
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
return ['zaqar']
|
||||
def get_service_type():
|
||||
return ['messaging']
|
||||
|
||||
@staticmethod
|
||||
def get_codename():
|
||||
|
@ -19,8 +19,8 @@ from config_tempest.services.base import Service
|
||||
class MetricService(Service):
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
return ['gnocchi']
|
||||
def get_service_type():
|
||||
return ['metric']
|
||||
|
||||
@staticmethod
|
||||
def get_codename():
|
||||
|
@ -93,8 +93,8 @@ class NetworkService(VersionedService):
|
||||
'discovered and must be specified')
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
return ['neutron']
|
||||
def get_service_type():
|
||||
return ['network']
|
||||
|
||||
@staticmethod
|
||||
def get_codename():
|
||||
|
@ -106,8 +106,8 @@ class ObjectStorageService(Service):
|
||||
self.list_create_roles(conf, self.client.roles)
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
return ['swift']
|
||||
def get_service_type():
|
||||
return ['object-store']
|
||||
|
||||
@staticmethod
|
||||
def get_codename():
|
||||
|
@ -28,8 +28,8 @@ class LoadBalancerService(VersionedService):
|
||||
conf.set('load_balancer', 'RBAC_test_type', 'owner_or_admin')
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
return ['octavia']
|
||||
def get_service_type():
|
||||
return ['load-balancer']
|
||||
|
||||
@staticmethod
|
||||
def get_codename():
|
||||
|
@ -22,8 +22,8 @@ from config_tempest.services.base import Service
|
||||
class OrchestrationService(Service):
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
return ['heat']
|
||||
def get_service_type():
|
||||
return ['orchestration']
|
||||
|
||||
@staticmethod
|
||||
def get_codename():
|
||||
|
@ -64,39 +64,50 @@ class Services(object):
|
||||
def get_available_services(self):
|
||||
try:
|
||||
services = self._clients.service_client.list_services()['services']
|
||||
return {s['name']: s['type'] for s in services}
|
||||
except exceptions.Forbidden:
|
||||
C.LOG.warning("User has no permissions to list services, using "
|
||||
"catalog. Services without endpoint will not be "
|
||||
"discovered.")
|
||||
token, auth_data = self._clients.auth_provider.get_auth()
|
||||
return {s['name']: s['type'] for s
|
||||
in auth_data[self.service_catalog]}
|
||||
services = self.catalog
|
||||
return services
|
||||
|
||||
def get_service_data(self, s_name, s_type):
|
||||
for s in self.catalog:
|
||||
if s['name'] == s_name and s['type'] == s_type:
|
||||
return s
|
||||
return None
|
||||
|
||||
def discover(self):
|
||||
token, auth_data = self._clients.auth_provider.get_auth()
|
||||
|
||||
auth_entries = {e['type']: e for e in auth_data[self.service_catalog]}
|
||||
|
||||
# We loop through the classes we have for each service, and if we find
|
||||
# a class that match a service enabled, we add it in our services list.
|
||||
# some services doesn't have endpoints, so we need to check first
|
||||
for s_class in self.service_classes:
|
||||
s_names = s_class.get_service_name()
|
||||
for s_name in s_names:
|
||||
s_type = self.available_services.get(s_name, None)
|
||||
if s_type:
|
||||
endpoint_data = auth_entries.get(s_type, None)
|
||||
s_types = s_class.get_service_type()
|
||||
for s_type in s_types:
|
||||
s_name = [t['name'] for t in self.available_services
|
||||
if t['type'] == s_type]
|
||||
if s_name:
|
||||
# In the general case, there should only be one service in
|
||||
# a deployment per service type
|
||||
# https://docs.openstack.org/keystone/latest/contributor/
|
||||
# service-catalog.html#services
|
||||
if len(s_name) > 1:
|
||||
C.LOG.warning("There are more service names ('%s') for"
|
||||
" '%s' service type, which is undefined"
|
||||
" behavior. Continuing with '%s'.",
|
||||
str(s_name), s_type, s_name[0])
|
||||
s_name = s_name[0]
|
||||
service_data = self.get_service_data(s_name, s_type)
|
||||
url = None
|
||||
if not endpoint_data:
|
||||
C.LOG.Warning('No endpoint data found for {}'.format(
|
||||
if not service_data:
|
||||
C.LOG.warning('No endpoint data found for {}'.format(
|
||||
s_name))
|
||||
else:
|
||||
url = self.parse_endpoints(self.get_endpoints(
|
||||
endpoint_data), s_type)
|
||||
service_data), s_type)
|
||||
|
||||
# Create the service class and add it to services list
|
||||
service = s_class(s_name, s_type, url, token,
|
||||
service = s_class(s_name, s_type, url, self.token,
|
||||
self._ssl_validation,
|
||||
self._clients.get_service_client(
|
||||
s_type))
|
||||
@ -153,11 +164,13 @@ class Services(object):
|
||||
|
||||
def set_catalog_and_url(self):
|
||||
if self._creds.api_version == 3:
|
||||
self.service_catalog = 'catalog'
|
||||
service_catalog = 'catalog'
|
||||
self.public_url = 'url'
|
||||
else:
|
||||
self.service_catalog = 'serviceCatalog'
|
||||
service_catalog = 'serviceCatalog'
|
||||
self.public_url = 'publicURL'
|
||||
self.token, auth_data = self._clients.auth_provider.get_auth()
|
||||
self.catalog = auth_data[service_catalog]
|
||||
|
||||
def parse_endpoints(self, ep, name):
|
||||
"""Parse an endpoint(s).
|
||||
@ -214,15 +227,16 @@ class Services(object):
|
||||
:param kwargs: Search parameters (accepts service name or type)
|
||||
:rtype: boolean
|
||||
"""
|
||||
a_s = self.available_services
|
||||
if kwargs.get('name'):
|
||||
if kwargs.get('name') not in self.available_services.keys():
|
||||
return False
|
||||
return True
|
||||
if [s for s in a_s if s['name'] == kwargs.get('name')]:
|
||||
return True
|
||||
return False
|
||||
|
||||
if kwargs.get('type'):
|
||||
if kwargs.get('type') not in self.available_services.values():
|
||||
return False
|
||||
return True
|
||||
if [s for s in a_s if s['type'] == kwargs.get('type')]:
|
||||
return True
|
||||
return False
|
||||
return False
|
||||
|
||||
def post_configuration(self):
|
||||
|
@ -35,5 +35,5 @@ class ShareService(VersionedService):
|
||||
return 'share'
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
return ['manila', 'manilav2']
|
||||
def get_service_type():
|
||||
return ['share', 'sharev2']
|
||||
|
@ -19,8 +19,8 @@ from config_tempest.services.base import Service
|
||||
class TelemetryService(Service):
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
return ['ceilometer']
|
||||
def get_service_type():
|
||||
return ['telemetry']
|
||||
|
||||
@staticmethod
|
||||
def get_codename():
|
||||
|
@ -56,8 +56,8 @@ class VolumeService(VersionedService):
|
||||
return 'volume'
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
return ['cinderv2', 'cinderv3']
|
||||
def get_service_type():
|
||||
return ['volumev2', 'volumev3']
|
||||
|
||||
def post_configuration(self, conf, is_service):
|
||||
# Verify if the cinder backup service is enabled
|
||||
|
@ -19,8 +19,8 @@ from config_tempest.services.base import Service
|
||||
class Workflowv2Service(Service):
|
||||
|
||||
@staticmethod
|
||||
def get_service_name():
|
||||
return ['mistral']
|
||||
def get_service_type():
|
||||
return ['workflow']
|
||||
|
||||
@staticmethod
|
||||
def get_codename():
|
||||
|
@ -26,9 +26,11 @@ class TestEc2Service(BaseConfigTempestTest):
|
||||
FAKE_URL = "http://10.200.16.10:8774/"
|
||||
|
||||
@mock.patch('config_tempest.services.services.Services.discover')
|
||||
@mock.patch('config_tempest.services.services.Services.'
|
||||
'set_catalog_and_url')
|
||||
@mock.patch('config_tempest.services.services.Services.'
|
||||
'get_available_services')
|
||||
def setUp(self, mock_set_avail, mock_discover):
|
||||
def setUp(self, mock_set_avail, mock_catalog, mock_discover):
|
||||
super(TestEc2Service, self).setUp()
|
||||
conf = self._get_conf('v2', 'v3')
|
||||
self.clients = self._get_clients(conf)
|
||||
@ -46,9 +48,11 @@ class TestS3Service(BaseConfigTempestTest):
|
||||
FAKE_URL = "http://10.200.16.10:8774/"
|
||||
|
||||
@mock.patch('config_tempest.services.services.Services.discover')
|
||||
@mock.patch('config_tempest.services.services.Services.'
|
||||
'set_catalog_and_url')
|
||||
@mock.patch('config_tempest.services.services.Services.'
|
||||
'get_available_services')
|
||||
def setUp(self, mock_set_avail, mock_discover):
|
||||
def setUp(self, mock_set_avail, mock_catalog, mock_discover):
|
||||
super(TestS3Service, self).setUp()
|
||||
conf = self._get_conf('v2', 'v3')
|
||||
self.clients = self._get_clients(conf)
|
||||
|
@ -37,10 +37,13 @@ class TestServices(BaseConfigTempestTest):
|
||||
super(TestServices, self).setUp()
|
||||
|
||||
@mock.patch('config_tempest.services.services.Services.discover')
|
||||
@mock.patch('config_tempest.services.services.Services.'
|
||||
'set_catalog_and_url')
|
||||
@mock.patch('config_tempest.services.services.Services.'
|
||||
'get_available_services')
|
||||
def _create_services_instance(self, mock_avail, mock_discover, v2=False):
|
||||
mock_avail.return_value = {'my_service': 'my_type'}
|
||||
def _create_services_instance(self, mock_avail, mock_catalog,
|
||||
mock_discover, v2=False):
|
||||
mock_avail.return_value = [{'name': 'my_service', 'type': 'my_type'}]
|
||||
conf = self._get_conf('v2', 'v3')
|
||||
creds = self._get_creds(conf, v2=v2)
|
||||
clients = mock.Mock()
|
||||
@ -74,18 +77,6 @@ class TestServices(BaseConfigTempestTest):
|
||||
resp = services.get_endpoints({'endpoints': []})
|
||||
self.assertEqual(resp, [])
|
||||
|
||||
def test_set_catalog_and_url(self):
|
||||
# api version = 2
|
||||
services = self._create_services_instance(v2=True)
|
||||
services.set_catalog_and_url()
|
||||
self.assertEqual(services.service_catalog, 'serviceCatalog')
|
||||
self.assertEqual(services.public_url, 'publicURL')
|
||||
# api version = 3
|
||||
services = self._create_services_instance()
|
||||
services.set_catalog_and_url()
|
||||
self.assertEqual(services.service_catalog, 'catalog')
|
||||
self.assertEqual(services.public_url, 'url')
|
||||
|
||||
def test_parse_endpoints_empty(self):
|
||||
services = self._create_services_instance()
|
||||
services.public_url = "url"
|
||||
|
Loading…
Reference in New Issue
Block a user