Merge "Add service name to catalog"
This commit is contained in:
		| @@ -84,11 +84,15 @@ class ServiceCatalog(object): | |||||||
|         """ |         """ | ||||||
|  |  | ||||||
|     def get_endpoints(self, service_type=None, endpoint_type=None, |     def get_endpoints(self, service_type=None, endpoint_type=None, | ||||||
|                       region_name=None): |                       region_name=None, service_name=None): | ||||||
|         """Fetch and filter endpoints for the specified service(s). |         """Fetch and filter endpoints for the specified service(s). | ||||||
|  |  | ||||||
|         Returns endpoints for the specified service (or all) containing |         Returns endpoints for the specified service (or all) containing | ||||||
|         the specified type (or all) and region (or all). |         the specified type (or all) and region (or all) and service name. | ||||||
|  |  | ||||||
|  |         If there is no name in the service catalog the service_name check will | ||||||
|  |         be skipped.  This allows compatibility with services that existed | ||||||
|  |         before the name was available in the catalog. | ||||||
|         """ |         """ | ||||||
|         endpoint_type = self._normalize_endpoint_type(endpoint_type) |         endpoint_type = self._normalize_endpoint_type(endpoint_type) | ||||||
|         region_name = region_name or self._region_name |         region_name = region_name or self._region_name | ||||||
| @@ -104,6 +108,21 @@ class ServiceCatalog(object): | |||||||
|             if service_type and service_type != st: |             if service_type and service_type != st: | ||||||
|                 continue |                 continue | ||||||
|  |  | ||||||
|  |             # NOTE(jamielennox): service_name is different. It is not available | ||||||
|  |             # in API < v3.3. If it is in the catalog then we enforce it, if it | ||||||
|  |             # is not then we don't because the name could be correct we just | ||||||
|  |             # don't have that information to check against. | ||||||
|  |             if service_name: | ||||||
|  |                 try: | ||||||
|  |                     sn = service['name'] | ||||||
|  |                 except KeyError: | ||||||
|  |                     # assume that we're in v3.0-v3.2 and don't have the name in | ||||||
|  |                     # the catalog. Skip the check. | ||||||
|  |                     pass | ||||||
|  |                 else: | ||||||
|  |                     if service_name != sn: | ||||||
|  |                         continue | ||||||
|  |  | ||||||
|             sc[st] = [] |             sc[st] = [] | ||||||
|  |  | ||||||
|             for endpoint in service.get('endpoints', []): |             for endpoint in service.get('endpoints', []): | ||||||
| @@ -117,13 +136,14 @@ class ServiceCatalog(object): | |||||||
|         return sc |         return sc | ||||||
|  |  | ||||||
|     def _get_service_endpoints(self, attr, filter_value, service_type, |     def _get_service_endpoints(self, attr, filter_value, service_type, | ||||||
|                                endpoint_type, region_name): |                                endpoint_type, region_name, service_name): | ||||||
|         """Fetch the endpoints of a particular service_type and handle |         """Fetch the endpoints of a particular service_type and handle | ||||||
|         the filtering. |         the filtering. | ||||||
|         """ |         """ | ||||||
|         sc_endpoints = self.get_endpoints(service_type=service_type, |         sc_endpoints = self.get_endpoints(service_type=service_type, | ||||||
|                                           endpoint_type=endpoint_type, |                                           endpoint_type=endpoint_type, | ||||||
|                                           region_name=region_name) |                                           region_name=region_name, | ||||||
|  |                                           service_name=service_name) | ||||||
|  |  | ||||||
|         try: |         try: | ||||||
|             endpoints = sc_endpoints[service_type] |             endpoints = sc_endpoints[service_type] | ||||||
| @@ -144,7 +164,7 @@ class ServiceCatalog(object): | |||||||
|     @utils.positional(enforcement=utils.positional.WARN) |     @utils.positional(enforcement=utils.positional.WARN) | ||||||
|     def get_urls(self, attr=None, filter_value=None, |     def get_urls(self, attr=None, filter_value=None, | ||||||
|                  service_type='identity', endpoint_type='publicURL', |                  service_type='identity', endpoint_type='publicURL', | ||||||
|                  region_name=None): |                  region_name=None, service_name=None): | ||||||
|         """Fetch endpoint urls from the service catalog. |         """Fetch endpoint urls from the service catalog. | ||||||
|  |  | ||||||
|         Fetch the endpoints from the service catalog for a particular |         Fetch the endpoints from the service catalog for a particular | ||||||
| @@ -159,6 +179,7 @@ class ServiceCatalog(object): | |||||||
|                                      internal or internalURL, admin or |                                      internal or internalURL, admin or | ||||||
|                                      adminURL |                                      adminURL | ||||||
|         :param string region_name: Region of the endpoint. |         :param string region_name: Region of the endpoint. | ||||||
|  |         :param string service_name: The assigned name of the service. | ||||||
|  |  | ||||||
|         :returns: tuple of urls or None (if no match found) |         :returns: tuple of urls or None (if no match found) | ||||||
|         """ |         """ | ||||||
| @@ -167,7 +188,7 @@ class ServiceCatalog(object): | |||||||
|     @utils.positional(3, enforcement=utils.positional.WARN) |     @utils.positional(3, enforcement=utils.positional.WARN) | ||||||
|     def url_for(self, attr=None, filter_value=None, |     def url_for(self, attr=None, filter_value=None, | ||||||
|                 service_type='identity', endpoint_type='publicURL', |                 service_type='identity', endpoint_type='publicURL', | ||||||
|                 region_name=None): |                 region_name=None, service_name=None): | ||||||
|         """Fetch an endpoint from the service catalog. |         """Fetch an endpoint from the service catalog. | ||||||
|  |  | ||||||
|         Fetch the specified endpoint from the service catalog for |         Fetch the specified endpoint from the service catalog for | ||||||
| @@ -177,6 +198,14 @@ class ServiceCatalog(object): | |||||||
|         Valid endpoint types: `public` or `publicURL`, |         Valid endpoint types: `public` or `publicURL`, | ||||||
|                               `internal` or `internalURL`, |                               `internal` or `internalURL`, | ||||||
|                               `admin` or 'adminURL` |                               `admin` or 'adminURL` | ||||||
|  |  | ||||||
|  |         :param string attr: Endpoint attribute name. | ||||||
|  |         :param string filter_value: Endpoint attribute value. | ||||||
|  |         :param string service_type: Service type of the endpoint. | ||||||
|  |         :param string endpoint_type: Type of endpoint. | ||||||
|  |         :param string region_name: Region of the endpoint. | ||||||
|  |         :param string service_name: The assigned name of the service. | ||||||
|  |         : | ||||||
|         """ |         """ | ||||||
|         if not self.get_data(): |         if not self.get_data(): | ||||||
|             raise exceptions.EmptyCatalog('The service catalog is empty.') |             raise exceptions.EmptyCatalog('The service catalog is empty.') | ||||||
| @@ -185,19 +214,20 @@ class ServiceCatalog(object): | |||||||
|                              filter_value=filter_value, |                              filter_value=filter_value, | ||||||
|                              service_type=service_type, |                              service_type=service_type, | ||||||
|                              endpoint_type=endpoint_type, |                              endpoint_type=endpoint_type, | ||||||
|                              region_name=region_name) |                              region_name=region_name, | ||||||
|  |                              service_name=service_name) | ||||||
|  |  | ||||||
|         try: |         try: | ||||||
|             return urls[0] |             return urls[0] | ||||||
|         except Exception: |         except Exception: | ||||||
|             pass |             pass | ||||||
|  |  | ||||||
|         msg = '%(endpoint)s endpoint for %(service)s%(region)s not found' |         msg = '%s endpoint for %s service' % (endpoint_type, service_type) | ||||||
|         region = ' in %s region' % region_name if region_name else '' |         if service_name: | ||||||
|         msg = msg % {'endpoint': endpoint_type, |             msg += ' named %s' % service_name | ||||||
|                      'service': service_type, |         if region_name: | ||||||
|                      'region': region} |             msg += ' in %s region' % region_name | ||||||
|  |         msg += ' not found' | ||||||
|         raise exceptions.EndpointNotFound(msg) |         raise exceptions.EndpointNotFound(msg) | ||||||
|  |  | ||||||
|     @abc.abstractmethod |     @abc.abstractmethod | ||||||
| @@ -254,13 +284,14 @@ class ServiceCatalogV2(ServiceCatalog): | |||||||
|     @utils.positional(enforcement=utils.positional.WARN) |     @utils.positional(enforcement=utils.positional.WARN) | ||||||
|     def get_urls(self, attr=None, filter_value=None, |     def get_urls(self, attr=None, filter_value=None, | ||||||
|                  service_type='identity', endpoint_type='publicURL', |                  service_type='identity', endpoint_type='publicURL', | ||||||
|                  region_name=None): |                  region_name=None, service_name=None): | ||||||
|         endpoint_type = self._normalize_endpoint_type(endpoint_type) |         endpoint_type = self._normalize_endpoint_type(endpoint_type) | ||||||
|         endpoints = self._get_service_endpoints(attr=attr, |         endpoints = self._get_service_endpoints(attr=attr, | ||||||
|                                                 filter_value=filter_value, |                                                 filter_value=filter_value, | ||||||
|                                                 service_type=service_type, |                                                 service_type=service_type, | ||||||
|                                                 endpoint_type=endpoint_type, |                                                 endpoint_type=endpoint_type, | ||||||
|                                                 region_name=region_name) |                                                 region_name=region_name, | ||||||
|  |                                                 service_name=service_name) | ||||||
|  |  | ||||||
|         if endpoints: |         if endpoints: | ||||||
|             return tuple([endpoint[endpoint_type] for endpoint in endpoints]) |             return tuple([endpoint[endpoint_type] for endpoint in endpoints]) | ||||||
| @@ -319,12 +350,13 @@ class ServiceCatalogV3(ServiceCatalog): | |||||||
|     @utils.positional(enforcement=utils.positional.WARN) |     @utils.positional(enforcement=utils.positional.WARN) | ||||||
|     def get_urls(self, attr=None, filter_value=None, |     def get_urls(self, attr=None, filter_value=None, | ||||||
|                  service_type='identity', endpoint_type='public', |                  service_type='identity', endpoint_type='public', | ||||||
|                  region_name=None): |                  region_name=None, service_name=None): | ||||||
|         endpoints = self._get_service_endpoints(attr=attr, |         endpoints = self._get_service_endpoints(attr=attr, | ||||||
|                                                 filter_value=filter_value, |                                                 filter_value=filter_value, | ||||||
|                                                 service_type=service_type, |                                                 service_type=service_type, | ||||||
|                                                 endpoint_type=endpoint_type, |                                                 endpoint_type=endpoint_type, | ||||||
|                                                 region_name=region_name) |                                                 region_name=region_name, | ||||||
|  |                                                 service_name=service_name) | ||||||
|  |  | ||||||
|         if endpoints: |         if endpoints: | ||||||
|             return tuple([endpoint['url'] for endpoint in endpoints]) |             return tuple([endpoint['url'] for endpoint in endpoints]) | ||||||
|   | |||||||
| @@ -150,3 +150,26 @@ class ServiceCatalogTest(utils.TestCase): | |||||||
|         self.assertEqual(len(endpoints['image']), 1) |         self.assertEqual(len(endpoints['image']), 1) | ||||||
|         self.assertEqual(endpoints['image'][0]['publicURL'], |         self.assertEqual(endpoints['image'][0]['publicURL'], | ||||||
|                          'https://image.south.host/v1/') |                          'https://image.south.host/v1/') | ||||||
|  |  | ||||||
|  |     def test_service_catalog_service_name(self): | ||||||
|  |         auth_ref = access.AccessInfo.factory(resp=None, | ||||||
|  |                                              body=self.AUTH_RESPONSE_BODY) | ||||||
|  |         sc = auth_ref.service_catalog | ||||||
|  |  | ||||||
|  |         url = sc.url_for(service_name='Image Servers', endpoint_type='public', | ||||||
|  |                          service_type='image', region_name='North') | ||||||
|  |         self.assertEqual('https://image.north.host/v1/', url) | ||||||
|  |  | ||||||
|  |         self.assertRaises(exceptions.EndpointNotFound, sc.url_for, | ||||||
|  |                           service_name='Image Servers', service_type='compute') | ||||||
|  |  | ||||||
|  |         urls = sc.get_urls(service_type='image', service_name='Image Servers', | ||||||
|  |                            endpoint_type='public') | ||||||
|  |  | ||||||
|  |         self.assertIn('https://image.north.host/v1/', urls) | ||||||
|  |         self.assertIn('https://image.south.host/v1/', urls) | ||||||
|  |  | ||||||
|  |         urls = sc.get_urls(service_type='image', service_name='Servers', | ||||||
|  |                            endpoint_type='public') | ||||||
|  |  | ||||||
|  |         self.assertIsNone(urls) | ||||||
|   | |||||||
| @@ -332,7 +332,8 @@ AUTH_RESPONSE_BODY = { | |||||||
|                 'region': 'North', |                 'region': 'North', | ||||||
|                 'interface': 'admin' |                 'interface': 'admin' | ||||||
|             }], |             }], | ||||||
|             'type': 'compute' |             'type': 'compute', | ||||||
|  |             'name': 'nova', | ||||||
|         }, { |         }, { | ||||||
|             'endpoints': [{ |             'endpoints': [{ | ||||||
|                 'url': 'http://swift.north.host/swiftapi/public', |                 'url': 'http://swift.north.host/swiftapi/public', | ||||||
| @@ -347,7 +348,8 @@ AUTH_RESPONSE_BODY = { | |||||||
|                 'region': 'South', |                 'region': 'South', | ||||||
|                 'interface': 'admin' |                 'interface': 'admin' | ||||||
|             }], |             }], | ||||||
|             'type': 'object-store' |             'type': 'object-store', | ||||||
|  |             'name': 'swift', | ||||||
|         }, { |         }, { | ||||||
|             'endpoints': [{ |             'endpoints': [{ | ||||||
|                 'url': 'http://glance.north.host/glanceapi/public', |                 'url': 'http://glance.north.host/glanceapi/public', | ||||||
| @@ -374,7 +376,8 @@ AUTH_RESPONSE_BODY = { | |||||||
|                 'region': 'South', |                 'region': 'South', | ||||||
|                 'interface': 'admin' |                 'interface': 'admin' | ||||||
|             }], |             }], | ||||||
|             'type': 'image' |             'type': 'image', | ||||||
|  |             'name': 'glance', | ||||||
|         }] |         }] | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -171,3 +171,51 @@ class ServiceCatalogTest(utils.TestCase): | |||||||
|         for endpoint in endpoints['image']: |         for endpoint in endpoints['image']: | ||||||
|             self.assertEqual(endpoint['url'], |             self.assertEqual(endpoint['url'], | ||||||
|                              self.south_endpoints[endpoint['interface']]) |                              self.south_endpoints[endpoint['interface']]) | ||||||
|  |  | ||||||
|  |     def test_service_catalog_service_name(self): | ||||||
|  |         auth_ref = access.AccessInfo.factory(resp=None, | ||||||
|  |                                              body=self.AUTH_RESPONSE_BODY) | ||||||
|  |         sc = auth_ref.service_catalog | ||||||
|  |  | ||||||
|  |         url = sc.url_for(service_name='glance', endpoint_type='public', | ||||||
|  |                          service_type='image', region_name='North') | ||||||
|  |         self.assertEqual('http://glance.north.host/glanceapi/public', url) | ||||||
|  |  | ||||||
|  |         url = sc.url_for(service_name='glance', endpoint_type='public', | ||||||
|  |                          service_type='image', region_name='South') | ||||||
|  |         self.assertEqual('http://glance.south.host/glanceapi/public', url) | ||||||
|  |  | ||||||
|  |         self.assertRaises(exceptions.EndpointNotFound, sc.url_for, | ||||||
|  |                           service_name='glance', service_type='compute') | ||||||
|  |  | ||||||
|  |         urls = sc.get_urls(service_type='image', service_name='glance', | ||||||
|  |                            endpoint_type='public') | ||||||
|  |  | ||||||
|  |         self.assertIn('http://glance.north.host/glanceapi/public', urls) | ||||||
|  |         self.assertIn('http://glance.south.host/glanceapi/public', urls) | ||||||
|  |  | ||||||
|  |         urls = sc.get_urls(service_type='image', service_name='Servers', | ||||||
|  |                            endpoint_type='public') | ||||||
|  |  | ||||||
|  |         self.assertIsNone(urls) | ||||||
|  |  | ||||||
|  |     def test_service_catalog_without_name(self): | ||||||
|  |         pr_auth_ref = access.AccessInfo.factory( | ||||||
|  |             resp=None, | ||||||
|  |             body=client_fixtures.PROJECT_SCOPED_TOKEN) | ||||||
|  |         pr_sc = pr_auth_ref.service_catalog | ||||||
|  |  | ||||||
|  |         # this will work because there are no service names on that token | ||||||
|  |         url_ref = 'http://public.com:8774/v2/225da22d3ce34b15877ea70b2a575f58' | ||||||
|  |         url = pr_sc.url_for(service_type='compute', service_name='NotExist', | ||||||
|  |                             endpoint_type='public') | ||||||
|  |         self.assertEqual(url_ref, url) | ||||||
|  |  | ||||||
|  |         ab_auth_ref = access.AccessInfo.factory(resp=None, | ||||||
|  |                                                 body=self.AUTH_RESPONSE_BODY) | ||||||
|  |         ab_sc = ab_auth_ref.service_catalog | ||||||
|  |  | ||||||
|  |         # this won't work because there is a name and it's not this one | ||||||
|  |         self.assertRaises(exceptions.EndpointNotFound, ab_sc.url_for, | ||||||
|  |                           service_type='compute', service_name='NotExist', | ||||||
|  |                           endpoint_type='public') | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Jenkins
					Jenkins