Merge "Remove v2.0 service and endpoint APIs"

This commit is contained in:
Jenkins 2017-09-12 23:31:54 +00:00 committed by Gerrit Code Review
commit 2764b49bc2
12 changed files with 0 additions and 988 deletions

View File

@ -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

View File

@ -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

View File

@ -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
=============

View File

@ -1,8 +0,0 @@
{
"OS-KSADM:service": {
"id": "123",
"name": "nova",
"type": "compute",
"description": "OpenStack Compute Service"
}
}

View File

@ -1,8 +0,0 @@
{
"OS-KSADM:service": {
"id": "123",
"name": "nova",
"type": "compute",
"description": "OpenStack Compute Service"
}
}

View File

@ -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": []
}

View File

@ -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'

View File

@ -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(

View File

@ -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'])

View File

@ -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

View File

@ -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"

View File

@ -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',