Merge "A request hook interface for the functional test client"
This commit is contained in:
commit
1a4eb3d4e7
|
@ -15,6 +15,7 @@ limitations under the License.
|
|||
"""
|
||||
|
||||
import abc
|
||||
import logging
|
||||
|
||||
from config import cfg
|
||||
from noauth import NoAuthAuthProvider
|
||||
|
@ -25,6 +26,9 @@ from tempest_lib.auth import KeystoneV2Credentials
|
|||
from tempest_lib.auth import KeystoneV2AuthProvider
|
||||
|
||||
from functionaltests.common.utils import memoized
|
||||
from functionaltests.common import hooks
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class KeystoneV2AuthProviderWithOverridableUrl(KeystoneV2AuthProvider):
|
||||
|
@ -59,6 +63,9 @@ class BaseDesignateClient(RestClient):
|
|||
if not interface.endswith('URL'):
|
||||
interface += "URL"
|
||||
|
||||
self.hooks = []
|
||||
self._populate_hooks()
|
||||
|
||||
super(BaseDesignateClient, self).__init__(
|
||||
auth_provider=self.get_auth_provider(with_token),
|
||||
service=cfg.CONF.designate.service,
|
||||
|
@ -67,6 +74,32 @@ class BaseDesignateClient(RestClient):
|
|||
endpoint_type=interface
|
||||
)
|
||||
|
||||
def _populate_hooks(self):
|
||||
for name in cfg.CONF.testconfig.hooks:
|
||||
LOG.debug("Loading request hook '%s' from config", name)
|
||||
try:
|
||||
cls = hooks.get_class(name)
|
||||
if not cls:
|
||||
LOG.debug("'%s' not found. Call register_hook", name)
|
||||
else:
|
||||
self.hooks.append(cls)
|
||||
except Exception as e:
|
||||
LOG.exception(e)
|
||||
|
||||
def request(self, *args, **kwargs):
|
||||
req_hooks = [hook_class() for hook_class in self.hooks]
|
||||
try:
|
||||
for hook in req_hooks:
|
||||
hook.before(args, kwargs)
|
||||
r, b = super(BaseDesignateClient, self).request(*args, **kwargs)
|
||||
for hook in req_hooks:
|
||||
hook.after(r, b)
|
||||
return r, b
|
||||
except Exception as e:
|
||||
for hook in req_hooks:
|
||||
hook.on_exception(e)
|
||||
raise
|
||||
|
||||
def get_auth_provider(self, with_token=True):
|
||||
if cfg.CONF.noauth.use_noauth:
|
||||
return self._get_noauth_auth_provider()
|
||||
|
|
|
@ -79,6 +79,8 @@ cfg.CONF.register_opts([
|
|||
|
||||
|
||||
cfg.CONF.register_opts([
|
||||
cfg.ListOpt('hooks', default=[],
|
||||
help="The list of request hook class names to enable"),
|
||||
cfg.StrOpt('v2_path_pattern', default='/v2/{path}',
|
||||
help="Specifies how to build the path for the request"),
|
||||
cfg.BoolOpt('no_admin_setup', default=False,
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
"""
|
||||
Copyright 2016 Rackspace
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
# a dictionary mapping the class name to the hook class
|
||||
_HOOKS = {}
|
||||
|
||||
|
||||
def register_hook(cls):
|
||||
"""Register the request hook. This does not enable the hook. Hooks are
|
||||
enable via the config file.
|
||||
|
||||
Usage:
|
||||
>>> register_hook(MyHook)
|
||||
"""
|
||||
_HOOKS[cls.__name__] = cls
|
||||
|
||||
|
||||
def get_class(name):
|
||||
"""Get a hook class by it's class name:
|
||||
|
||||
Usage:
|
||||
>>> get_hook_class('MyHook')
|
||||
"""
|
||||
return _HOOKS.get(name)
|
|
@ -0,0 +1,43 @@
|
|||
"""
|
||||
Copyright 2016 Rackspace
|
||||
|
||||
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.
|
||||
"""
|
||||
|
||||
|
||||
class BaseRequestHook(object):
|
||||
"""When writing your own hook, do three things:
|
||||
|
||||
1. Implement this hook interface
|
||||
2. Register your hook in a global lookup using hook.register_hook()
|
||||
3. Specify the name of your hook in a config file
|
||||
|
||||
A new instance of a hook is created before for each request, for storing
|
||||
per request state if you want.
|
||||
"""
|
||||
|
||||
def before(self, req_args, req_kwargs):
|
||||
"""A hook called before each request
|
||||
|
||||
:param req_args: a list (mutable)
|
||||
:param req_kwargs: a dictionary
|
||||
"""
|
||||
pass
|
||||
|
||||
def after(self, resp, resp_body):
|
||||
"""A hook called after each request"""
|
||||
pass
|
||||
|
||||
def on_exception(self, exception):
|
||||
"""A hook called when an exception occurs on a request"""
|
||||
pass
|
Loading…
Reference in New Issue