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

View File

@ -214,19 +214,24 @@ pipeline = versionnegotiation context apiv1app
# pipeline = versionnegotiation authtoken auth-context cachemanage 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]
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]
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]
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]
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]
paste.filter_factory = keystone.middleware.auth_token:filter_factory
@ -240,4 +245,5 @@ auth_uri = http://127.0.0.1:5000/
admin_token = 999888777666
[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
[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]
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]
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]
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
[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]
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]
paste.filter_factory = keystone.middleware.auth_token:filter_factory
@ -76,4 +78,5 @@ admin_token = 999888777666
[filter:auth-context]
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
[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()
serializer = CachedImageSerializer()
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)
for chunk in chunks:
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"))
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.minor_version'] = minor_version
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"]))
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(
auth_tok=auth_tok, user=user, tenant=tenant, roles=roles,
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
from glance.common import exception
from glance.common import utils
class WritableLogger(object):
@ -406,3 +407,52 @@ class Resource(object):
pass
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):
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)
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):
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)
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")
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))]))
os.chmod(file_path, 0600)
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
[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]
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]
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]
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]
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
[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]
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
[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
[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

View File

@ -209,16 +209,20 @@ metadata_encryption_key = %(metadata_encryption_key)s
log_file = %(log_file)s
[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]
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]
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]
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.flush()

View File

@ -338,16 +338,20 @@ metadata_encryption_key = %(metadata_encryption_key)s
log_file = %(log_file)s
[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]
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]
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]
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.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 members
from glance.common import config
from glance.common import wsgi
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(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', {}, [],
'glance-cache')