diff --git a/api-ref/source/v2-admin/admin-endpoints.inc b/api-ref/source/v2-admin/admin-endpoints.inc deleted file mode 100644 index 8bdd22adf9..0000000000 --- a/api-ref/source/v2-admin/admin-endpoints.inc +++ /dev/null @@ -1,78 +0,0 @@ -.. -*- rst -*- - -========= -Endpoints -========= - - -List endpoint templates -======================= - -.. rest_method:: GET /v2.0/endpoints - -Normal response codes: 200 - -Response Parameters -------------------- - -.. rest_parameters:: parameters.yaml - - - endpoints: endpoints - -Response Example ----------------- - -.. literalinclude:: samples/admin/endpoint-list-response.json - :language: javascript - - -Create endpoint template -======================== - -.. rest_method:: POST /v2.0/endpoints - -Normal response codes: 201 - -Request -------- - -.. rest_parameters:: parameters.yaml - - - endpoint: endpoint - - region: endpoint_region_request - - service_id: service_id_request - - publicurl: endpoint_publicurl_request - - adminurl: endpoint_adminurl_request - - internalurl: endpoint_internalurl_request - -Request Example ---------------- - -.. literalinclude:: samples/admin/endpoint-create-request.json - :language: javascript - -Response Parameters -------------------- - -.. rest_parameters:: parameters.yaml - - - endpoint: endpoint - - id: endpoint_id - - internalurl: endpoint_internalurl_response - - publicurl: endpoint_publicurl_response - - region: endpoint_region_response - - -Delete endpoint template -======================== - -.. rest_method:: DELETE /v2.0/endpoints/{endpointId} - -Normal response codes: 204 - -Request -------- - -.. rest_parameters:: parameters.yaml - - - endpointId: endpoint_id_path diff --git a/api-ref/source/v2-admin/index.rst b/api-ref/source/v2-admin/index.rst index acad2ac633..a5ecbd06fc 100644 --- a/api-ref/source/v2-admin/index.rst +++ b/api-ref/source/v2-admin/index.rst @@ -9,6 +9,5 @@ .. include:: admin-tenants.inc .. include:: admin-tokens.inc .. include:: admin-users.inc -.. include:: admin-endpoints.inc .. include:: admin-versions.inc .. include:: admin-certificates.inc diff --git a/api-ref/source/v2-ext/ksadm-admin.inc b/api-ref/source/v2-ext/ksadm-admin.inc index 0279004bf2..9f50bafc52 100644 --- a/api-ref/source/v2-ext/ksadm-admin.inc +++ b/api-ref/source/v2-ext/ksadm-admin.inc @@ -142,141 +142,6 @@ Response Example :language: javascript -Create service (admin extension) -================================ - -.. rest_method:: POST /v2.0/OS-KSADM/services - -Creates a service. - -Normal response codes: 201 -Error response codes: 413,415,405,404,403,401,400,503,409 - -Request Example ---------------- - -.. literalinclude:: samples/OS-KSADM/service-create-request.json - :language: javascript - -Response Parameters -------------------- - -.. rest_parameters:: parameters.yaml - - - Location: Location - - type: service_type - - description: service_description - - name: service_name - - id: service_id - - -List services (admin extension) -=============================== - -.. rest_method:: GET /v2.0/OS-KSADM/services - -Lists all services. - -Normal response codes: 200,203 -Error response codes: 413,405,404,403,401,400,503 - -Response Parameters -------------------- - -.. rest_parameters:: parameters.yaml - - - type: service_type - - description: service_description - - name: service_name - - id: service_id - -Response Example ----------------- - -.. literalinclude:: samples/OS-KSADM/services-list-response.json - :language: javascript - - -Shows service information by ID -=============================== - -.. rest_method:: GET /v2.0/OS-KSADM/services/{service_id} - -Shows information for a service, by ID. - -Normal response codes: 200,203 -Error response codes: 413,405,404,403,401,400,503 - -Request -------- - -.. rest_parameters:: parameters.yaml - - - service_id: service_id_path - -Response Parameters -------------------- - -.. rest_parameters:: parameters.yaml - - - type: service_type - - description: service_description - - name: service_name - - id: service_id - -Response Example ----------------- - -.. literalinclude:: samples/OS-KSADM/service-show-response.json - :language: javascript - - -Show service information by name -================================ - -.. rest_method:: GET /v2.0/OS-KSADM/services/{serviceName} - -Shows information for a service, by name. - -Normal response codes: 200,203 -Error response codes: 413,405,404,403,401,400,503 - -Response Parameters -------------------- - -.. rest_parameters:: parameters.yaml - - - serviceName: service_name_path - - type: service_type - - description: service_description - - name: service_name - - id: service_id - -Response Example ----------------- - -.. literalinclude:: samples/OS-KSADM/service-show-response.json - :language: javascript - - -Delete service (admin extension) -================================ - -.. rest_method:: DELETE /v2.0/OS-KSADM/services/{service_id} - -Deletes a service. - -Normal response codes: 204 -Error response codes: 413,415,405,404,403,401,400,503,409 - -Request -------- - -.. rest_parameters:: parameters.yaml - - - service_id: service_id_path - - Create a role ============= diff --git a/api-ref/source/v2-ext/samples/OS-KSADM/service-create-request.json b/api-ref/source/v2-ext/samples/OS-KSADM/service-create-request.json deleted file mode 100644 index 06acd60a4a..0000000000 --- a/api-ref/source/v2-ext/samples/OS-KSADM/service-create-request.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "OS-KSADM:service": { - "id": "123", - "name": "nova", - "type": "compute", - "description": "OpenStack Compute Service" - } -} diff --git a/api-ref/source/v2-ext/samples/OS-KSADM/service-show-response.json b/api-ref/source/v2-ext/samples/OS-KSADM/service-show-response.json deleted file mode 100644 index 06acd60a4a..0000000000 --- a/api-ref/source/v2-ext/samples/OS-KSADM/service-show-response.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "OS-KSADM:service": { - "id": "123", - "name": "nova", - "type": "compute", - "description": "OpenStack Compute Service" - } -} diff --git a/api-ref/source/v2-ext/samples/OS-KSADM/services-list-response.json b/api-ref/source/v2-ext/samples/OS-KSADM/services-list-response.json deleted file mode 100644 index 07cd95cb31..0000000000 --- a/api-ref/source/v2-ext/samples/OS-KSADM/services-list-response.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "OS-KSADM:services": [ - { - "id": "123", - "name": "nova", - "type": "compute", - "description": "OpenStack Compute Service" - }, - { - "id": "234", - "name": "glance", - "type": "image", - "description": "OpenStack Image Service" - } - ], - "OS-KSADM:services_links": [] -} diff --git a/keystone/catalog/controllers.py b/keystone/catalog/controllers.py index 3782896000..b5bfb4e73c 100644 --- a/keystone/catalog/controllers.py +++ b/keystone/catalog/controllers.py @@ -13,8 +13,6 @@ # License for the specific language governing permissions and limitations # under the License. -import uuid - from six.moves import http_client from keystone.catalog import schema @@ -32,177 +30,6 @@ from keystone import resource INTERFACES = ['public', 'internal', 'admin'] -@dependency.requires('catalog_api') -class Service(controller.V2Controller): - - @controller.v2_deprecated - def get_services(self, request): - self.assert_admin(request) - service_list = self.catalog_api.list_services() - return {'OS-KSADM:services': service_list} - - @controller.v2_deprecated - def get_service(self, request, service_id): - self.assert_admin(request) - service_ref = self.catalog_api.get_service(service_id) - return {'OS-KSADM:service': service_ref} - - @controller.v2_deprecated - def delete_service(self, request, service_id): - self.assert_admin(request) - self.catalog_api.delete_service( - service_id, initiator=request.audit_initiator - ) - - @controller.v2_deprecated - def create_service(self, request, OS_KSADM_service): - validation.lazy_validate(schema.service_create_v2, OS_KSADM_service) - self.assert_admin(request) - service_id = uuid.uuid4().hex - service_ref = OS_KSADM_service.copy() - service_ref['id'] = service_id - new_service_ref = self.catalog_api.create_service( - service_id, service_ref, initiator=request.audit_initiator) - return {'OS-KSADM:service': new_service_ref} - - -@dependency.requires('catalog_api') -class Endpoint(controller.V2Controller): - - @controller.v2_deprecated - def get_endpoints(self, request): - """Merge matching v3 endpoint refs into legacy refs.""" - self.assert_admin(request) - legacy_endpoints = {} - v3_endpoints = {} - for endpoint in self.catalog_api.list_endpoints(): - if not endpoint.get('legacy_endpoint_id'): # pure v3 endpoint - # tell endpoints apart by the combination of - # service_id and region_id. - # NOTE(muyu): in theory, it's possible that there are more than - # one endpoint of one service, one region and one interface, - # but in practice, it makes no sense because only one will be - # used. - key = (endpoint['service_id'], endpoint['region_id']) - v3_endpoints.setdefault(key, []).append(endpoint) - else: # legacy endpoint - if endpoint['legacy_endpoint_id'] not in legacy_endpoints: - legacy_ep = endpoint.copy() - legacy_ep['id'] = legacy_ep.pop('legacy_endpoint_id') - legacy_ep.pop('interface') - legacy_ep.pop('url') - legacy_ep['region'] = legacy_ep.pop('region_id') - - legacy_endpoints[endpoint['legacy_endpoint_id']] = ( - legacy_ep) - else: - legacy_ep = ( - legacy_endpoints[endpoint['legacy_endpoint_id']]) - - # add the legacy endpoint with an interface url - legacy_ep['%surl' % endpoint['interface']] = endpoint['url'] - - # convert collected v3 endpoints into v2 endpoints - for endpoints in v3_endpoints.values(): - legacy_ep = {} - # For v3 endpoints in the same group, contents of extra attributes - # can be different, which may cause confusion if a random one is - # used. So only necessary attributes are used here. - # It's different for legacy v2 endpoints, which are created - # with the same "extra" value when being migrated. - for key in ('service_id', 'enabled'): - legacy_ep[key] = endpoints[0][key] - legacy_ep['region'] = endpoints[0]['region_id'] - for endpoint in endpoints: - # Public URL is required for v2 endpoints, so the generated v2 - # endpoint uses public endpoint's id as its id, which can also - # be an indicator whether a public v3 endpoint is present. - # It's safe to do so is also because that there is no v2 API to - # get an endpoint by endpoint ID. - if endpoint['interface'] == 'public': - legacy_ep['id'] = endpoint['id'] - legacy_ep['%surl' % endpoint['interface']] = endpoint['url'] - - # this means there is no public URL of this group of v3 endpoints - if 'id' not in legacy_ep: - continue - legacy_endpoints[legacy_ep['id']] = legacy_ep - return {'endpoints': list(legacy_endpoints.values())} - - @controller.v2_deprecated - def create_endpoint(self, request, endpoint): - """Create three v3 endpoint refs based on a legacy ref.""" - self.assert_admin(request) - - # according to the v2 spec publicurl is mandatory - self._require_attribute(endpoint, 'publicurl') - # service_id is necessary - self._require_attribute(endpoint, 'service_id') - - # we should check publicurl, adminurl, internalurl - # if invalid, we should raise an exception to reject - # the request - for interface in INTERFACES: - interface_url = endpoint.get(interface + 'url') - if interface_url: - utils.check_endpoint_url(interface_url) - - if endpoint.get('region') is not None: - try: - self.catalog_api.get_region(endpoint['region']) - except exception.RegionNotFound: - region = dict(id=endpoint['region']) - self.catalog_api.create_region( - region, initiator=request.audit_initiator - ) - - legacy_endpoint_ref = endpoint.copy() - - urls = {} - for i in INTERFACES: - # remove all urls so they aren't persisted them more than once - url = '%surl' % i - if endpoint.get(url): - # valid urls need to be persisted - urls[i] = endpoint.pop(url) - elif url in endpoint: - # null or empty urls can be discarded - endpoint.pop(url) - legacy_endpoint_ref.pop(url) - - legacy_endpoint_id = uuid.uuid4().hex - for interface, url in urls.items(): - endpoint_ref = endpoint.copy() - endpoint_ref['id'] = uuid.uuid4().hex - endpoint_ref['legacy_endpoint_id'] = legacy_endpoint_id - endpoint_ref['interface'] = interface - endpoint_ref['url'] = url - endpoint_ref['region_id'] = endpoint_ref.pop('region', None) - self.catalog_api.create_endpoint(endpoint_ref['id'], - endpoint_ref, - initiator=request.audit_initiator) - - legacy_endpoint_ref['id'] = legacy_endpoint_id - return {'endpoint': legacy_endpoint_ref} - - @controller.v2_deprecated - def delete_endpoint(self, request, endpoint_id): - """Delete up to three v3 endpoint refs based on a legacy ref ID.""" - self.assert_admin(request) - - deleted_at_least_one = False - for endpoint in self.catalog_api.list_endpoints(): - if endpoint['legacy_endpoint_id'] == endpoint_id: - self.catalog_api.delete_endpoint( - endpoint['id'], - initiator=request.audit_initiator - ) - deleted_at_least_one = True - - if not deleted_at_least_one: - raise exception.EndpointNotFound(endpoint_id=endpoint_id) - - @dependency.requires('catalog_api') class RegionV3(controller.V3Controller): collection_name = 'regions' diff --git a/keystone/tests/unit/common/test_notifications.py b/keystone/tests/unit/common/test_notifications.py index 722508a27a..ddb8ff4b02 100644 --- a/keystone/tests/unit/common/test_notifications.py +++ b/keystone/tests/unit/common/test_notifications.py @@ -945,61 +945,6 @@ class V2Notifications(BaseNotificationTest): 'role', cadftaxonomy.SECURITY_ROLE) - def test_service_and_endpoint(self): - token = self.get_scoped_token() - resp = self.admin_request( - method='POST', - path='/v2.0/OS-KSADM/services', - body={ - 'OS-KSADM:service': { - 'name': uuid.uuid4().hex, - 'type': uuid.uuid4().hex, - 'description': uuid.uuid4().hex, - }, - }, - token=token, - ) - service_id = resp.result.get('OS-KSADM:service').get('id') - self._assert_initiator_data_is_set(CREATED_OPERATION, - 'service', - cadftaxonomy.SECURITY_SERVICE) - resp = self.admin_request( - method='POST', - path='/v2.0/endpoints', - body={ - 'endpoint': { - 'region': uuid.uuid4().hex, - 'service_id': service_id, - 'publicurl': uuid.uuid4().hex, - 'adminurl': uuid.uuid4().hex, - 'internalurl': uuid.uuid4().hex, - }, - }, - token=token, - ) - endpoint_id = resp.result.get('endpoint').get('id') - self._assert_initiator_data_is_set(CREATED_OPERATION, - 'endpoint', - cadftaxonomy.SECURITY_ENDPOINT) - # test for delete endpoint - self.admin_request( - method='DELETE', - path='/v2.0/endpoints/%s' % endpoint_id, - token=token, - ) - self._assert_initiator_data_is_set(DELETED_OPERATION, - 'endpoint', - cadftaxonomy.SECURITY_ENDPOINT) - # test for delete service - self.admin_request( - method='DELETE', - path='/v2.0/OS-KSADM/services/%s' % service_id, - token=token, - ) - self._assert_initiator_data_is_set(DELETED_OPERATION, - 'service', - cadftaxonomy.SECURITY_SERVICE) - def test_project(self): token = self.get_scoped_token() resp = self.admin_request( diff --git a/keystone/tests/unit/test_catalog.py b/keystone/tests/unit/test_catalog.py deleted file mode 100644 index 70dbc75e35..0000000000 --- a/keystone/tests/unit/test_catalog.py +++ /dev/null @@ -1,365 +0,0 @@ -# Copyright 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 uuid - -from six.moves import http_client - -from keystone import catalog -from keystone.tests import unit -from keystone.tests.unit.ksfixtures import database -from keystone.tests.unit import rest - - -BASE_URL = 'http://127.0.0.1:35357/v2' -SERVICE_ID = uuid.uuid4().hex - - -class V2CatalogTestCase(rest.RestfulTestCase): - def setUp(self): - super(V2CatalogTestCase, self).setUp() - self.useFixture(database.Database()) - - self.service = unit.new_service_ref() - self.service_id = self.service['id'] - self.catalog_api.create_service(self.service_id, self.service) - - # TODO(termie): add an admin user to the fixtures and use that user - # override the fixtures, for now - self.assignment_api.add_role_to_user_and_project( - self.user_foo['id'], - self.tenant_bar['id'], - self.role_admin['id']) - - def config_overrides(self): - super(V2CatalogTestCase, self).config_overrides() - self.config_fixture.config(group='catalog', driver='sql') - - def _get_token_id(self, r): - """Applicable only to JSON.""" - return r.result['access']['token']['id'] - - def _endpoint_create(self, expected_status=http_client.OK, - service_id=SERVICE_ID, - publicurl='http://localhost:8080', - internalurl='http://localhost:8080', - adminurl='http://localhost:8080', - region=uuid.uuid4().hex): - if service_id is SERVICE_ID: - service_id = self.service_id - - path = '/v2.0/endpoints' - body = { - 'endpoint': { - 'adminurl': adminurl, - 'service_id': service_id, - 'internalurl': internalurl, - 'publicurl': publicurl - } - } - if region is not None: - body['endpoint']['region'] = region - - r = self.admin_request(method='POST', token=self.get_scoped_token(), - path=path, expected_status=expected_status, - body=body) - return body, r - - def _region_create(self): - region = unit.new_region_ref() - region_id = region['id'] - self.catalog_api.create_region(region) - return region_id - - def test_endpoint_create(self): - req_body, response = self._endpoint_create() - self.assertIn('endpoint', response.result) - self.assertIn('id', response.result['endpoint']) - for field, value in req_body['endpoint'].items(): - self.assertEqual(value, response.result['endpoint'][field]) - - def test_endpoint_create_without_region(self): - req_body, response = self._endpoint_create(region=None) - self.assertIn('endpoint', response.result) - self.assertIn('id', response.result['endpoint']) - self.assertNotIn('region', response.result['endpoint']) - for field, value in req_body['endpoint'].items(): - self.assertEqual(value, response.result['endpoint'][field]) - - def test_pure_v3_endpoint_with_publicurl_visible_from_v2(self): - """Test pure v3 endpoint can be fetched via v2.0 API. - - For those who are using v2.0 APIs, endpoints created by v3 API should - also be visible as there are no differences about the endpoints - except the format or the internal implementation. Since publicURL is - required for v2.0 API, so only v3 endpoints of the service which have - the public interface endpoint will be converted into v2.0 endpoints. - """ - region_id = self._region_create() - - # create v3 endpoints with three interfaces - body = { - 'endpoint': unit.new_endpoint_ref(self.service_id, - region_id=region_id) - } - for interface in catalog.controllers.INTERFACES: - body['endpoint']['interface'] = interface - self.admin_request(method='POST', - token=self.get_scoped_token(), - path='/v3/endpoints', - expected_status=http_client.CREATED, - body=body) - - r = self.admin_request(token=self.get_scoped_token(), - path='/v2.0/endpoints') - # Endpoints of the service which have a public interface endpoint - # will be returned via v2.0 API - self.assertEqual(1, len(r.result['endpoints'])) - v2_endpoint = r.result['endpoints'][0] - self.assertEqual(self.service_id, v2_endpoint['service_id']) - # This is not the focus of this test, so no different urls are used. - self.assertEqual(body['endpoint']['url'], v2_endpoint['publicurl']) - self.assertEqual(body['endpoint']['url'], v2_endpoint['adminurl']) - self.assertEqual(body['endpoint']['url'], v2_endpoint['internalurl']) - self.assertNotIn('name', v2_endpoint) - - v3_endpoint = self.catalog_api.get_endpoint(v2_endpoint['id']) - # Checks the v3 public endpoint's id is the generated v2.0 endpoint - self.assertEqual('public', v3_endpoint['interface']) - self.assertEqual(self.service_id, v3_endpoint['service_id']) - - def test_pure_v3_endpoint_without_publicurl_invisible_from_v2(self): - """Test that the v2.0 API can't fetch v3 endpoints without publicURLs. - - v2.0 API will return endpoints created by v3 API, but publicURL is - required for the service in the v2.0 API, therefore v3 endpoints of - a service which don't have publicURL will be ignored. - """ - region_id = self._region_create() - - # create a v3 endpoint without public interface - body = { - 'endpoint': unit.new_endpoint_ref(self.service_id, - region_id=region_id) - } - for interface in catalog.controllers.INTERFACES: - if interface == 'public': - continue - body['endpoint']['interface'] = interface - self.admin_request(method='POST', - token=self.get_scoped_token(), - path='/v3/endpoints', - expected_status=http_client.CREATED, - body=body) - - r = self.admin_request(token=self.get_scoped_token(), - path='/v2.0/endpoints') - # v3 endpoints of a service which don't have publicURL can't be - # fetched via v2.0 API - self.assertEqual(0, len(r.result['endpoints'])) - - def test_endpoint_create_with_null_adminurl(self): - req_body, response = self._endpoint_create(adminurl=None) - self.assertIsNone(req_body['endpoint']['adminurl']) - self.assertNotIn('adminurl', response.result['endpoint']) - - def test_endpoint_create_with_empty_adminurl(self): - req_body, response = self._endpoint_create(adminurl='') - self.assertEqual('', req_body['endpoint']['adminurl']) - self.assertNotIn("adminurl", response.result['endpoint']) - - def test_endpoint_create_with_null_internalurl(self): - req_body, response = self._endpoint_create(internalurl=None) - self.assertIsNone(req_body['endpoint']['internalurl']) - self.assertNotIn('internalurl', response.result['endpoint']) - - def test_endpoint_create_with_empty_internalurl(self): - req_body, response = self._endpoint_create(internalurl='') - self.assertEqual('', req_body['endpoint']['internalurl']) - self.assertNotIn("internalurl", response.result['endpoint']) - - def test_endpoint_create_with_null_publicurl(self): - self._endpoint_create(expected_status=http_client.BAD_REQUEST, - publicurl=None) - - def test_endpoint_create_with_empty_publicurl(self): - self._endpoint_create(expected_status=http_client.BAD_REQUEST, - publicurl='') - - def test_endpoint_create_with_null_service_id(self): - self._endpoint_create(expected_status=http_client.BAD_REQUEST, - service_id=None) - - def test_endpoint_create_with_empty_service_id(self): - self._endpoint_create(expected_status=http_client.BAD_REQUEST, - service_id='') - - def test_endpoint_create_with_valid_url(self): - """Create endpoint with valid URL should be tested, too.""" - # list one valid url is enough, no need to list too much - valid_url = 'http://127.0.0.1:8774/v1.1/$(tenant_id)s' - - # baseline tests that all valid URLs works - self._endpoint_create(expected_status=http_client.OK, - publicurl=valid_url, - internalurl=valid_url, - adminurl=valid_url) - - def test_endpoint_create_with_invalid_url(self): - """Test the invalid cases: substitutions is not exactly right.""" - invalid_urls = [ - # using a substitution that is not whitelisted - KeyError - 'http://127.0.0.1:8774/v1.1/$(nonexistent)s', - - # invalid formatting - ValueError - 'http://127.0.0.1:8774/v1.1/$(project_id)', - 'http://127.0.0.1:8774/v1.1/$(project_id)t', - 'http://127.0.0.1:8774/v1.1/$(project_id', - - # invalid type specifier - TypeError - # admin_url is a string not an int - 'http://127.0.0.1:8774/v1.1/$(admin_url)d', - ] - - # list one valid url is enough, no need to list too much - valid_url = 'http://127.0.0.1:8774/v1.1/$(project_id)s' - - # Case one: publicurl, internalurl and adminurl are - # all invalid - for invalid_url in invalid_urls: - self._endpoint_create(expected_status=http_client.BAD_REQUEST, - publicurl=invalid_url, - internalurl=invalid_url, - adminurl=invalid_url) - - # Case two: publicurl, internalurl are invalid - # and adminurl is valid - for invalid_url in invalid_urls: - self._endpoint_create(expected_status=http_client.BAD_REQUEST, - publicurl=invalid_url, - internalurl=invalid_url, - adminurl=valid_url) - - # Case three: publicurl, adminurl are invalid - # and internalurl is valid - for invalid_url in invalid_urls: - self._endpoint_create(expected_status=http_client.BAD_REQUEST, - publicurl=invalid_url, - internalurl=valid_url, - adminurl=invalid_url) - - # Case four: internalurl, adminurl are invalid - # and publicurl is valid - for invalid_url in invalid_urls: - self._endpoint_create(expected_status=http_client.BAD_REQUEST, - publicurl=valid_url, - internalurl=invalid_url, - adminurl=invalid_url) - - # Case five: publicurl is invalid, internalurl - # and adminurl are valid - for invalid_url in invalid_urls: - self._endpoint_create(expected_status=http_client.BAD_REQUEST, - publicurl=invalid_url, - internalurl=valid_url, - adminurl=valid_url) - - # Case six: internalurl is invalid, publicurl - # and adminurl are valid - for invalid_url in invalid_urls: - self._endpoint_create(expected_status=http_client.BAD_REQUEST, - publicurl=valid_url, - internalurl=invalid_url, - adminurl=valid_url) - - # Case seven: adminurl is invalid, publicurl - # and internalurl are valid - for invalid_url in invalid_urls: - self._endpoint_create(expected_status=http_client.BAD_REQUEST, - publicurl=valid_url, - internalurl=valid_url, - adminurl=invalid_url) - - -class TestV2CatalogAPISQL(unit.TestCase): - - def setUp(self): - super(TestV2CatalogAPISQL, self).setUp() - self.useFixture(database.Database()) - self.catalog_api = catalog.Manager() - - service = unit.new_service_ref() - self.service_id = service['id'] - self.catalog_api.create_service(self.service_id, service) - - self.create_endpoint(service_id=self.service_id) - - def create_endpoint(self, service_id, **kwargs): - endpoint = unit.new_endpoint_ref(service_id=service_id, - region_id=None, - **kwargs) - self.catalog_api.create_endpoint(endpoint['id'], endpoint) - return endpoint - - def config_overrides(self): - super(TestV2CatalogAPISQL, self).config_overrides() - self.config_fixture.config(group='catalog', driver='sql') - - def test_get_catalog_ignores_endpoints_with_invalid_urls(self): - user_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - - # the only endpoint in the catalog is the one created in setUp - catalog = self.catalog_api.get_catalog(user_id, project_id) - self.assertEqual(1, len(catalog)) - # it's also the only endpoint in the backend - self.assertEqual(1, len(self.catalog_api.list_endpoints())) - - # create a new, invalid endpoint - malformed type declaration - self.create_endpoint(self.service_id, - url='http://keystone/%(project_id)') - - # create a new, invalid endpoint - nonexistent key - self.create_endpoint(self.service_id, - url='http://keystone/%(you_wont_find_me)s') - - # verify that the invalid endpoints don't appear in the catalog - catalog = self.catalog_api.get_catalog(user_id, project_id) - self.assertEqual(1, len(catalog)) - # all three endpoints appear in the backend - self.assertEqual(3, len(self.catalog_api.list_endpoints())) - - def test_get_catalog_always_returns_service_name(self): - user_id = uuid.uuid4().hex - project_id = uuid.uuid4().hex - - # new_service_ref() returns a ref with a `name`. - named_svc = unit.new_service_ref() - self.catalog_api.create_service(named_svc['id'], named_svc) - self.create_endpoint(service_id=named_svc['id']) - - # This time manually delete the generated `name`. - unnamed_svc = unit.new_service_ref() - del unnamed_svc['name'] - self.catalog_api.create_service(unnamed_svc['id'], unnamed_svc) - self.create_endpoint(service_id=unnamed_svc['id']) - - region = None - catalog = self.catalog_api.get_catalog(user_id, project_id) - - self.assertEqual(named_svc['name'], - catalog[region][named_svc['type']]['name']) - - # verify a name is not generated when the service is passed to the API - self.assertEqual('', catalog[region][unnamed_svc['type']]['name']) diff --git a/keystone/tests/unit/test_v2.py b/keystone/tests/unit/test_v2.py index 018a92b404..fe66e89c33 100644 --- a/keystone/tests/unit/test_v2.py +++ b/keystone/tests/unit/test_v2.py @@ -385,27 +385,6 @@ class CoreApiTests(object): self.public_request(path='/v2.0/tenants', expected_status=http_client.UNAUTHORIZED) - def test_invalid_parameter_error_response(self): - token = self.get_scoped_token() - bad_body = { - 'OS-KSADM:service%s' % uuid.uuid4().hex: { - 'name': uuid.uuid4().hex, - 'type': uuid.uuid4().hex, - }, - } - res = self.admin_request(method='POST', - path='/v2.0/OS-KSADM/services', - body=bad_body, - token=token, - expected_status=http_client.BAD_REQUEST) - self.assertValidErrorResponse(res) - res = self.admin_request(method='POST', - path='/v2.0/users', - body=bad_body, - token=token, - expected_status=http_client.BAD_REQUEST) - self.assertValidErrorResponse(res) - def _get_user_id(self, r): """Helper method to return user ID from a response. @@ -1158,39 +1137,6 @@ class V2TestCase(object): def get_user_attribute_from_response(self, r, attribute_name): return r.result['user'][attribute_name] - def test_service_crud_requires_auth(self): - """Service CRUD should return unauthorized without an X-Auth-Token.""" - # values here don't matter because it will be unauthorized before - # they're checked (bug 1006822). - service_path = '/v2.0/OS-KSADM/services/%s' % uuid.uuid4().hex - service_body = { - 'OS-KSADM:service': { - 'name': uuid.uuid4().hex, - 'type': uuid.uuid4().hex, - }, - } - - r = self.admin_request(method='GET', - path='/v2.0/OS-KSADM/services', - expected_status=http_client.UNAUTHORIZED) - self.assertValidErrorResponse(r) - - r = self.admin_request(method='POST', - path='/v2.0/OS-KSADM/services', - body=service_body, - expected_status=http_client.UNAUTHORIZED) - self.assertValidErrorResponse(r) - - r = self.admin_request(method='GET', - path=service_path, - expected_status=http_client.UNAUTHORIZED) - self.assertValidErrorResponse(r) - - r = self.admin_request(method='DELETE', - path=service_path, - expected_status=http_client.UNAUTHORIZED) - self.assertValidErrorResponse(r) - def test_user_role_list_requires_auth(self): """User role list return unauthorized without an X-Auth-Token.""" # values here don't matter because it will be unauthorized before diff --git a/keystone/tests/unit/test_v3_catalog.py b/keystone/tests/unit/test_v3_catalog.py index d40e280143..0026fbedeb 100644 --- a/keystone/tests/unit/test_v3_catalog.py +++ b/keystone/tests/unit/test_v3_catalog.py @@ -677,58 +677,6 @@ class CatalogTestCase(test_v3.RestfulTestCase): '/endpoints/%(endpoint_id)s' % { 'endpoint_id': self.endpoint_id}) - def test_create_endpoint_on_v2(self): - # clear the v3 endpoint so we only have endpoints created on v2 - self.delete( - '/endpoints/%(endpoint_id)s' % { - 'endpoint_id': self.endpoint_id}) - - # create a v3 endpoint ref, and then tweak it back to a v2-style ref - ref = unit.new_endpoint_ref_with_region(service_id=self.service['id'], - region=uuid.uuid4().hex, - internalurl=None) - del ref['id'] - del ref['interface'] - ref['publicurl'] = ref.pop('url') - # don't set adminurl to ensure it's absence is handled like internalurl - - # create the endpoint on v2 (using a v3 token) - r = self.admin_request( - method='POST', - path='/v2.0/endpoints', - token=self.get_scoped_token(), - body={'endpoint': ref}) - endpoint_v2 = r.result['endpoint'] - - # test the endpoint on v3 - r = self.get('/endpoints') - endpoints = self.assertValidEndpointListResponse(r) - self.assertEqual(1, len(endpoints)) - endpoint_v3 = endpoints.pop() - - # these attributes are identical between both APIs - self.assertEqual(ref['region'], endpoint_v3['region_id']) - self.assertEqual(ref['service_id'], endpoint_v3['service_id']) - self.assertEqual(ref['description'], endpoint_v3['description']) - - # a v2 endpoint is not quite the same concept as a v3 endpoint, so they - # receive different identifiers - self.assertNotEqual(endpoint_v2['id'], endpoint_v3['id']) - - # v2 has a publicurl; v3 has a url + interface type - self.assertEqual(ref['publicurl'], endpoint_v3['url']) - self.assertEqual('public', endpoint_v3['interface']) - - # tests for bug 1152632 -- these attributes were being returned by v3 - self.assertNotIn('publicurl', endpoint_v3) - self.assertNotIn('adminurl', endpoint_v3) - self.assertNotIn('internalurl', endpoint_v3) - - # test for bug 1152635 -- this attribute was being returned by v3 - self.assertNotIn('legacy_endpoint_id', endpoint_v3) - - self.assertEqual(endpoint_v2['region'], endpoint_v3['region_id']) - def test_deleting_endpoint_with_space_in_url(self): # add a space to all urls (intentional "i d" to test bug) url_with_space = "http://127.0.0.1:8774 /v1.1/\$(tenant_i d)s" diff --git a/keystone/v2_crud/admin_crud.py b/keystone/v2_crud/admin_crud.py index d076f85f88..b539e78bce 100644 --- a/keystone/v2_crud/admin_crud.py +++ b/keystone/v2_crud/admin_crud.py @@ -13,7 +13,6 @@ # under the License. from keystone import assignment -from keystone import catalog from keystone.common import extension from keystone.common import wsgi from keystone import identity @@ -53,8 +52,6 @@ class Router(wsgi.ComposableRouter): user_controller = identity.controllers.User() role_controller = assignment.controllers.Role() assignment_role_controller = assignment.controllers.RoleAssignmentV2() - service_controller = catalog.controllers.Service() - endpoint_controller = catalog.controllers.Endpoint() # Tenant Operations mapper.connect( @@ -178,45 +175,6 @@ class Router(wsgi.ComposableRouter): action='remove_role_from_user', conditions=dict(method=['DELETE'])) - # Service Operations - mapper.connect( - '/OS-KSADM/services', - controller=service_controller, - action='get_services', - conditions=dict(method=['GET'])) - mapper.connect( - '/OS-KSADM/services', - controller=service_controller, - action='create_service', - conditions=dict(method=['POST'])) - mapper.connect( - '/OS-KSADM/services/{service_id}', - controller=service_controller, - action='delete_service', - conditions=dict(method=['DELETE'])) - mapper.connect( - '/OS-KSADM/services/{service_id}', - controller=service_controller, - action='get_service', - conditions=dict(method=['GET'])) - - # Endpoint Templates - mapper.connect( - '/endpoints', - controller=endpoint_controller, - action='get_endpoints', - conditions=dict(method=['GET'])) - mapper.connect( - '/endpoints', - controller=endpoint_controller, - action='create_endpoint', - conditions=dict(method=['POST'])) - mapper.connect( - '/endpoints/{endpoint_id}', - controller=endpoint_controller, - action='delete_endpoint', - conditions=dict(method=['DELETE'])) - # Role Operations mapper.connect( '/OS-KSADM/roles',