Merge "Add Admin API and add extensions"
This commit is contained in:
commit
3ea4b30971
@ -55,7 +55,8 @@ DESIGNATE_SERVICE_PORT_MDNS=${DESIGNATE_SERVICE_PORT_MDNS:-5354}
|
|||||||
DESIGNATE_TEST_NSREC=${DESIGNATE_TEST_NSREC:-ns1.devstack.org.}
|
DESIGNATE_TEST_NSREC=${DESIGNATE_TEST_NSREC:-ns1.devstack.org.}
|
||||||
|
|
||||||
DESIGNATE_ENABLED_EXTENSIONS_V1=${DESIGNATE_ENABLED_EXTENSIONS_V1:-"quotas"}
|
DESIGNATE_ENABLED_EXTENSIONS_V1=${DESIGNATE_ENABLED_EXTENSIONS_V1:-"quotas"}
|
||||||
DESIGNATE_ENABLED_EXTENSIONS_V2=${DESIGNATE_ENABLED_EXTENSIONS_V2:-"quotas"}
|
DESIGNATE_ENABLED_EXTENSIONS_V2=${DESIGNATE_ENABLED_EXTENSIONS_V2:-""}
|
||||||
|
DESIGNATE_ENABLED_EXTENSIONS_ADMIN=${DESIGNATE_ENABLED_EXTENSIONS_ADMIN:-"quotas"}
|
||||||
|
|
||||||
# Tell Tempest this project is present
|
# Tell Tempest this project is present
|
||||||
TEMPEST_SERVICES+=,designate
|
TEMPEST_SERVICES+=,designate
|
||||||
@ -113,6 +114,7 @@ function configure_designate {
|
|||||||
iniset $DESIGNATE_CONF pool_manager_cache:sqlalchemy connection `database_connection_url designate_pool_manager`
|
iniset $DESIGNATE_CONF pool_manager_cache:sqlalchemy connection `database_connection_url designate_pool_manager`
|
||||||
iniset $DESIGNATE_CONF service:api enabled_extensions_v1 $DESIGNATE_ENABLED_EXTENSIONS_V1
|
iniset $DESIGNATE_CONF service:api enabled_extensions_v1 $DESIGNATE_ENABLED_EXTENSIONS_V1
|
||||||
iniset $DESIGNATE_CONF service:api enabled_extensions_v2 $DESIGNATE_ENABLED_EXTENSIONS_V2
|
iniset $DESIGNATE_CONF service:api enabled_extensions_v2 $DESIGNATE_ENABLED_EXTENSIONS_V2
|
||||||
|
iniset $DESIGNATE_CONF service:api enabled_extensions_admin $DESIGNATE_ENABLED_EXTENSIONS_ADMIN
|
||||||
|
|
||||||
sudo cp $DESIGNATE_DIR/etc/designate/rootwrap.conf.sample $DESIGNATE_ROOTWRAP_CONF
|
sudo cp $DESIGNATE_DIR/etc/designate/rootwrap.conf.sample $DESIGNATE_ROOTWRAP_CONF
|
||||||
iniset $DESIGNATE_ROOTWRAP_CONF DEFAULT filters_path $DESIGNATE_DIR/etc/designate/rootwrap.d root-helper
|
iniset $DESIGNATE_ROOTWRAP_CONF DEFAULT filters_path $DESIGNATE_DIR/etc/designate/rootwrap.d root-helper
|
||||||
@ -146,6 +148,7 @@ function configure_designate {
|
|||||||
iniset $DESIGNATE_CONF service:api api_base_uri $DESIGNATE_SERVICE_PROTOCOL://$DESIGNATE_SERVICE_HOST:$DESIGNATE_SERVICE_PORT/
|
iniset $DESIGNATE_CONF service:api api_base_uri $DESIGNATE_SERVICE_PROTOCOL://$DESIGNATE_SERVICE_HOST:$DESIGNATE_SERVICE_PORT/
|
||||||
iniset $DESIGNATE_CONF service:api enable_api_v1 True
|
iniset $DESIGNATE_CONF service:api enable_api_v1 True
|
||||||
iniset $DESIGNATE_CONF service:api enable_api_v2 True
|
iniset $DESIGNATE_CONF service:api enable_api_v2 True
|
||||||
|
iniset $DESIGNATE_CONF service:api enable_api_admin True
|
||||||
if is_service_enabled tls-proxy; then
|
if is_service_enabled tls-proxy; then
|
||||||
# Set the service port for a proxy to take the original
|
# Set the service port for a proxy to take the original
|
||||||
iniset $DESIGNATE_CONF service:api api_port $DESIGNATE_SERVICE_PORT_INT
|
iniset $DESIGNATE_CONF service:api api_port $DESIGNATE_SERVICE_PORT_INT
|
||||||
|
@ -35,4 +35,5 @@ cfg.CONF.register_opts([
|
|||||||
'keystone'),
|
'keystone'),
|
||||||
cfg.BoolOpt('enable-api-v1', default=True),
|
cfg.BoolOpt('enable-api-v1', default=True),
|
||||||
cfg.BoolOpt('enable-api-v2', default=False),
|
cfg.BoolOpt('enable-api-v2', default=False),
|
||||||
|
cfg.BoolOpt('enable-api-admin', default=False),
|
||||||
], group='service:api')
|
], group='service:api')
|
||||||
|
52
designate/api/admin/__init__.py
Normal file
52
designate/api/admin/__init__.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# Copyright (c) 2014 Rackspace Hosting
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# 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 pecan.deploy
|
||||||
|
from oslo.config import cfg
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
OPTS = [
|
||||||
|
cfg.ListOpt('enabled-extensions-admin', default=[],
|
||||||
|
help='Enabled Admin API Extensions'),
|
||||||
|
]
|
||||||
|
|
||||||
|
cfg.CONF.register_opts(OPTS, group='service:api')
|
||||||
|
|
||||||
|
|
||||||
|
def factory(global_config, **local_conf):
|
||||||
|
if not cfg.CONF['service:api'].enable_api_admin:
|
||||||
|
def disabled_app(environ, start_response):
|
||||||
|
status = '404 Not Found'
|
||||||
|
start_response(status, [])
|
||||||
|
return []
|
||||||
|
|
||||||
|
return disabled_app
|
||||||
|
|
||||||
|
conf = {
|
||||||
|
'app': {
|
||||||
|
'root': 'designate.api.admin.controllers.root.RootController',
|
||||||
|
'modules': ['designate.api.admin'],
|
||||||
|
'errors': {
|
||||||
|
404: '/errors/not_found',
|
||||||
|
405: '/errors/method_not_allowed',
|
||||||
|
'__force_dict__': True
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
app = pecan.deploy.deploy(conf)
|
||||||
|
|
||||||
|
return app
|
46
designate/api/admin/app.py
Normal file
46
designate/api/admin/app.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# Copyright 2013 Hewlett-Packard Development Company, L.P.
|
||||||
|
#
|
||||||
|
# Author: Kiall Mac Innes <kiall@hp.com>
|
||||||
|
#
|
||||||
|
# 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 pecan
|
||||||
|
import pecan.deploy
|
||||||
|
from oslo.config import cfg
|
||||||
|
from oslo_log import log as logging
|
||||||
|
|
||||||
|
from designate.api.v2 import patches
|
||||||
|
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
cfg.CONF.register_opts([
|
||||||
|
cfg.BoolOpt('pecan_debug', default=False,
|
||||||
|
help='Pecan HTML Debug Interface'),
|
||||||
|
], group='service:api')
|
||||||
|
|
||||||
|
|
||||||
|
def setup_app(pecan_config):
|
||||||
|
config = dict(pecan_config)
|
||||||
|
|
||||||
|
config['app']['debug'] = cfg.CONF['service:api'].pecan_debug
|
||||||
|
|
||||||
|
pecan.configuration.set_config(config, overwrite=True)
|
||||||
|
|
||||||
|
app = pecan.make_app(
|
||||||
|
pecan_config.app.root,
|
||||||
|
debug=getattr(pecan_config.app, 'debug', False),
|
||||||
|
force_canonical=getattr(pecan_config.app, 'force_canonical', True),
|
||||||
|
request_cls=patches.Request
|
||||||
|
)
|
||||||
|
|
||||||
|
return app
|
@ -18,7 +18,7 @@ import pecan
|
|||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from designate.api.v2.controllers import rest
|
from designate.api.v2.controllers import rest
|
||||||
from designate.api.v2.views.extensions import reports as reports_view
|
from designate.api.admin.views.extensions import reports as reports_view
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
@ -18,7 +18,7 @@ from oslo_log import log as logging
|
|||||||
|
|
||||||
from designate import schema
|
from designate import schema
|
||||||
from designate.api.v2.controllers import rest
|
from designate.api.v2.controllers import rest
|
||||||
from designate.api.v2.views.extensions import quotas as quotas_view
|
from designate.api.admin.views.extensions import quotas as quotas_view
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
@ -17,8 +17,8 @@
|
|||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from designate.api.v2.controllers import rest
|
from designate.api.v2.controllers import rest
|
||||||
from designate.api.v2.controllers.extensions import counts
|
from designate.api.admin.controllers.extensions import counts
|
||||||
from designate.api.v2.controllers.extensions import tenants
|
from designate.api.admin.controllers.extensions import tenants
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
@ -18,7 +18,7 @@ import pecan
|
|||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from designate.api.v2.controllers import rest
|
from designate.api.v2.controllers import rest
|
||||||
from designate.api.v2.views.extensions import reports as reports_view
|
from designate.api.admin.views.extensions import reports as reports_view
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
46
designate/api/admin/controllers/root.py
Normal file
46
designate/api/admin/controllers/root.py
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
# Copyright (c) 2014 Rackspace Hosting
|
||||||
|
# All Rights Reserved.
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
from oslo.config import cfg
|
||||||
|
from oslo_log import log as logging
|
||||||
|
from stevedore import named
|
||||||
|
|
||||||
|
from designate.api.v2.controllers import errors
|
||||||
|
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class RootController(object):
|
||||||
|
"""
|
||||||
|
This is /admin/ Controller. Pecan will find all controllers via the object
|
||||||
|
properties attached to this.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
enabled_ext = cfg.CONF['service:api'].enabled_extensions_admin
|
||||||
|
if len(enabled_ext) > 0:
|
||||||
|
self._mgr = named.NamedExtensionManager(
|
||||||
|
namespace='designate.api.admin.extensions',
|
||||||
|
names=enabled_ext,
|
||||||
|
invoke_on_load=True)
|
||||||
|
for ext in self._mgr:
|
||||||
|
controller = self
|
||||||
|
path = ext.obj.get_path()
|
||||||
|
for p in path.split('.')[:-1]:
|
||||||
|
if p != '':
|
||||||
|
controller = getattr(controller, p)
|
||||||
|
setattr(controller, path.split('.')[-1], ext.obj)
|
||||||
|
|
||||||
|
errors = errors.ErrorsController()
|
0
designate/api/admin/views/extensions/__init__.py
Normal file
0
designate/api/admin/views/extensions/__init__.py
Normal file
@ -25,14 +25,24 @@ def factory(global_config, **local_conf):
|
|||||||
base = cfg.CONF['service:api'].api_base_uri.rstrip('/')
|
base = cfg.CONF['service:api'].api_base_uri.rstrip('/')
|
||||||
|
|
||||||
def _version(version, status):
|
def _version(version, status):
|
||||||
versions.append({
|
if version.isdigit():
|
||||||
'id': 'v%s' % version,
|
versions.append({
|
||||||
'status': status,
|
'id': 'v%s' % version,
|
||||||
'links': [{
|
'status': status,
|
||||||
'href': base + '/v' + version,
|
'links': [{
|
||||||
'rel': 'self'
|
'href': base + '/v' + version,
|
||||||
}]
|
'rel': 'self'
|
||||||
})
|
}]
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
versions.append({
|
||||||
|
'id': '%s' % version,
|
||||||
|
'status': status,
|
||||||
|
'links': [{
|
||||||
|
'href': base + '/' + version,
|
||||||
|
'rel': 'self'
|
||||||
|
}]
|
||||||
|
})
|
||||||
|
|
||||||
if cfg.CONF['service:api'].enable_api_v1:
|
if cfg.CONF['service:api'].enable_api_v1:
|
||||||
_version('1', 'CURRENT')
|
_version('1', 'CURRENT')
|
||||||
|
@ -34,7 +34,7 @@ class Schema(object):
|
|||||||
self.validator = validators.Draft3Validator(
|
self.validator = validators.Draft3Validator(
|
||||||
self.raw_schema, resolver=self.resolver,
|
self.raw_schema, resolver=self.resolver,
|
||||||
format_checker=format.draft3_format_checker)
|
format_checker=format.draft3_format_checker)
|
||||||
elif version == 'v2':
|
elif version in ['v2', 'admin']:
|
||||||
self.validator = validators.Draft4Validator(
|
self.validator = validators.Draft4Validator(
|
||||||
self.raw_schema, resolver=self.resolver,
|
self.raw_schema, resolver=self.resolver,
|
||||||
format_checker=format.draft4_format_checker)
|
format_checker=format.draft4_format_checker)
|
||||||
|
150
designate/tests/test_api/test_admin/__init__.py
Normal file
150
designate/tests/test_api/test_admin/__init__.py
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
# Copyright 2013 Hewlett-Packard Development Company, L.P.
|
||||||
|
#
|
||||||
|
# Author: Kiall Mac Innes <kiall@managedit.ie>
|
||||||
|
#
|
||||||
|
# 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 itertools
|
||||||
|
|
||||||
|
from oslo_log import log as logging
|
||||||
|
from webtest import TestApp
|
||||||
|
|
||||||
|
from designate.api import admin as admin_api
|
||||||
|
from designate.api import middleware
|
||||||
|
from designate.tests.test_api import ApiTestCase
|
||||||
|
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
INVALID_ID = [
|
||||||
|
'2fdadfb1-cf96-4259-ac6b-bb7b6d2ff98g',
|
||||||
|
'2fdadfb1cf964259ac6bbb7b6d2ff9GG',
|
||||||
|
'12345'
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class AdminApiTestCase(ApiTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
super(AdminApiTestCase, self).setUp()
|
||||||
|
|
||||||
|
# Ensure the v2 API is enabled
|
||||||
|
self.config(enable_api_admin=True, group='service:api')
|
||||||
|
|
||||||
|
# Create the application
|
||||||
|
self.app = admin_api.factory({})
|
||||||
|
|
||||||
|
# Inject the NormalizeURIMiddleware middleware
|
||||||
|
self.app = middleware.NormalizeURIMiddleware(self.app)
|
||||||
|
|
||||||
|
# Inject the FaultWrapper middleware
|
||||||
|
self.app = middleware.FaultWrapperMiddleware(self.app)
|
||||||
|
|
||||||
|
# Inject the TestContext middleware
|
||||||
|
self.app = middleware.TestContextMiddleware(
|
||||||
|
self.app, self.admin_context.tenant,
|
||||||
|
self.admin_context.tenant)
|
||||||
|
|
||||||
|
# Obtain a test client
|
||||||
|
self.client = TestApp(self.app)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
self.app = None
|
||||||
|
self.client = None
|
||||||
|
|
||||||
|
super(AdminApiTestCase, self).tearDown()
|
||||||
|
|
||||||
|
def _assert_invalid_uuid(self, method, url_format, *args, **kw):
|
||||||
|
"""
|
||||||
|
Test that UUIDs used in the URL is valid.
|
||||||
|
"""
|
||||||
|
count = url_format.count('%s')
|
||||||
|
for i in itertools.product(INVALID_ID, repeat=count):
|
||||||
|
self._assert_exception('invalid_uuid', 400, method, url_format % i)
|
||||||
|
|
||||||
|
def _assert_exception(self, expected_type, expected_status, obj,
|
||||||
|
*args, **kwargs):
|
||||||
|
"""
|
||||||
|
Checks the response that a api call with a exception contains the
|
||||||
|
wanted data.
|
||||||
|
"""
|
||||||
|
kwargs.setdefault('status', expected_status)
|
||||||
|
|
||||||
|
response = obj(*args, **kwargs) if not hasattr(obj, 'json') else obj
|
||||||
|
|
||||||
|
self.assertEqual(expected_status, response.json['code'])
|
||||||
|
self.assertEqual(expected_type, response.json['type'])
|
||||||
|
|
||||||
|
def _assert_invalid_paging(self, data, url, key):
|
||||||
|
"""
|
||||||
|
Test that certain circumstances is invalid for paging in a given url.
|
||||||
|
"""
|
||||||
|
self._assert_paging(data, url, key=key,
|
||||||
|
limit='invalid_limit',
|
||||||
|
expected_type='invalid_limit',
|
||||||
|
expected_status=400)
|
||||||
|
|
||||||
|
self._assert_paging(data, url, key=key,
|
||||||
|
sort_dir='invalid_sort_dir',
|
||||||
|
expected_type='invalid_sort_dir',
|
||||||
|
expected_status=400)
|
||||||
|
|
||||||
|
self._assert_paging(data, url, key=key,
|
||||||
|
sort_key='invalid_sort_key',
|
||||||
|
expected_type='invalid_sort_key',
|
||||||
|
expected_status=400)
|
||||||
|
|
||||||
|
self._assert_paging(data, url, key=key,
|
||||||
|
marker='invalid_marker',
|
||||||
|
expected_type='invalid_marker',
|
||||||
|
expected_status=400)
|
||||||
|
|
||||||
|
def _assert_paging(self, data, url, key=None, limit=5, sort_dir='asc',
|
||||||
|
sort_key='created_at', marker=None,
|
||||||
|
expected_type=None, expected_status=200):
|
||||||
|
|
||||||
|
def _page(marker=None):
|
||||||
|
params = {'limit': limit,
|
||||||
|
'sort_dir': sort_dir,
|
||||||
|
'sort_key': sort_key}
|
||||||
|
|
||||||
|
if marker is not None:
|
||||||
|
params['marker'] = marker
|
||||||
|
|
||||||
|
r = self.client.get(url, params, status=expected_status)
|
||||||
|
if expected_status != 200:
|
||||||
|
if expected_type:
|
||||||
|
self._assert_exception(expected_type, expected_status, r)
|
||||||
|
return r
|
||||||
|
else:
|
||||||
|
return r.json[key] if key in r.json else r.json
|
||||||
|
|
||||||
|
response = _page(marker=marker)
|
||||||
|
if expected_status != 200:
|
||||||
|
if expected_type:
|
||||||
|
self._assert_exception(expected_type, expected_status,
|
||||||
|
response)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
x = 0
|
||||||
|
length = len(data)
|
||||||
|
for i in xrange(0, length):
|
||||||
|
assert data[i]['id'] == response[x]['id']
|
||||||
|
|
||||||
|
x += 1
|
||||||
|
# Don't bother getting a new page if we're at the last item
|
||||||
|
if x == len(response) and i != length - 1:
|
||||||
|
x = 0
|
||||||
|
response = _page(response[-1:][0]['id'])
|
||||||
|
|
||||||
|
_page(marker=response[-1:][0]['id'])
|
@ -16,16 +16,16 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
|
|
||||||
from designate.tests.test_api.test_v2 import ApiV2TestCase
|
from designate.tests.test_api.test_admin import AdminApiTestCase
|
||||||
|
|
||||||
cfg.CONF.import_opt('enabled_extensions_v2', 'designate.api.v2',
|
cfg.CONF.import_opt('enabled_extensions_admin', 'designate.api.admin',
|
||||||
group='service:api')
|
group='service:api')
|
||||||
|
|
||||||
|
|
||||||
class ApiV2QuotasTest(ApiV2TestCase):
|
class AdminApiQuotasTest(AdminApiTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.config(enabled_extensions_v2=['quotas'], group='service:api')
|
self.config(enabled_extensions_admin=['quotas'], group='service:api')
|
||||||
super(ApiV2QuotasTest, self).setUp()
|
super(AdminApiQuotasTest, self).setUp()
|
||||||
|
|
||||||
def test_get_quotas(self):
|
def test_get_quotas(self):
|
||||||
self.policy({'get_quotas': '@'})
|
self.policy({'get_quotas': '@'})
|
@ -16,16 +16,16 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
|
|
||||||
from designate.tests.test_api.test_v2 import ApiV2TestCase
|
from designate.tests.test_api.test_admin import AdminApiTestCase
|
||||||
|
|
||||||
cfg.CONF.import_opt('enabled_extensions_v2', 'designate.api.v2',
|
cfg.CONF.import_opt('enabled_extensions_admin', 'designate.api.admin',
|
||||||
group='service:api')
|
group='service:api')
|
||||||
|
|
||||||
|
|
||||||
class ApiV2ReportsTest(ApiV2TestCase):
|
class AdminApiReportsTest(AdminApiTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.config(enabled_extensions_v2=['reports'], group='service:api')
|
self.config(enabled_extensions_admin=['reports'], group='service:api')
|
||||||
super(ApiV2ReportsTest, self).setUp()
|
super(AdminApiReportsTest, self).setUp()
|
||||||
|
|
||||||
def test_get_counts(self):
|
def test_get_counts(self):
|
||||||
self.policy({'count_tenants': '@'})
|
self.policy({'count_tenants': '@'})
|
@ -3,6 +3,7 @@ use = egg:Paste#urlmap
|
|||||||
/: osapi_dns_app_versions
|
/: osapi_dns_app_versions
|
||||||
/v1: osapi_dns_v1
|
/v1: osapi_dns_v1
|
||||||
/v2: osapi_dns_v2
|
/v2: osapi_dns_v2
|
||||||
|
/admin: osapi_dns_admin
|
||||||
|
|
||||||
[app:osapi_dns_app_versions]
|
[app:osapi_dns_app_versions]
|
||||||
paste.app_factory = designate.api.versions:factory
|
paste.app_factory = designate.api.versions:factory
|
||||||
@ -23,6 +24,14 @@ keystone = request_id faultwrapper validation_API_v2 authtoken keystonecontext m
|
|||||||
[app:osapi_dns_app_v2]
|
[app:osapi_dns_app_v2]
|
||||||
paste.app_factory = designate.api.v2:factory
|
paste.app_factory = designate.api.v2:factory
|
||||||
|
|
||||||
|
[composite:osapi_dns_admin]
|
||||||
|
use = call:designate.api.middleware:auth_pipeline_factory
|
||||||
|
noauth = request_id faultwrapper noauthcontext maintenance normalizeuri osapi_dns_app_admin
|
||||||
|
keystone = request_id faultwrapper authtoken keystonecontext maintenance normalizeuri osapi_dns_app_admin
|
||||||
|
|
||||||
|
[app:osapi_dns_app_admin]
|
||||||
|
paste.app_factory = designate.api.admin:factory
|
||||||
|
|
||||||
[filter:request_id]
|
[filter:request_id]
|
||||||
paste.filter_factory = oslo_middleware:RequestId.factory
|
paste.filter_factory = oslo_middleware:RequestId.factory
|
||||||
|
|
||||||
|
@ -84,6 +84,13 @@ debug = False
|
|||||||
# Enable Version 2 API (experimental)
|
# Enable Version 2 API (experimental)
|
||||||
#enable_api_v2 = False
|
#enable_api_v2 = False
|
||||||
|
|
||||||
|
# Enable Admin API (experimental)
|
||||||
|
#enable_api_admin = False
|
||||||
|
|
||||||
|
# Enabled Admin API extensions
|
||||||
|
# Can be one or more of : reports, quotas, counts, tenants
|
||||||
|
#enabled_extensions_admin =
|
||||||
|
|
||||||
# Show the pecan HTML based debug interface (v2 only)
|
# Show the pecan HTML based debug interface (v2 only)
|
||||||
# This is only useful for development, and WILL break python-designateclient
|
# This is only useful for development, and WILL break python-designateclient
|
||||||
# if an error occurs
|
# if an error occurs
|
||||||
@ -94,7 +101,7 @@ debug = False
|
|||||||
#enabled_extensions_v1 =
|
#enabled_extensions_v1 =
|
||||||
|
|
||||||
# Enabled API Version 2 extensions
|
# Enabled API Version 2 extensions
|
||||||
# Can be one or more of : reports, quotas
|
# Can be one or more of :
|
||||||
#enabled_extensions_v2 =
|
#enabled_extensions_v2 =
|
||||||
|
|
||||||
#-----------------------
|
#-----------------------
|
||||||
|
@ -24,7 +24,7 @@ class QuotasClient(object):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def quotas_uri(cls, tenant_id):
|
def quotas_uri(cls, tenant_id):
|
||||||
return "/v2/quotas/" + tenant_id
|
return "/admin/quotas/" + tenant_id
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def deserialize(cls, resp, body, model_type):
|
def deserialize(cls, resp, body, model_type):
|
||||||
|
@ -53,9 +53,9 @@ designate.api.v1.extensions =
|
|||||||
reports = designate.api.v1.extensions.reports:blueprint
|
reports = designate.api.v1.extensions.reports:blueprint
|
||||||
touch = designate.api.v1.extensions.touch:blueprint
|
touch = designate.api.v1.extensions.touch:blueprint
|
||||||
|
|
||||||
designate.api.v2.extensions =
|
designate.api.admin.extensions =
|
||||||
reports = designate.api.v2.controllers.extensions.reports:ReportsController
|
reports = designate.api.admin.controllers.extensions.reports:ReportsController
|
||||||
quotas = designate.api.v2.controllers.extensions.quotas:QuotasController
|
quotas = designate.api.admin.controllers.extensions.quotas:QuotasController
|
||||||
|
|
||||||
designate.storage =
|
designate.storage =
|
||||||
sqlalchemy = designate.storage.impl_sqlalchemy:SQLAlchemyStorage
|
sqlalchemy = designate.storage.impl_sqlalchemy:SQLAlchemyStorage
|
||||||
|
Loading…
Reference in New Issue
Block a user