Add generic PasteDeploy app and filter factories

These generic factories allow us to dump the copied and pasted
app_factory and filter_factory methods in the codebase.

The main difference is the paste configuration changes from:

  [app:apiv1app]
  paste.app_factory = glance.api.v1:app_factory
  ...
  [filter:cache]
  paste.filter_factory = glance.api.middleware.cache:filter_factory

to this:

  [app:apiv1app]
  paste.app_factory = glance.common.wsgi:app_factory
  glance.app_factory = glance.api.v1:API
  ...
  [filter:cache]
  paste.filter_factory = glance.common.wsgi:filter_factory
  glance.filter_factory = glance.api.middleware.cache:CacheFilter

Apart from reducing code duplication, this will also allow us to have
the generic factories inject other data into the apps and filters.

Change-Id: I1d2be5630ab61d29b8948ff88d58e6e1b11c2e5f
This commit is contained in:
Mark McLoughlin 2011-11-28 14:37:58 +00:00
parent 07dcb32106
commit ba44d1c384
24 changed files with 118 additions and 159 deletions

View File

@ -513,7 +513,8 @@ The cache middleware should be in your ``glance-api.conf`` in a section titled
``[filter:cache]``. It should look like this:: ``[filter:cache]``. It should look like this::
[filter:cache] [filter:cache]
paste.filter_factory = glance.api.middleware.cache:filter_factory paste.filter_factory = glance.common.wsgi:filter_factory
glance.filter_factory = glance.api.middleware.cache:CacheFilter
For example, suppose your application pipeline in the ``glance-api.conf`` file For example, suppose your application pipeline in the ``glance-api.conf`` file

View File

@ -214,19 +214,24 @@ pipeline = versionnegotiation context apiv1app
# pipeline = versionnegotiation authtoken auth-context cachemanage apiv1app # pipeline = versionnegotiation authtoken auth-context cachemanage apiv1app
[app:apiv1app] [app:apiv1app]
paste.app_factory = glance.api.v1.router:app_factory paste.app_factory = glance.common.wsgi:app_factory
glance.app_factory = glance.api.v1.router:API
[filter:versionnegotiation] [filter:versionnegotiation]
paste.filter_factory = glance.api.middleware.version_negotiation:filter_factory paste.filter_factory = glance.common.wsgi:filter_factory
glance.filter_factory = glance.api.middleware.version_negotiation:VersionNegotiationFilter
[filter:cache] [filter:cache]
paste.filter_factory = glance.api.middleware.cache:filter_factory paste.filter_factory = glance.common.wsgi:filter_factory
glance.filter_factory = glance.api.middleware.cache:CacheFilter
[filter:cachemanage] [filter:cachemanage]
paste.filter_factory = glance.api.middleware.cache_manage:filter_factory paste.filter_factory = glance.common.wsgi:filter_factory
glance.filter_factory = glance.api.middleware.cache_manage:CacheManageFilter
[filter:context] [filter:context]
paste.filter_factory = glance.common.context:filter_factory paste.filter_factory = glance.common.wsgi:filter_factory
glance.filter_factory = glance.common.context:ContextMiddleware
[filter:authtoken] [filter:authtoken]
paste.filter_factory = keystone.middleware.auth_token:filter_factory paste.filter_factory = keystone.middleware.auth_token:filter_factory
@ -240,4 +245,5 @@ auth_uri = http://127.0.0.1:5000/
admin_token = 999888777666 admin_token = 999888777666
[filter:auth-context] [filter:auth-context]
paste.filter_factory = keystone.middleware.glance_auth_token:filter_factory paste.filter_factory = glance.common.wsgi:filter_factory
glance.filter_factory = keystone.middleware.glance_auth_token:KeystoneContextMiddleware

View File

@ -40,13 +40,17 @@ registry_port = 9191
# admin_token = 123 # admin_token = 123
[app:glance-pruner] [app:glance-pruner]
paste.app_factory = glance.image_cache.pruner:app_factory paste.app_factory = glance.common.wsgi:app_factory
glance.app_factory = glance.image_cache.pruner:Pruner
[app:glance-prefetcher] [app:glance-prefetcher]
paste.app_factory = glance.image_cache.prefetcher:app_factory paste.app_factory = glance.common.wsgi:app_factory
glance.app_factory = glance.image_cache.prefetcher:Prefetcher
[app:glance-cleaner] [app:glance-cleaner]
paste.app_factory = glance.image_cache.cleaner:app_factory paste.app_factory = glance.common.wsgi:app_factory
glance.app_factory = glance.image_cache.cleaner:Cleaner
[app:glance-queue-image] [app:glance-queue-image]
paste.app_factory = glance.image_cache.queue_image:app_factory paste.app_factory = glance.common.wsgi:app_factory
glance.app_factory = glance.image_cache.queue_image:Queuer

View File

@ -57,11 +57,13 @@ pipeline = context registryapp
# pipeline = authtoken auth-context registryapp # pipeline = authtoken auth-context registryapp
[app:registryapp] [app:registryapp]
paste.app_factory = glance.registry.api.v1:app_factory paste.app_factory = glance.common.wsgi:app_factory
glance.app_factory = glance.registry.api.v1:API
[filter:context] [filter:context]
context_class = glance.registry.context.RequestContext context_class = glance.registry.context.RequestContext
paste.filter_factory = glance.common.context:filter_factory paste.filter_factory = glance.common.wsgi:filter_factory
glance.filter_factory = glance.common.context:ContextMiddleware
[filter:authtoken] [filter:authtoken]
paste.filter_factory = keystone.middleware.auth_token:filter_factory paste.filter_factory = keystone.middleware.auth_token:filter_factory
@ -76,4 +78,5 @@ admin_token = 999888777666
[filter:auth-context] [filter:auth-context]
context_class = glance.registry.context.RequestContext context_class = glance.registry.context.RequestContext
paste.filter_factory = keystone.middleware.glance_auth_token:filter_factory paste.filter_factory = glance.common.wsgi:filter_factory
glance.filter_factory = keystone.middleware.glance_auth_token:KeystoneContextMiddleware

View File

@ -35,4 +35,5 @@ registry_host = 0.0.0.0
registry_port = 9191 registry_port = 9191
[app:glance-scrubber] [app:glance-scrubber]
paste.app_factory = glance.store.scrubber:app_factory paste.app_factory = glance.common.wsgi:app_factory
glance.app_factory = glance.store.scrubber:Scrubber

View File

@ -115,10 +115,3 @@ def create_resource(options):
deserializer = CachedImageDeserializer() deserializer = CachedImageDeserializer()
serializer = CachedImageSerializer() serializer = CachedImageSerializer()
return wsgi.Resource(Controller(options), deserializer, serializer) return wsgi.Resource(Controller(options), deserializer, serializer)
def app_factory(global_conf, **local_conf):
"""paste.deploy app factory for creating Cached Images apps"""
conf = global_conf.copy()
conf.update(local_conf)
return Controller(conf)

View File

@ -132,16 +132,3 @@ class CacheFilter(wsgi.Middleware):
chunks = utils.chunkiter(cache_file) chunks = utils.chunkiter(cache_file)
for chunk in chunks: for chunk in chunks:
yield chunk yield chunk
def filter_factory(global_conf, **local_conf):
"""
Factory method for paste.deploy
"""
conf = global_conf.copy()
conf.update(local_conf)
def filter(app):
return CacheFilter(app, conf)
return filter

View File

@ -70,16 +70,3 @@ class CacheManageFilter(wsgi.Middleware):
logger.info(_("Initialized image cache management middleware")) logger.info(_("Initialized image cache management middleware"))
super(CacheManageFilter, self).__init__(app) super(CacheManageFilter, self).__init__(app)
def filter_factory(global_conf, **local_conf):
"""
Factory method for paste.deploy
"""
conf = global_conf.copy()
conf.update(local_conf)
def filter(app):
return CacheManageFilter(app, conf)
return filter

View File

@ -121,16 +121,3 @@ class VersionNegotiationFilter(wsgi.Middleware):
req.environ['api.major_version'] = major_version req.environ['api.major_version'] = major_version
req.environ['api.minor_version'] = minor_version req.environ['api.minor_version'] = minor_version
return match is not None return match is not None
def filter_factory(global_conf, **local_conf):
"""
Factory method for paste.deploy
"""
conf = global_conf.copy()
conf.update(local_conf)
def filter(app):
return VersionNegotiationFilter(app, conf)
return filter

View File

@ -56,10 +56,3 @@ class API(wsgi.Router):
conditions=dict(method=["PUT"])) conditions=dict(method=["PUT"]))
super(API, self).__init__(mapper) super(API, self).__init__(mapper)
def app_factory(global_conf, **local_conf):
"""paste.deploy app factory for creating Glance API server apps"""
conf = global_conf.copy()
conf.update(local_conf)
return API(conf)

View File

@ -119,16 +119,3 @@ class ContextMiddleware(wsgi.Middleware):
req.context = self.make_context( req.context = self.make_context(
auth_tok=auth_tok, user=user, tenant=tenant, roles=roles, auth_tok=auth_tok, user=user, tenant=tenant, roles=roles,
is_admin=is_admin) is_admin=is_admin)
def filter_factory(global_conf, **local_conf):
"""
Factory method for paste.deploy
"""
conf = global_conf.copy()
conf.update(local_conf)
def filter(app):
return ContextMiddleware(app, conf)
return filter

View File

@ -37,6 +37,7 @@ import webob.dec
import webob.exc import webob.exc
from glance.common import exception from glance.common import exception
from glance.common import utils
class WritableLogger(object): class WritableLogger(object):
@ -406,3 +407,52 @@ class Resource(object):
pass pass
return args return args
def _import_factory(conf, key):
return utils.import_class(conf[key].replace(':', '.').strip())
def app_factory(global_conf, **local_conf):
"""A Generic paste.deploy app factory.
This requires glance.app_factory to be set to a callable which returns a
WSGI app when invoked. The format of the name is <module>:<callable> e.g.
[app:apiv1app]
paste.app_factory = glance.common.wsgi:app_factory
glance.app_factory = glance.api.v1:API
The WSGI app constructor must accept a configuration dict as its only
argument.
"""
factory = _import_factory(local_conf, 'glance.app_factory')
conf = global_conf.copy()
conf.update(local_conf)
return factory(conf)
def filter_factory(global_conf, **local_conf):
"""A Generic paste.deploy filter factory.
This requires glance.filter_factory to be set to a callable which returns a
WSGI filter when invoked. The format is <module>:<callable> e.g.
[filter:cache]
paste.filter_factory = glance.common.wsgi:filter_factory
glance.filter_factory = glance.api.middleware.cache:CacheFilter
The WSGI filter constructor must accept a WSGI app and a configuration dict
as its only two arguments.
"""
factory = _import_factory(local_conf, 'glance.filter_factory')
conf = global_conf.copy()
conf.update(local_conf)
def filter(app):
return factory(app, conf)
return filter

View File

@ -33,9 +33,3 @@ class Cleaner(object):
def run(self): def run(self):
self.cache.clean() self.cache.clean()
def app_factory(global_config, **local_conf):
conf = global_config.copy()
conf.update(local_conf)
return Cleaner(conf)

View File

@ -88,9 +88,3 @@ class Prefetcher(object):
logger.info(_("Successfully cached all %d images"), num_images) logger.info(_("Successfully cached all %d images"), num_images)
return True return True
def app_factory(global_config, **local_conf):
conf = global_config.copy()
conf.update(local_conf)
return Prefetcher(conf)

View File

@ -33,9 +33,3 @@ class Pruner(object):
def run(self): def run(self):
self.cache.prune() self.cache.prune()
def app_factory(global_config, **local_conf):
conf = global_config.copy()
conf.update(local_conf)
return Pruner(conf)

View File

@ -78,9 +78,3 @@ class Queuer(object):
logger.info(_("Successfully queued all %d images"), num_images) logger.info(_("Successfully queued all %d images"), num_images)
return True return True
def app_factory(global_config, **local_conf):
conf = global_config.copy()
conf.update(local_conf)
return Queuer(conf)

View File

@ -45,13 +45,3 @@ class API(wsgi.Router):
action="index_shared_images") action="index_shared_images")
super(API, self).__init__(mapper) super(API, self).__init__(mapper)
def app_factory(global_conf, **local_conf):
"""
paste.deploy app factory for creating Glance reference implementation
registry server apps
"""
conf = global_conf.copy()
conf.update(local_conf)
return API(conf)

View File

@ -1,20 +0,0 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4
# Copyright 2010-2011 OpenStack LLC.
# 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.
# NOTE(bcwaldon): This is done as a convenience for people
# so they don't have to update their paste configs just yet.
from glance.registry.api.v1 import app_factory

View File

@ -180,9 +180,3 @@ def write_queue_file(file_path, uri, delete_time):
f.write('\n'.join([uri, str(int(delete_time))])) f.write('\n'.join([uri, str(int(delete_time))]))
os.chmod(file_path, 0600) os.chmod(file_path, 0600)
os.utime(file_path, (delete_time, delete_time)) os.utime(file_path, (delete_time, delete_time))
def app_factory(global_config, **local_conf):
conf = global_config.copy()
conf.update(local_conf)
return Scrubber(conf)

View File

@ -217,19 +217,25 @@ image_cache_driver = %(image_cache_driver)s
pipeline = versionnegotiation context %(cache_pipeline)s apiv1app pipeline = versionnegotiation context %(cache_pipeline)s apiv1app
[app:apiv1app] [app:apiv1app]
paste.app_factory = glance.api.v1.router:app_factory paste.app_factory = glance.common.wsgi:app_factory
glance.app_factory = glance.api.v1.router:API
[filter:versionnegotiation] [filter:versionnegotiation]
paste.filter_factory = glance.api.middleware.version_negotiation:filter_factory paste.filter_factory = glance.common.wsgi:filter_factory
glance.filter_factory =
glance.api.middleware.version_negotiation:VersionNegotiationFilter
[filter:cache] [filter:cache]
paste.filter_factory = glance.api.middleware.cache:filter_factory paste.filter_factory = glance.common.wsgi:filter_factory
glance.filter_factory = glance.api.middleware.cache:CacheFilter
[filter:cache_manage] [filter:cache_manage]
paste.filter_factory = glance.api.middleware.cache_manage:filter_factory paste.filter_factory = glance.common.wsgi:filter_factory
glance.filter_factory = glance.api.middleware.cache_manage:CacheManageFilter
[filter:context] [filter:context]
paste.filter_factory = glance.common.context:filter_factory paste.filter_factory = glance.common.wsgi:filter_factory
glance.filter_factory = glance.common.context:ContextMiddleware
""" """
@ -267,11 +273,13 @@ owner_is_tenant = %(owner_is_tenant)s
pipeline = context registryapp pipeline = context registryapp
[app:registryapp] [app:registryapp]
paste.app_factory = glance.registry.api.v1:app_factory paste.app_factory = glance.common.wsgi:app_factory
glance.app_factory = glance.registry.api.v1:API
[filter:context] [filter:context]
context_class = glance.registry.context.RequestContext context_class = glance.registry.context.RequestContext
paste.filter_factory = glance.common.context:filter_factory paste.filter_factory = glance.common.wsgi:filter_factory
glance.filter_factory = glance.common.context:ContextMiddleware
""" """
@ -302,7 +310,8 @@ registry_host = 0.0.0.0
registry_port = %(registry_port)s registry_port = %(registry_port)s
[app:glance-scrubber] [app:glance-scrubber]
paste.app_factory = glance.store.scrubber:app_factory paste.app_factory = glance.common.wsgi:app_factory
glance.app_factory = glance.store.scrubber:Scrubber
""" """

View File

@ -158,7 +158,9 @@ admin_token = 999888777666
delay_auth_decision = 1 delay_auth_decision = 1
[filter:keystone_shim] [filter:keystone_shim]
paste.filter_factory = keystone.middleware.glance_auth_token:filter_factory paste.filter_factory = glance.common.wsgi:filter_factory
glance.filter_factory =
keystone.middleware.glance_auth_token:KeystoneContextMiddleware
""" % subs """ % subs

View File

@ -209,16 +209,20 @@ metadata_encryption_key = %(metadata_encryption_key)s
log_file = %(log_file)s log_file = %(log_file)s
[app:glance-pruner] [app:glance-pruner]
paste.app_factory = glance.image_cache.pruner:app_factory paste.app_factory = glance.common.wsgi:app_factory
glance.app_factory = glance.image_cache.pruner:Pruner
[app:glance-prefetcher] [app:glance-prefetcher]
paste.app_factory = glance.image_cache.prefetcher:app_factory paste.app_factory = glance.common.wsgi:app_factory
glance.app_factory = glance.image_cache.prefetcher:Prefetcher
[app:glance-cleaner] [app:glance-cleaner]
paste.app_factory = glance.image_cache.cleaner:app_factory paste.app_factory = glance.common.wsgi:app_factory
glance.app_factory = glance.image_cache.cleaner:Cleaner
[app:glance-queue-image] [app:glance-queue-image]
paste.app_factory = glance.image_cache.queue_image:app_factory paste.app_factory = glance.common.wsgi:app_factory
glance.app_factory = glance.image_cache.queue_image:Queuer
""" % cache_file_options) """ % cache_file_options)
cache_file.flush() cache_file.flush()

View File

@ -338,16 +338,20 @@ metadata_encryption_key = %(metadata_encryption_key)s
log_file = %(log_file)s log_file = %(log_file)s
[app:glance-pruner] [app:glance-pruner]
paste.app_factory = glance.image_cache.pruner:app_factory paste.app_factory = glance.common.wsgi:app_factory
glance.app_factory = glance.image_cache.pruner:Pruner
[app:glance-prefetcher] [app:glance-prefetcher]
paste.app_factory = glance.image_cache.prefetcher:app_factory paste.app_factory = glance.common.wsgi:app_factory
glance.app_factory = glance.image_cache.prefetcher:Prefetcher
[app:glance-cleaner] [app:glance-cleaner]
paste.app_factory = glance.image_cache.cleaner:app_factory paste.app_factory = glance.common.wsgi:app_factory
glance.app_factory = glance.image_cache.cleaner:Cleaner
[app:glance-queue-image] [app:glance-queue-image]
paste.app_factory = glance.image_cache.queue_image:app_factory paste.app_factory = glance.common.wsgi:app_factory
glance.app_factory = glance.image_cache.queue_image:Queuer
""" % cache_file_options) """ % cache_file_options)
cache_file.flush() cache_file.flush()

View File

@ -26,6 +26,7 @@ from glance.api.middleware import version_negotiation
from glance.api.v1 import images from glance.api.v1 import images
from glance.api.v1 import members from glance.api.v1 import members
from glance.common import config from glance.common import config
from glance.common import wsgi
from glance.image_cache import pruner from glance.image_cache import pruner
@ -178,7 +179,7 @@ class TestPasteApp(unittest.TestCase):
self.stubs.Set(os.path, 'join', fake_join) self.stubs.Set(os.path, 'join', fake_join)
self.stubs.Set(config, 'setup_logging', lambda *a: None) self.stubs.Set(config, 'setup_logging', lambda *a: None)
self.stubs.Set(pruner, 'app_factory', lambda *a: 'pruner') self.stubs.Set(wsgi, 'app_factory', lambda *a, **kw: 'pruner')
conf, app = config.load_paste_app('glance-pruner', {}, [], conf, app = config.load_paste_app('glance-pruner', {}, [],
'glance-cache') 'glance-cache')