Remove pastedeploy
This patchset removes the lingering code that supported paste.deploy that is obsolted by the loader wrapped around keystone's use of Flask. * The keystone-paste.ini file has been removed. * All options have been removed (without deprecation) as they are no longer referenced. * The TokenAuthMiddleware code (with deprecation warning) has been removed as it was only provided to ensure compatibility with paste.ini files that were not updated (ensuring not breaking a deployer that did not update paste.ini file to remove it from the pipeline). * Paste deploy entrypoints have been removed. Change-Id: I35064a440ef718f50c7e644e8b2d56a99c3ec74f
This commit is contained in:
parent
a11d6ca0eb
commit
8bf335bb01
doc/source/configuration/samples
etc
keystone
catalog/backends
common
conf
middleware
server
tests/unit
version
@ -9,6 +9,5 @@ found below:
|
|||||||
.. toctree::
|
.. toctree::
|
||||||
|
|
||||||
keystone-conf.rst
|
keystone-conf.rst
|
||||||
keystone-paste-ini.rst
|
|
||||||
logging-conf.rst
|
logging-conf.rst
|
||||||
policy-yaml.rst
|
policy-yaml.rst
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
==================
|
|
||||||
keystone-paste.ini
|
|
||||||
==================
|
|
||||||
|
|
||||||
Use the ``keystone-paste.ini`` file to configure the Web Service Gateway
|
|
||||||
Interface (WSGI) middleware pipeline for the Identity service:
|
|
||||||
|
|
||||||
.. literalinclude:: ../../../../etc/keystone-paste.ini
|
|
@ -1,3 +1,8 @@
|
|||||||
|
# !!! WARNING: THIS FILE IS NO LONGER USED. KEYSTONE IS LOADED DIRECTLY AND
|
||||||
|
# !!! WILL IGNORE THIS FILE. THIS FILE WILL BE REMOVED IN THE STEIN
|
||||||
|
# !!! RELEASE. IT IS BEING MAINTAINED TO EASE THE TRANSITION OF THE
|
||||||
|
# !!! DEPLOYMENT TOOLING IN THE WILD.
|
||||||
|
|
||||||
# Keystone PasteDeploy configuration file.
|
# Keystone PasteDeploy configuration file.
|
||||||
|
|
||||||
[filter:debug]
|
[filter:debug]
|
||||||
|
@ -64,8 +64,7 @@ class Catalog(base.CatalogDriverBase):
|
|||||||
|
|
||||||
and is stored in a similar looking hierarchy. Where a value can contain
|
and is stored in a similar looking hierarchy. Where a value can contain
|
||||||
values to be interpolated by standard python string interpolation that look
|
values to be interpolated by standard python string interpolation that look
|
||||||
like (the % is replaced by a $ due to paste attempting to interpolate on
|
like (the % is replaced by a $):
|
||||||
its own:
|
|
||||||
|
|
||||||
http://localhost:$(public_port)s/
|
http://localhost:$(public_port)s/
|
||||||
|
|
||||||
|
@ -136,27 +136,7 @@ class BaseApplication(object):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def factory(cls, global_config, **local_config):
|
def factory(cls, global_config, **local_config):
|
||||||
"""Used for paste app factories in paste.deploy config files.
|
"""Used for loading in middleware (holdover from paste.deploy)."""
|
||||||
|
|
||||||
Any local configuration (that is, values under the [app:APPNAME]
|
|
||||||
section of the paste config) will be passed into the `__init__` method
|
|
||||||
as kwargs.
|
|
||||||
|
|
||||||
A hypothetical configuration would look like:
|
|
||||||
|
|
||||||
[app:wadl]
|
|
||||||
latest_version = 1.3
|
|
||||||
paste.app_factory = keystone.fancy_api:Wadl.factory
|
|
||||||
|
|
||||||
which would result in a call to the `Wadl` class as
|
|
||||||
|
|
||||||
import keystone.fancy_api
|
|
||||||
keystone.fancy_api.Wadl(latest_version='1.3')
|
|
||||||
|
|
||||||
You could of course re-implement the `factory` method in subclasses,
|
|
||||||
but using the kwarg passing it shouldn't be necessary.
|
|
||||||
|
|
||||||
"""
|
|
||||||
return cls(**local_config)
|
return cls(**local_config)
|
||||||
|
|
||||||
def __call__(self, environ, start_response):
|
def __call__(self, environ, start_response):
|
||||||
@ -194,6 +174,11 @@ class BaseApplication(object):
|
|||||||
See the end of http://pythonpaste.org/webob/modules/dec.html
|
See the end of http://pythonpaste.org/webob/modules/dec.html
|
||||||
for more info.
|
for more info.
|
||||||
|
|
||||||
|
NOTE: this is now strictly used in conversion from old wsgi
|
||||||
|
implementation to flask. Once the flask implementation is complete,
|
||||||
|
the __call__ will not be needed as the flask app will handle
|
||||||
|
dispatching and __call__.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError('You must implement __call__')
|
raise NotImplementedError('You must implement __call__')
|
||||||
|
|
||||||
@ -566,27 +551,7 @@ class ExtensionRouter(Router):
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def factory(cls, global_config, **local_config):
|
def factory(cls, global_config, **local_config):
|
||||||
"""Used for paste app factories in paste.deploy config files.
|
"""Used for loading in middleware (holdover from paste.deploy)."""
|
||||||
|
|
||||||
Any local configuration (that is, values under the [filter:APPNAME]
|
|
||||||
section of the paste config) will be passed into the `__init__` method
|
|
||||||
as kwargs.
|
|
||||||
|
|
||||||
A hypothetical configuration would look like:
|
|
||||||
|
|
||||||
[filter:analytics]
|
|
||||||
redis_host = 127.0.0.1
|
|
||||||
paste.filter_factory = keystone.analytics:Analytics.factory
|
|
||||||
|
|
||||||
which would result in a call to the `Analytics` class as
|
|
||||||
|
|
||||||
import keystone.analytics
|
|
||||||
keystone.analytics.Analytics(app, redis_host='127.0.0.1')
|
|
||||||
|
|
||||||
You could of course re-implement the `factory` method in subclasses,
|
|
||||||
but using the kwarg passing it shouldn't be necessary.
|
|
||||||
|
|
||||||
"""
|
|
||||||
def _factory(app):
|
def _factory(app):
|
||||||
conf = global_config.copy()
|
conf = global_config.copy()
|
||||||
conf.update(local_config)
|
conf.update(local_config)
|
||||||
|
@ -36,7 +36,6 @@ from keystone.conf import identity_mapping
|
|||||||
from keystone.conf import ldap
|
from keystone.conf import ldap
|
||||||
from keystone.conf import memcache
|
from keystone.conf import memcache
|
||||||
from keystone.conf import oauth1
|
from keystone.conf import oauth1
|
||||||
from keystone.conf import paste_deploy
|
|
||||||
from keystone.conf import policy
|
from keystone.conf import policy
|
||||||
from keystone.conf import resource
|
from keystone.conf import resource
|
||||||
from keystone.conf import revoke
|
from keystone.conf import revoke
|
||||||
@ -72,7 +71,6 @@ conf_modules = [
|
|||||||
ldap,
|
ldap,
|
||||||
memcache,
|
memcache,
|
||||||
oauth1,
|
oauth1,
|
||||||
paste_deploy,
|
|
||||||
policy,
|
policy,
|
||||||
resource,
|
resource,
|
||||||
revoke,
|
revoke,
|
||||||
|
@ -1,40 +0,0 @@
|
|||||||
# 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 keystone.conf import utils
|
|
||||||
|
|
||||||
|
|
||||||
config_file = cfg.StrOpt(
|
|
||||||
'config_file',
|
|
||||||
default='keystone-paste.ini',
|
|
||||||
help=utils.fmt("""
|
|
||||||
Name of (or absolute path to) the Paste Deploy configuration file that composes
|
|
||||||
middleware and the keystone application itself into actual WSGI entry points.
|
|
||||||
See http://pythonpaste.org/deploy/ for additional documentation on the file's
|
|
||||||
format.
|
|
||||||
"""))
|
|
||||||
|
|
||||||
|
|
||||||
GROUP_NAME = __name__.split('.')[-1]
|
|
||||||
ALL_OPTS = [
|
|
||||||
config_file,
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def register_opts(conf):
|
|
||||||
conf.register_opts(ALL_OPTS, group=GROUP_NAME)
|
|
||||||
|
|
||||||
|
|
||||||
def list_opts():
|
|
||||||
return {GROUP_NAME: ALL_OPTS}
|
|
@ -249,27 +249,7 @@ class AuthContextMiddleware(provider_api.ProviderAPIMixin,
|
|||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def factory(cls, global_config, **local_config):
|
def factory(cls, global_config, **local_config):
|
||||||
"""Used for paste app factories in paste.deploy config files.
|
"""Used for loading in middleware (holdover from paste.deploy)."""
|
||||||
|
|
||||||
Any local configuration (that is, values under the [filter:APPNAME]
|
|
||||||
section of the paste config) will be passed into the `__init__` method
|
|
||||||
as kwargs.
|
|
||||||
|
|
||||||
A hypothetical configuration would look like:
|
|
||||||
|
|
||||||
[filter:analytics]
|
|
||||||
redis_host = 127.0.0.1
|
|
||||||
paste.filter_factory = keystone.analytics:Analytics.factory
|
|
||||||
|
|
||||||
which would result in a call to the `Analytics` class as
|
|
||||||
|
|
||||||
import keystone.analytics
|
|
||||||
keystone.analytics.Analytics(app, redis_host='127.0.0.1')
|
|
||||||
|
|
||||||
You could of course re-implement the `factory` method in subclasses,
|
|
||||||
but using the kwarg passing it shouldn't be necessary.
|
|
||||||
|
|
||||||
"""
|
|
||||||
def _factory(app):
|
def _factory(app):
|
||||||
conf = global_config.copy()
|
conf = global_config.copy()
|
||||||
conf.update(local_config)
|
conf.update(local_config)
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
from oslo_log import versionutils
|
|
||||||
from oslo_serialization import jsonutils
|
from oslo_serialization import jsonutils
|
||||||
|
|
||||||
from keystone.common import wsgi
|
from keystone.common import wsgi
|
||||||
@ -23,25 +22,6 @@ from keystone import exception
|
|||||||
LOG = log.getLogger(__name__)
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class TokenAuthMiddleware(wsgi.Middleware):
|
|
||||||
|
|
||||||
@versionutils.deprecated(
|
|
||||||
as_of=versionutils.deprecated.ROCKY,
|
|
||||||
what='TokenAuthMiddleware in the paste-ini pipeline.',
|
|
||||||
remove_in=+2)
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super(TokenAuthMiddleware, self).__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
LOG.warning('The token_auth middleware functionality has been '
|
|
||||||
'merged into the main auth middleware '
|
|
||||||
'(keystone.middleware.auth.AuthContextMiddleware). '
|
|
||||||
'The [filter:token_auth] block will need to be'
|
|
||||||
'removed from your paste ini file. Failure to'
|
|
||||||
'remove these elements from your paste ini file will '
|
|
||||||
'result in keystone to no longer start/run when the '
|
|
||||||
'`token_auth` is removed in the Stein release.')
|
|
||||||
|
|
||||||
|
|
||||||
class JsonBodyMiddleware(wsgi.Middleware):
|
class JsonBodyMiddleware(wsgi.Middleware):
|
||||||
"""Middleware to allow method arguments to be passed as serialized JSON.
|
"""Middleware to allow method arguments to be passed as serialized JSON.
|
||||||
|
|
||||||
|
@ -11,3 +11,10 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from keystone.server.flask.core import * # noqa
|
from keystone.server.flask.core import * # noqa
|
||||||
|
from keystone.server.flask import application # noqa
|
||||||
|
|
||||||
|
|
||||||
|
__all__ = ('application', 'core', 'fail_gracefully', 'initialize_application',
|
||||||
|
'setup_app_middleware')
|
||||||
|
|
||||||
|
fail_gracefully = application.fail_gracefully
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
# Copyright 2013 OpenStack Foundation
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# a copy of the License at
|
# a copy of the License at
|
||||||
@ -12,124 +10,21 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
import oslo_i18n
|
|
||||||
from oslo_log import log
|
|
||||||
|
|
||||||
# NOTE(dstanek): i18n.enable_lazy() must be called before
|
|
||||||
# keystone.i18n._() is called to ensure it has the desired lazy lookup
|
|
||||||
# behavior. This includes cases, like keystone.exceptions, where
|
|
||||||
# keystone.i18n._() is called at import time.
|
|
||||||
oslo_i18n.enable_lazy()
|
|
||||||
|
|
||||||
from keystone.common import profiler
|
|
||||||
import keystone.conf
|
|
||||||
from keystone import exception
|
|
||||||
from keystone.server import common
|
|
||||||
from keystone.server import flask as keystone_flask
|
from keystone.server import flask as keystone_flask
|
||||||
from keystone.version import service as keystone_service
|
from keystone.server.flask import core as flask_core
|
||||||
|
|
||||||
|
|
||||||
CONF = keystone.conf.CONF
|
|
||||||
|
|
||||||
|
|
||||||
def initialize_application(name,
|
|
||||||
post_log_configured_function=lambda: None,
|
|
||||||
config_files=None):
|
|
||||||
possible_topdir = os.path.normpath(os.path.join(
|
|
||||||
os.path.abspath(__file__),
|
|
||||||
os.pardir,
|
|
||||||
os.pardir,
|
|
||||||
os.pardir))
|
|
||||||
|
|
||||||
dev_conf = os.path.join(possible_topdir,
|
|
||||||
'etc',
|
|
||||||
'keystone.conf')
|
|
||||||
if not config_files:
|
|
||||||
config_files = None
|
|
||||||
if os.path.exists(dev_conf):
|
|
||||||
config_files = [dev_conf]
|
|
||||||
|
|
||||||
common.configure(config_files=config_files)
|
|
||||||
|
|
||||||
# Log the options used when starting if we're in debug mode...
|
|
||||||
if CONF.debug:
|
|
||||||
CONF.log_opt_values(log.getLogger(CONF.prog), log.DEBUG)
|
|
||||||
|
|
||||||
post_log_configured_function()
|
|
||||||
|
|
||||||
def loadapp():
|
|
||||||
return keystone_service.loadapp(
|
|
||||||
'config:%s' % find_paste_config(), name)
|
|
||||||
|
|
||||||
_unused, application = common.setup_backends(
|
|
||||||
startup_application_fn=loadapp)
|
|
||||||
|
|
||||||
# setup OSprofiler notifier and enable the profiling if that is configured
|
|
||||||
# in Keystone configuration file.
|
|
||||||
profiler.setup(name)
|
|
||||||
|
|
||||||
return application
|
|
||||||
|
|
||||||
|
|
||||||
def find_paste_config():
|
|
||||||
"""Find Keystone's paste.deploy configuration file.
|
|
||||||
|
|
||||||
Keystone's paste.deploy configuration file is specified in the
|
|
||||||
``[paste_deploy]`` section of the main Keystone configuration file,
|
|
||||||
``keystone.conf``.
|
|
||||||
|
|
||||||
For example::
|
|
||||||
|
|
||||||
[paste_deploy]
|
|
||||||
config_file = keystone-paste.ini
|
|
||||||
|
|
||||||
:returns: The selected configuration filename
|
|
||||||
:raises: exception.ConfigFileNotFound
|
|
||||||
|
|
||||||
"""
|
|
||||||
if CONF.paste_deploy.config_file:
|
|
||||||
paste_config = CONF.paste_deploy.config_file
|
|
||||||
paste_config_value = paste_config
|
|
||||||
if not os.path.isabs(paste_config):
|
|
||||||
paste_config = CONF.find_file(paste_config)
|
|
||||||
elif CONF.config_file:
|
|
||||||
paste_config = CONF.config_file[0]
|
|
||||||
paste_config_value = paste_config
|
|
||||||
else:
|
|
||||||
# this provides backwards compatibility for keystone.conf files that
|
|
||||||
# still have the entire paste configuration included, rather than just
|
|
||||||
# a [paste_deploy] configuration section referring to an external file
|
|
||||||
paste_config = CONF.find_file('keystone.conf')
|
|
||||||
paste_config_value = 'keystone.conf'
|
|
||||||
if not paste_config or not os.path.exists(paste_config):
|
|
||||||
raise exception.ConfigFileNotFound(config_file=paste_config_value)
|
|
||||||
return paste_config
|
|
||||||
|
|
||||||
|
|
||||||
def _get_config_files(env=None):
|
|
||||||
if env is None:
|
|
||||||
env = os.environ
|
|
||||||
|
|
||||||
dirname = env.get('OS_KEYSTONE_CONFIG_DIR', '').strip()
|
|
||||||
|
|
||||||
files = [s.strip() for s in
|
|
||||||
env.get('OS_KEYSTONE_CONFIG_FILES', '').split(';') if s.strip()]
|
|
||||||
|
|
||||||
if dirname:
|
|
||||||
if not files:
|
|
||||||
files = ['keystone.conf']
|
|
||||||
files = [os.path.join(dirname, fname) for fname in files]
|
|
||||||
|
|
||||||
return files
|
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE(morgan): While "_get_config_files" is present in the keystone_flask
|
||||||
|
# module, since it is considered "private", we are going to directly
|
||||||
|
# import core and call it directly, eventually keystone_flask will not
|
||||||
|
# export all the symbols from keystone.flask.core only specific ones that
|
||||||
|
# are meant for public consumption
|
||||||
def initialize_admin_application():
|
def initialize_admin_application():
|
||||||
return keystone_flask.initialize_application(
|
return keystone_flask.initialize_application(
|
||||||
name='admin', config_files=_get_config_files())
|
name='admin', config_files=flask_core._get_config_files())
|
||||||
|
|
||||||
|
|
||||||
def initialize_public_application():
|
def initialize_public_application():
|
||||||
return keystone_flask.initialize_application(
|
return keystone_flask.initialize_application(
|
||||||
name='public', config_files=_get_config_files())
|
name='public', config_files=flask_core._get_config_files())
|
||||||
|
@ -25,10 +25,10 @@ from keystone.common import utils as common_utils
|
|||||||
import keystone.conf
|
import keystone.conf
|
||||||
from keystone.credential.providers import fernet as credential_fernet
|
from keystone.credential.providers import fernet as credential_fernet
|
||||||
from keystone import exception
|
from keystone import exception
|
||||||
|
from keystone.server import flask as server_flask
|
||||||
from keystone.tests import unit
|
from keystone.tests import unit
|
||||||
from keystone.tests.unit import ksfixtures
|
from keystone.tests.unit import ksfixtures
|
||||||
from keystone.tests.unit import utils
|
from keystone.tests.unit import utils
|
||||||
from keystone.version import service
|
|
||||||
|
|
||||||
|
|
||||||
CONF = keystone.conf.CONF
|
CONF = keystone.conf.CONF
|
||||||
@ -250,7 +250,7 @@ class UtilsTestCase(unit.BaseTestCase):
|
|||||||
|
|
||||||
class ServiceHelperTests(unit.BaseTestCase):
|
class ServiceHelperTests(unit.BaseTestCase):
|
||||||
|
|
||||||
@service.fail_gracefully
|
@server_flask.fail_gracefully
|
||||||
def _do_test(self):
|
def _do_test(self):
|
||||||
raise Exception("Test Exc")
|
raise Exception("Test Exc")
|
||||||
|
|
||||||
|
@ -34,7 +34,6 @@ from oslo_context import fixture as oslo_ctx_fixture
|
|||||||
from oslo_log import fixture as log_fixture
|
from oslo_log import fixture as log_fixture
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
from oslo_utils import timeutils
|
from oslo_utils import timeutils
|
||||||
from paste.deploy import loadwsgi
|
|
||||||
import six
|
import six
|
||||||
from sqlalchemy import exc
|
from sqlalchemy import exc
|
||||||
import testtools
|
import testtools
|
||||||
@ -112,26 +111,6 @@ class dirs(object):
|
|||||||
return os.path.join(TESTCONF, *p)
|
return os.path.join(TESTCONF, *p)
|
||||||
|
|
||||||
|
|
||||||
class EggLoader(loadwsgi.EggLoader):
|
|
||||||
_basket = {}
|
|
||||||
|
|
||||||
def find_egg_entry_point(self, object_type, name=None):
|
|
||||||
egg_key = '%s:%s' % (object_type, name)
|
|
||||||
egg_ep = self._basket.get(egg_key)
|
|
||||||
if not egg_ep:
|
|
||||||
egg_ep = super(EggLoader, self).find_egg_entry_point(
|
|
||||||
object_type, name=name)
|
|
||||||
self._basket[egg_key] = egg_ep
|
|
||||||
return egg_ep
|
|
||||||
|
|
||||||
|
|
||||||
# NOTE(dstanek): class paths were removed from the keystone-paste.ini in
|
|
||||||
# favor of using entry points. This caused tests to slow to a crawl
|
|
||||||
# since we reload the application object for each RESTful test. This
|
|
||||||
# monkey-patching adds caching to paste deploy's egg lookup.
|
|
||||||
loadwsgi.EggLoader = EggLoader
|
|
||||||
|
|
||||||
|
|
||||||
@atexit.register
|
@atexit.register
|
||||||
def remove_test_databases():
|
def remove_test_databases():
|
||||||
db = dirs.tmp('test.db')
|
db = dirs.tmp('test.db')
|
||||||
@ -798,15 +777,6 @@ class TestCase(BaseTestCase):
|
|||||||
|
|
||||||
self.addCleanup(self.cleanup_instance(*fixtures_to_cleanup))
|
self.addCleanup(self.cleanup_instance(*fixtures_to_cleanup))
|
||||||
|
|
||||||
def _paste_config(self, config):
|
|
||||||
if not config.startswith('config:'):
|
|
||||||
test_path = os.path.join(TESTSDIR, config)
|
|
||||||
etc_path = os.path.join(ROOTDIR, 'etc', config)
|
|
||||||
for path in [test_path, etc_path]:
|
|
||||||
if os.path.exists('%s-paste.ini' % path):
|
|
||||||
return 'config:%s-paste.ini' % path
|
|
||||||
return config
|
|
||||||
|
|
||||||
def loadapp(self, name='public'):
|
def loadapp(self, name='public'):
|
||||||
return service.loadapp(name=name)
|
return service.loadapp(name=name)
|
||||||
|
|
||||||
|
@ -13,13 +13,10 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import uuid
|
|
||||||
|
|
||||||
from oslo_config import generator
|
from oslo_config import generator
|
||||||
|
|
||||||
import keystone.conf
|
import keystone.conf
|
||||||
from keystone import exception
|
|
||||||
from keystone.server import wsgi
|
|
||||||
from keystone.tests import unit
|
from keystone.tests import unit
|
||||||
|
|
||||||
|
|
||||||
@ -31,10 +28,6 @@ class ConfigTestCase(unit.TestCase):
|
|||||||
def config_files(self):
|
def config_files(self):
|
||||||
config_files = super(ConfigTestCase, self).config_files()
|
config_files = super(ConfigTestCase, self).config_files()
|
||||||
|
|
||||||
# NOTE(lbragstad): This needs some investigation, but CONF.find_file()
|
|
||||||
# apparently needs the sample configuration file in order to find the
|
|
||||||
# paste file. This should really be replaced by just setting the
|
|
||||||
# default configuration directory on the config object instead.
|
|
||||||
sample_file = 'keystone.conf.sample'
|
sample_file = 'keystone.conf.sample'
|
||||||
args = ['--namespace', 'keystone', '--output-file',
|
args = ['--namespace', 'keystone', '--output-file',
|
||||||
unit.dirs.etc(sample_file)]
|
unit.dirs.etc(sample_file)]
|
||||||
@ -43,18 +36,6 @@ class ConfigTestCase(unit.TestCase):
|
|||||||
self.addCleanup(os.remove, unit.dirs.etc(sample_file))
|
self.addCleanup(os.remove, unit.dirs.etc(sample_file))
|
||||||
return config_files
|
return config_files
|
||||||
|
|
||||||
def test_default_paste_config_location_succeeds(self):
|
|
||||||
paste_file_location = unit.dirs.etc(CONF.paste_deploy.config_file)
|
|
||||||
self.assertEqual(paste_file_location, wsgi.find_paste_config())
|
|
||||||
|
|
||||||
def test_invalid_paste_file_location_fails(self):
|
|
||||||
self.config_fixture.config(
|
|
||||||
group='paste_deploy', config_file=uuid.uuid4().hex
|
|
||||||
)
|
|
||||||
self.assertRaises(
|
|
||||||
exception.ConfigFileNotFound, wsgi.find_paste_config
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_config_default(self):
|
def test_config_default(self):
|
||||||
self.assertIsNone(CONF.auth.password)
|
self.assertIsNone(CONF.auth.password)
|
||||||
self.assertIsNone(CONF.auth.token)
|
self.assertIsNone(CONF.auth.token)
|
||||||
|
@ -26,7 +26,6 @@ class TestEntryPoints(test.TestCase):
|
|||||||
'json_body',
|
'json_body',
|
||||||
'request_id',
|
'request_id',
|
||||||
'sizelimit',
|
'sizelimit',
|
||||||
'token_auth',
|
|
||||||
'url_normalize',
|
'url_normalize',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ import webob
|
|||||||
|
|
||||||
from keystone.common import wsgi
|
from keystone.common import wsgi
|
||||||
from keystone import exception
|
from keystone import exception
|
||||||
from keystone.server import wsgi as server_wsgi
|
from keystone.server.flask import core as server_flask
|
||||||
from keystone.tests import unit
|
from keystone.tests import unit
|
||||||
|
|
||||||
|
|
||||||
@ -297,7 +297,7 @@ class WSGIAppConfigTest(unit.TestCase):
|
|||||||
custom_config_files = ['kst.conf', 'kst2.conf']
|
custom_config_files = ['kst.conf', 'kst2.conf']
|
||||||
|
|
||||||
def test_config_files_have_default_values_when_envars_not_set(self):
|
def test_config_files_have_default_values_when_envars_not_set(self):
|
||||||
config_files = server_wsgi._get_config_files()
|
config_files = server_flask._get_config_files()
|
||||||
config_files.sort()
|
config_files.sort()
|
||||||
expected_config_files = []
|
expected_config_files = []
|
||||||
self.assertListEqual(config_files, expected_config_files)
|
self.assertListEqual(config_files, expected_config_files)
|
||||||
@ -305,7 +305,7 @@ class WSGIAppConfigTest(unit.TestCase):
|
|||||||
def test_config_files_have_default_values_with_empty_envars(self):
|
def test_config_files_have_default_values_with_empty_envars(self):
|
||||||
env = {'OS_KEYSTONE_CONFIG_FILES': '',
|
env = {'OS_KEYSTONE_CONFIG_FILES': '',
|
||||||
'OS_KEYSTONE_CONFIG_DIR': ''}
|
'OS_KEYSTONE_CONFIG_DIR': ''}
|
||||||
config_files = server_wsgi._get_config_files(env)
|
config_files = server_flask._get_config_files(env)
|
||||||
config_files.sort()
|
config_files.sort()
|
||||||
expected_config_files = []
|
expected_config_files = []
|
||||||
self.assertListEqual(config_files, expected_config_files)
|
self.assertListEqual(config_files, expected_config_files)
|
||||||
@ -313,20 +313,20 @@ class WSGIAppConfigTest(unit.TestCase):
|
|||||||
def test_can_use_single_config_file_under_default_config_dir(self):
|
def test_can_use_single_config_file_under_default_config_dir(self):
|
||||||
cfg = self.custom_config_files[0]
|
cfg = self.custom_config_files[0]
|
||||||
env = {'OS_KEYSTONE_CONFIG_FILES': cfg}
|
env = {'OS_KEYSTONE_CONFIG_FILES': cfg}
|
||||||
config_files = server_wsgi._get_config_files(env)
|
config_files = server_flask._get_config_files(env)
|
||||||
expected_config_files = [cfg]
|
expected_config_files = [cfg]
|
||||||
self.assertListEqual(config_files, expected_config_files)
|
self.assertListEqual(config_files, expected_config_files)
|
||||||
|
|
||||||
def test_can_use_multiple_config_files_under_default_config_dir(self):
|
def test_can_use_multiple_config_files_under_default_config_dir(self):
|
||||||
env = {'OS_KEYSTONE_CONFIG_FILES': ';'.join(self.custom_config_files)}
|
env = {'OS_KEYSTONE_CONFIG_FILES': ';'.join(self.custom_config_files)}
|
||||||
config_files = server_wsgi._get_config_files(env)
|
config_files = server_flask._get_config_files(env)
|
||||||
config_files.sort()
|
config_files.sort()
|
||||||
expected_config_files = self.custom_config_files
|
expected_config_files = self.custom_config_files
|
||||||
self.assertListEqual(config_files, expected_config_files)
|
self.assertListEqual(config_files, expected_config_files)
|
||||||
|
|
||||||
config_with_empty_strings = self.custom_config_files + ['', ' ']
|
config_with_empty_strings = self.custom_config_files + ['', ' ']
|
||||||
env = {'OS_KEYSTONE_CONFIG_FILES': ';'.join(config_with_empty_strings)}
|
env = {'OS_KEYSTONE_CONFIG_FILES': ';'.join(config_with_empty_strings)}
|
||||||
config_files = server_wsgi._get_config_files(env)
|
config_files = server_flask._get_config_files(env)
|
||||||
config_files.sort()
|
config_files.sort()
|
||||||
self.assertListEqual(config_files, expected_config_files)
|
self.assertListEqual(config_files, expected_config_files)
|
||||||
|
|
||||||
@ -334,7 +334,7 @@ class WSGIAppConfigTest(unit.TestCase):
|
|||||||
cfg = self.custom_config_files[0]
|
cfg = self.custom_config_files[0]
|
||||||
cfgpath = os.path.join(self.custom_config_dir, cfg)
|
cfgpath = os.path.join(self.custom_config_dir, cfg)
|
||||||
env = {'OS_KEYSTONE_CONFIG_FILES': cfgpath}
|
env = {'OS_KEYSTONE_CONFIG_FILES': cfgpath}
|
||||||
config_files = server_wsgi._get_config_files(env)
|
config_files = server_flask._get_config_files(env)
|
||||||
self.assertListEqual(config_files, [cfgpath])
|
self.assertListEqual(config_files, [cfgpath])
|
||||||
|
|
||||||
def test_can_use_multiple_absolute_path_config_files(self):
|
def test_can_use_multiple_absolute_path_config_files(self):
|
||||||
@ -342,18 +342,18 @@ class WSGIAppConfigTest(unit.TestCase):
|
|||||||
for cfg in self.custom_config_files]
|
for cfg in self.custom_config_files]
|
||||||
cfgpaths.sort()
|
cfgpaths.sort()
|
||||||
env = {'OS_KEYSTONE_CONFIG_FILES': ';'.join(cfgpaths)}
|
env = {'OS_KEYSTONE_CONFIG_FILES': ';'.join(cfgpaths)}
|
||||||
config_files = server_wsgi._get_config_files(env)
|
config_files = server_flask._get_config_files(env)
|
||||||
config_files.sort()
|
config_files.sort()
|
||||||
self.assertListEqual(config_files, cfgpaths)
|
self.assertListEqual(config_files, cfgpaths)
|
||||||
|
|
||||||
env = {'OS_KEYSTONE_CONFIG_FILES': ';'.join(cfgpaths + ['', ' '])}
|
env = {'OS_KEYSTONE_CONFIG_FILES': ';'.join(cfgpaths + ['', ' '])}
|
||||||
config_files = server_wsgi._get_config_files(env)
|
config_files = server_flask._get_config_files(env)
|
||||||
config_files.sort()
|
config_files.sort()
|
||||||
self.assertListEqual(config_files, cfgpaths)
|
self.assertListEqual(config_files, cfgpaths)
|
||||||
|
|
||||||
def test_can_use_default_config_files_with_custom_config_dir(self):
|
def test_can_use_default_config_files_with_custom_config_dir(self):
|
||||||
env = {'OS_KEYSTONE_CONFIG_DIR': self.custom_config_dir}
|
env = {'OS_KEYSTONE_CONFIG_DIR': self.custom_config_dir}
|
||||||
config_files = server_wsgi._get_config_files(env)
|
config_files = server_flask._get_config_files(env)
|
||||||
config_files.sort()
|
config_files.sort()
|
||||||
expected_config_files = [os.path.join(self.custom_config_dir,
|
expected_config_files = [os.path.join(self.custom_config_dir,
|
||||||
self.default_config_file)]
|
self.default_config_file)]
|
||||||
@ -363,7 +363,7 @@ class WSGIAppConfigTest(unit.TestCase):
|
|||||||
cfg = self.custom_config_files[0]
|
cfg = self.custom_config_files[0]
|
||||||
env = {'OS_KEYSTONE_CONFIG_DIR': self.custom_config_dir,
|
env = {'OS_KEYSTONE_CONFIG_DIR': self.custom_config_dir,
|
||||||
'OS_KEYSTONE_CONFIG_FILES': cfg}
|
'OS_KEYSTONE_CONFIG_FILES': cfg}
|
||||||
config_files = server_wsgi._get_config_files(env)
|
config_files = server_flask._get_config_files(env)
|
||||||
config_files.sort()
|
config_files.sort()
|
||||||
expected_config_files = [os.path.join(self.custom_config_dir, cfg)]
|
expected_config_files = [os.path.join(self.custom_config_dir, cfg)]
|
||||||
self.assertListEqual(config_files, expected_config_files)
|
self.assertListEqual(config_files, expected_config_files)
|
||||||
@ -371,7 +371,7 @@ class WSGIAppConfigTest(unit.TestCase):
|
|||||||
def test_can_use_multiple_config_files_under_custom_config_dir(self):
|
def test_can_use_multiple_config_files_under_custom_config_dir(self):
|
||||||
env = {'OS_KEYSTONE_CONFIG_DIR': self.custom_config_dir,
|
env = {'OS_KEYSTONE_CONFIG_DIR': self.custom_config_dir,
|
||||||
'OS_KEYSTONE_CONFIG_FILES': ';'.join(self.custom_config_files)}
|
'OS_KEYSTONE_CONFIG_FILES': ';'.join(self.custom_config_files)}
|
||||||
config_files = server_wsgi._get_config_files(env)
|
config_files = server_flask._get_config_files(env)
|
||||||
config_files.sort()
|
config_files.sort()
|
||||||
expected_config_files = [os.path.join(self.custom_config_dir, s)
|
expected_config_files = [os.path.join(self.custom_config_dir, s)
|
||||||
for s in self.custom_config_files]
|
for s in self.custom_config_files]
|
||||||
@ -381,7 +381,7 @@ class WSGIAppConfigTest(unit.TestCase):
|
|||||||
config_with_empty_strings = self.custom_config_files + ['', ' ']
|
config_with_empty_strings = self.custom_config_files + ['', ' ']
|
||||||
env = {'OS_KEYSTONE_CONFIG_DIR': self.custom_config_dir,
|
env = {'OS_KEYSTONE_CONFIG_DIR': self.custom_config_dir,
|
||||||
'OS_KEYSTONE_CONFIG_FILES': ';'.join(config_with_empty_strings)}
|
'OS_KEYSTONE_CONFIG_FILES': ';'.join(config_with_empty_strings)}
|
||||||
config_files = server_wsgi._get_config_files(env)
|
config_files = server_flask._get_config_files(env)
|
||||||
config_files.sort()
|
config_files.sort()
|
||||||
self.assertListEqual(config_files, expected_config_files)
|
self.assertListEqual(config_files, expected_config_files)
|
||||||
|
|
||||||
@ -393,14 +393,14 @@ class WSGIAppConfigTest(unit.TestCase):
|
|||||||
self.custom_config_files[1])
|
self.custom_config_files[1])
|
||||||
env = {'OS_KEYSTONE_CONFIG_DIR': self.custom_config_dir,
|
env = {'OS_KEYSTONE_CONFIG_DIR': self.custom_config_dir,
|
||||||
'OS_KEYSTONE_CONFIG_FILES': ';'.join([cfg0, cfgpath1])}
|
'OS_KEYSTONE_CONFIG_FILES': ';'.join([cfg0, cfgpath1])}
|
||||||
config_files = server_wsgi._get_config_files(env)
|
config_files = server_flask._get_config_files(env)
|
||||||
config_files.sort()
|
config_files.sort()
|
||||||
expected_config_files = [cfgpath0, cfgpath1]
|
expected_config_files = [cfgpath0, cfgpath1]
|
||||||
expected_config_files.sort()
|
expected_config_files.sort()
|
||||||
self.assertListEqual(config_files, expected_config_files)
|
self.assertListEqual(config_files, expected_config_files)
|
||||||
|
|
||||||
env = {'OS_KEYSTONE_CONFIG_FILES': ';'.join([cfg0, cfgpath1])}
|
env = {'OS_KEYSTONE_CONFIG_FILES': ';'.join([cfg0, cfgpath1])}
|
||||||
config_files = server_wsgi._get_config_files(env)
|
config_files = server_flask._get_config_files(env)
|
||||||
config_files.sort()
|
config_files.sort()
|
||||||
expected_config_files = [cfg0, cfgpath1]
|
expected_config_files = [cfg0, cfgpath1]
|
||||||
expected_config_files.sort()
|
expected_config_files.sort()
|
||||||
|
@ -12,33 +12,12 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import functools
|
|
||||||
import sys
|
|
||||||
|
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
import routes
|
|
||||||
|
|
||||||
from keystone.application_credential import routers as app_cred_routers
|
|
||||||
from keystone.assignment import routers as assignment_routers
|
|
||||||
from keystone.auth import routers as auth_routers
|
|
||||||
from keystone.catalog import routers as catalog_routers
|
|
||||||
from keystone.common import wsgi
|
|
||||||
import keystone.conf
|
import keystone.conf
|
||||||
from keystone.credential import routers as credential_routers
|
|
||||||
from keystone.endpoint_policy import routers as endpoint_policy_routers
|
|
||||||
from keystone.federation import routers as federation_routers
|
|
||||||
from keystone.identity import routers as identity_routers
|
|
||||||
from keystone.limit import routers as limit_routers
|
|
||||||
from keystone.oauth1 import routers as oauth1_routers
|
|
||||||
from keystone.policy import routers as policy_routers
|
|
||||||
from keystone.resource import routers as resource_routers
|
|
||||||
from keystone.revoke import routers as revoke_routers
|
|
||||||
from keystone.server import flask as keystone_flask
|
from keystone.server import flask as keystone_flask
|
||||||
from keystone.server.flask import application
|
from keystone.server.flask import application
|
||||||
from keystone.token import _simple_cert as simple_cert_ext
|
|
||||||
from keystone.trust import routers as trust_routers
|
|
||||||
from keystone.version import controllers
|
from keystone.version import controllers
|
||||||
from keystone.version import routers
|
|
||||||
|
|
||||||
|
|
||||||
CONF = keystone.conf.CONF
|
CONF = keystone.conf.CONF
|
||||||
@ -52,107 +31,3 @@ def loadapp(name):
|
|||||||
controllers.latest_app = keystone_flask.setup_app_middleware(
|
controllers.latest_app = keystone_flask.setup_app_middleware(
|
||||||
application.application_factory(name))
|
application.application_factory(name))
|
||||||
return controllers.latest_app
|
return controllers.latest_app
|
||||||
|
|
||||||
|
|
||||||
def fail_gracefully(f):
|
|
||||||
"""Log exceptions and aborts."""
|
|
||||||
@functools.wraps(f)
|
|
||||||
def wrapper(*args, **kw):
|
|
||||||
try:
|
|
||||||
return f(*args, **kw)
|
|
||||||
except Exception as e:
|
|
||||||
LOG.debug(e, exc_info=True)
|
|
||||||
|
|
||||||
# exception message is printed to all logs
|
|
||||||
LOG.critical(e)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
return wrapper
|
|
||||||
|
|
||||||
|
|
||||||
def warn_local_conf(f):
|
|
||||||
@functools.wraps(f)
|
|
||||||
def wrapper(*args, **local_conf):
|
|
||||||
if local_conf:
|
|
||||||
LOG.warning("'local conf' from PasteDeploy INI is being ignored.")
|
|
||||||
return f(*args, **local_conf)
|
|
||||||
return wrapper
|
|
||||||
|
|
||||||
|
|
||||||
@fail_gracefully
|
|
||||||
@warn_local_conf
|
|
||||||
def public_app_factory(global_conf, **local_conf):
|
|
||||||
controllers.register_version('v2.0')
|
|
||||||
# NOTE(lbragstad): Only wire up the v2.0 version controller. We should keep
|
|
||||||
# this here because we still support the ec2tokens API on the v2.0 path
|
|
||||||
# until T. Once that is removed, we can remove the rest of the v2.0 routers
|
|
||||||
# and whatnot. The ec2token controller is actually wired up by the paste
|
|
||||||
# pipeline.
|
|
||||||
return wsgi.ComposingRouter(routes.Mapper(), [routers.VersionV2('public')])
|
|
||||||
|
|
||||||
|
|
||||||
@fail_gracefully
|
|
||||||
@warn_local_conf
|
|
||||||
def admin_app_factory(global_conf, **local_conf):
|
|
||||||
controllers.register_version('v2.0')
|
|
||||||
# NOTE(lbragstad): Only wire up the v2.0 version controller. We should keep
|
|
||||||
# this here because we still support the ec2tokens API on the v2.0 path
|
|
||||||
# until T. Once that is removed, we can remove the rest of the v2.0 routers
|
|
||||||
# and whatnot. The ec2token controller is actually wired up by the paste
|
|
||||||
# pipeline.
|
|
||||||
return wsgi.ComposingRouter(routes.Mapper(), [routers.VersionV2('admin')])
|
|
||||||
|
|
||||||
|
|
||||||
@fail_gracefully
|
|
||||||
@warn_local_conf
|
|
||||||
def public_version_app_factory(global_conf, **local_conf):
|
|
||||||
return wsgi.ComposingRouter(routes.Mapper(),
|
|
||||||
[routers.Versions('public')])
|
|
||||||
|
|
||||||
|
|
||||||
@fail_gracefully
|
|
||||||
@warn_local_conf
|
|
||||||
def admin_version_app_factory(global_conf, **local_conf):
|
|
||||||
return wsgi.ComposingRouter(routes.Mapper(),
|
|
||||||
[routers.Versions('admin')])
|
|
||||||
|
|
||||||
|
|
||||||
@fail_gracefully
|
|
||||||
@warn_local_conf
|
|
||||||
def v3_app_factory(global_conf, **local_conf):
|
|
||||||
controllers.register_version('v3')
|
|
||||||
mapper = routes.Mapper()
|
|
||||||
sub_routers = []
|
|
||||||
_routers = []
|
|
||||||
|
|
||||||
# NOTE(dstanek): Routers should be ordered by their frequency of use in
|
|
||||||
# a live system. This is due to the routes implementation. The most
|
|
||||||
# frequently used routers should appear first.
|
|
||||||
all_api_routers = [auth_routers,
|
|
||||||
assignment_routers,
|
|
||||||
catalog_routers,
|
|
||||||
credential_routers,
|
|
||||||
identity_routers,
|
|
||||||
app_cred_routers,
|
|
||||||
limit_routers,
|
|
||||||
policy_routers,
|
|
||||||
resource_routers,
|
|
||||||
revoke_routers,
|
|
||||||
federation_routers,
|
|
||||||
oauth1_routers,
|
|
||||||
endpoint_policy_routers,
|
|
||||||
# TODO(morganfainberg): Remove the simple_cert router
|
|
||||||
# when PKI and PKIZ tokens are removed.
|
|
||||||
simple_cert_ext]
|
|
||||||
|
|
||||||
if CONF.trust.enabled:
|
|
||||||
all_api_routers.append(trust_routers)
|
|
||||||
|
|
||||||
for api_routers in all_api_routers:
|
|
||||||
routers_instance = api_routers.Routers()
|
|
||||||
_routers.append(routers_instance)
|
|
||||||
routers_instance.append_v3_routers(mapper, sub_routers)
|
|
||||||
|
|
||||||
# Add in the v3 version api
|
|
||||||
sub_routers.append(routers.VersionV3('public', _routers))
|
|
||||||
return wsgi.ComposingRouter(mapper, sub_routers)
|
|
||||||
|
@ -8,8 +8,6 @@ Babel!=2.4.0,>=2.3.4 # BSD
|
|||||||
|
|
||||||
pbr!=2.1.0,>=2.0.0 # Apache-2.0
|
pbr!=2.1.0,>=2.0.0 # Apache-2.0
|
||||||
WebOb>=1.7.1 # MIT
|
WebOb>=1.7.1 # MIT
|
||||||
PasteDeploy>=1.5.0 # MIT
|
|
||||||
Paste>=2.0.2 # MIT
|
|
||||||
Routes>=2.3.1 # MIT
|
Routes>=2.3.1 # MIT
|
||||||
Flask!=0.11,<1.0 # BSD
|
Flask!=0.11,<1.0 # BSD
|
||||||
cryptography>=2.1 # BSD/Apache-2.0
|
cryptography>=2.1 # BSD/Apache-2.0
|
||||||
|
25
setup.cfg
25
setup.cfg
@ -194,28 +194,3 @@ keystone.server_middleware =
|
|||||||
token_auth = keystone.middleware:TokenAuthMiddleware
|
token_auth = keystone.middleware:TokenAuthMiddleware
|
||||||
json_body = keystone.middleware:JsonBodyMiddleware
|
json_body = keystone.middleware:JsonBodyMiddleware
|
||||||
debug = oslo_middleware:Debug
|
debug = oslo_middleware:Debug
|
||||||
|
|
||||||
paste.filter_factory =
|
|
||||||
# TODO(morgan): Remove paste.filter_factory
|
|
||||||
healthcheck = oslo_middleware:Healthcheck.factory
|
|
||||||
cors = oslo_middleware:CORS.factory
|
|
||||||
sizelimit = oslo_middleware:RequestBodySizeLimiter.factory
|
|
||||||
http_proxy_to_wsgi = oslo_middleware:HTTPProxyToWSGI.factory
|
|
||||||
osprofiler = osprofiler.web:WsgiMiddleware.factory
|
|
||||||
url_normalize = keystone.middleware:NormalizingFilter.factory
|
|
||||||
request_id = oslo_middleware:RequestId.factory
|
|
||||||
build_auth_context = keystone.middleware:AuthContextMiddleware.factory
|
|
||||||
token_auth = keystone.middleware:TokenAuthMiddleware.factory
|
|
||||||
json_body = keystone.middleware:JsonBodyMiddleware.factory
|
|
||||||
debug = oslo_middleware:Debug.factory
|
|
||||||
ec2_extension = keystone.contrib.ec2:Ec2Extension.factory
|
|
||||||
ec2_extension_v3 = keystone.contrib.ec2:Ec2ExtensionV3.factory
|
|
||||||
s3_extension = keystone.contrib.s3:S3Extension.factory
|
|
||||||
|
|
||||||
paste.app_factory =
|
|
||||||
# TODO(morgan): Remove paste.app_factory
|
|
||||||
admin_service = keystone.version.service:admin_app_factory
|
|
||||||
admin_version_service = keystone.version.service:admin_version_app_factory
|
|
||||||
public_service = keystone.version.service:public_app_factory
|
|
||||||
public_version_service = keystone.version.service:public_version_app_factory
|
|
||||||
service_v3 = keystone.version.service:v3_app_factory
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user