def test_successful_formatting(self): url_template = ('http://$(public_bind_host)s:$(admin_port)d/' '$(tenant_id)s/$(user_id)s/$(project_id)s') project_id = uuid.uuid4().hex values = {'public_bind_host': 'server', 'admin_port': 9090, 'tenant_id': 'A', 'user_id': 'B', 'project_id': project_id} actual_url = utils.format_url(url_template, values) expected_url = 'http://server:9090/A/B/%s' % (project_id,) self.assertEqual(expected_url, actual_url)
def test_substitution_with_allowed_project_keyerror(self): # No value of 'project_id' is passed into url_template. # mod: format_url will return None instead of raising # "MalformedEndpoint" exception. # This is intentional behavior since we don't want to skip # all the later endpoints once there is an URL of endpoint # trying to replace 'project_id' with None. url_template = ('http://$(public_bind_host)s:$(admin_port)d/' '$(project_id)s/$(user_id)s') values = {'public_bind_host': 'server', 'admin_port': 9090, 'user_id': 'B'} self.assertIsNone(utils.format_url(url_template, values, silent_keyerror_failures=['project_id']))
def get_v3_catalog(self, user_id, project_id): substitutions = dict(CONF.items()) substitutions.update({ 'tenant_id': project_id, 'project_id': project_id, 'user_id': user_id, }) services = {} dict_of_endpoint_refs = (self.catalog_api. list_endpoints_for_project(project_id)) if (not dict_of_endpoint_refs and CONF.endpoint_filter.return_all_endpoints_if_no_filter): return super(EndpointFilterCatalog, self).get_v3_catalog( user_id, project_id) for endpoint_id, endpoint in dict_of_endpoint_refs.items(): if not endpoint['enabled']: # Skip disabled endpoints. continue service_id = endpoint['service_id'] services.setdefault( service_id, self.get_service(service_id)) service = services[service_id] del endpoint['service_id'] del endpoint['enabled'] del endpoint['legacy_endpoint_id'] # Include deprecated region for backwards compatibility endpoint['region'] = endpoint['region_id'] endpoint['url'] = utils.format_url( endpoint['url'], substitutions) # populate filtered endpoints if 'endpoints' in services[service_id]: service['endpoints'].append(endpoint) else: service['endpoints'] = [endpoint] # format catalog catalog = [] for service_id, service in services.items(): formatted_service = {} formatted_service['id'] = service['id'] formatted_service['type'] = service['type'] formatted_service['name'] = service['name'] formatted_service['endpoints'] = service['endpoints'] catalog.append(formatted_service) return catalog
def get_catalog(self, user_id, tenant_id): """Retrieve and format the V2 service catalog. :param user_id: The id of the user who has been authenticated for creating service catalog. :param tenant_id: The id of the project. 'tenant_id' will be None in the case this being called to create a catalog to go in a domain scoped token. In this case, any endpoint that requires a tenant_id as part of their URL will be skipped. :returns: A nested dict representing the service catalog or an empty dict. """ substitutions = dict( itertools.chain(CONF.items(), CONF.eventlet_server.items())) substitutions.update({'user_id': user_id}) silent_keyerror_failures = [] if tenant_id: substitutions.update({ 'tenant_id': tenant_id, 'project_id': tenant_id, }) else: silent_keyerror_failures = [ 'tenant_id', 'project_id', ] catalog = {} # TODO(davechen): If there is service with no endpoints, we should # skip the service instead of keeping it in the catalog. # see bug #1436704. for region, region_ref in self.templates.items(): catalog[region] = {} for service, service_ref in region_ref.items(): service_data = {} try: for k, v in service_ref.items(): formatted_value = utils.format_url( v, substitutions, silent_keyerror_failures=silent_keyerror_failures) if formatted_value: service_data[k] = formatted_value except exception.MalformedEndpoint: # nosec(tkelsey) continue # this failure is already logged in format_url() catalog[region][service] = service_data return catalog
def test_successful_formatting(self): url_template = ('http://$(public_bind_host)s:$(admin_port)d/' '$(tenant_id)s/$(user_id)s/$(project_id)s') project_id = uuid.uuid4().hex values = { 'public_bind_host': 'server', 'admin_port': 9090, 'tenant_id': 'A', 'user_id': 'B', 'project_id': project_id } actual_url = utils.format_url(url_template, values) expected_url = 'http://server:9090/A/B/%s' % (project_id, ) self.assertEqual(expected_url, actual_url)
def get_v3_catalog(self, user_id, project_id): substitutions = dict(CONF.items()) substitutions.update({ 'tenant_id': project_id, 'project_id': project_id, 'user_id': user_id, }) services = {} dict_of_endpoint_refs = ( self.catalog_api.list_endpoints_for_project(project_id)) if (not dict_of_endpoint_refs and CONF.endpoint_filter.return_all_endpoints_if_no_filter): return super(EndpointFilterCatalog, self).get_v3_catalog(user_id, project_id) for endpoint_id, endpoint in dict_of_endpoint_refs.items(): if not endpoint['enabled']: # Skip disabled endpoints. continue service_id = endpoint['service_id'] services.setdefault(service_id, self.get_service(service_id)) service = services[service_id] del endpoint['service_id'] del endpoint['enabled'] del endpoint['legacy_endpoint_id'] # Include deprecated region for backwards compatibility endpoint['region'] = endpoint['region_id'] endpoint['url'] = utils.format_url(endpoint['url'], substitutions) # populate filtered endpoints if 'endpoints' in services[service_id]: service['endpoints'].append(endpoint) else: service['endpoints'] = [endpoint] # format catalog catalog = [] for service_id, service in services.items(): formatted_service = {} formatted_service['id'] = service['id'] formatted_service['type'] = service['type'] formatted_service['name'] = service['name'] formatted_service['endpoints'] = service['endpoints'] catalog.append(formatted_service) return catalog
def get_catalog(self, user_id, tenant_id): """Retrieve and format the V2 service catalog. :param user_id: The id of the user who has been authenticated for creating service catalog. :param tenant_id: The id of the project. 'tenant_id' will be None in the case this being called to create a catalog to go in a domain scoped token. In this case, any endpoint that requires a tenant_id as part of their URL will be skipped. :returns: A nested dict representing the service catalog or an empty dict. """ substitutions = dict( itertools.chain(CONF.items(), CONF.eventlet_server.items())) substitutions.update({'user_id': user_id}) silent_keyerror_failures = [] if tenant_id: substitutions.update({ 'tenant_id': tenant_id, 'project_id': tenant_id, }) else: silent_keyerror_failures = ['tenant_id', 'project_id', ] catalog = {} # TODO(davechen): If there is service with no endpoints, we should # skip the service instead of keeping it in the catalog. # see bug #1436704. for region, region_ref in self.templates.items(): catalog[region] = {} for service, service_ref in region_ref.items(): service_data = {} try: for k, v in service_ref.items(): formatted_value = utils.format_url( v, substitutions, silent_keyerror_failures=silent_keyerror_failures) if formatted_value: service_data[k] = formatted_value except exception.MalformedEndpoint: # nosec(tkelsey) continue # this failure is already logged in format_url() catalog[region][service] = service_data return catalog
def test_substitution_with_allowed_project_keyerror(self): # No value of 'project_id' is passed into url_template. # mod: format_url will return None instead of raising # "MalformedEndpoint" exception. # This is intentional behavior since we don't want to skip # all the later endpoints once there is an URL of endpoint # trying to replace 'project_id' with None. url_template = ('http://$(public_bind_host)s:$(admin_port)d/' '$(project_id)s/$(user_id)s') values = { 'public_bind_host': 'server', 'admin_port': 9090, 'user_id': 'B' } self.assertIsNone( utils.format_url(url_template, values, silent_keyerror_failures=['project_id']))
def make_v3_endpoints(endpoints): for endpoint in (ep.to_dict() for ep in endpoints if ep.enabled): del endpoint['service_id'] del endpoint['legacy_endpoint_id'] del endpoint['enabled'] endpoint['region'] = endpoint['region_id'] try: formatted_url = utils.format_url( endpoint['url'], d, silent_keyerror_failures=silent_keyerror_failures) if formatted_url: endpoint['url'] = formatted_url else: continue except exception.MalformedEndpoint: # nosec(tkelsey) # this failure is already logged in format_url() continue yield endpoint
def get_catalog(self, user_id, tenant_id): """Retrieve and format the V2 service catalog. :param user_id: The id of the user who has been authenticated for creating service catalog. :param tenant_id: The id of the project. 'tenant_id' will be None in the case this being called to create a catalog to go in a domain scoped token. In this case, any endpoint that requires a tenant_id as part of their URL will be skipped (as would a whole service if, as a consequence, it has no valid endpoints). :returns: A nested dict representing the service catalog or an empty dict. """ substitutions = dict( itertools.chain(CONF.items(), CONF.eventlet_server.items())) substitutions.update({'user_id': user_id}) silent_keyerror_failures = [] if tenant_id: substitutions.update({ 'tenant_id': tenant_id, 'project_id': tenant_id }) else: silent_keyerror_failures = ['tenant_id', 'project_id', ] with sql.session_for_read() as session: endpoints = (session.query(Endpoint). options(sql.joinedload(Endpoint.service)). filter(Endpoint.enabled == true()).all()) catalog = {} for endpoint in endpoints: if not endpoint.service['enabled']: continue try: formatted_url = utils.format_url( endpoint['url'], substitutions, silent_keyerror_failures=silent_keyerror_failures) if formatted_url is not None: url = formatted_url else: continue except exception.MalformedEndpoint: # nosec(tkelsey) continue # this failure is already logged in format_url() region = endpoint['region_id'] service_type = endpoint.service['type'] default_service = { 'id': endpoint['id'], 'name': endpoint.service.extra.get('name', ''), 'publicURL': '' } catalog.setdefault(region, {}) catalog[region].setdefault(service_type, default_service) interface_url = '%sURL' % endpoint['interface'] catalog[region][service_type][interface_url] = url return catalog
def get_catalog(self, user_id, project_id): """Retrieve and format the V2 service catalog. :param user_id: The id of the user who has been authenticated for creating service catalog. :param project_id: The id of the project. 'project_id' will be None in the case this being called to create a catalog to go in a domain scoped token. In this case, any endpoint that requires a project_id as part of their URL will be skipped (as would a whole service if, as a consequence, it has no valid endpoints). :returns: A nested dict representing the service catalog or an empty dict. """ substitutions = dict( itertools.chain(CONF.items(), CONF.eventlet_server.items())) substitutions.update({'user_id': user_id}) silent_keyerror_failures = [] if project_id: substitutions.update({ 'tenant_id': project_id, 'project_id': project_id }) else: silent_keyerror_failures = ['tenant_id', 'project_id'] with sql.session_for_read() as session: endpoints = (session.query(Endpoint).options( sql.joinedload(Endpoint.service)).filter( Endpoint.enabled == true()).all()) catalog = {} for endpoint in endpoints: if not endpoint.service['enabled']: continue try: formatted_url = utils.format_url( endpoint['url'], substitutions, silent_keyerror_failures=silent_keyerror_failures) if formatted_url is not None: url = formatted_url else: continue except exception.MalformedEndpoint: # nosec(tkelsey) continue # this failure is already logged in format_url() region = endpoint['region_id'] service_type = endpoint.service['type'] default_service = { 'id': endpoint['id'], 'name': endpoint.service.extra.get('name', ''), 'publicURL': '' } catalog.setdefault(region, {}) catalog[region].setdefault(service_type, default_service) interface_url = '%sURL' % endpoint['interface'] catalog[region][service_type][interface_url] = url return catalog