Fixing initial PEP8 and python check errors
Note the locale part is temporarily disabled. Need to be re-enabled some time in future. Change-Id: I3b2e0a2f40a171266ec76ad0d3cb4939e48d7ceb
This commit is contained in:
parent
aa59c55c09
commit
9b8989365f
80
doc/source/conf.py
Executable file
80
doc/source/conf.py
Executable file
@ -0,0 +1,80 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# 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 os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.path.insert(0, os.path.abspath('../..'))
|
||||||
|
# -- General configuration ----------------------------------------------------
|
||||||
|
|
||||||
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||||
|
extensions = [
|
||||||
|
'sphinx.ext.autodoc',
|
||||||
|
'sphinx.ext.todo'
|
||||||
|
#'sphinx.ext.intersphinx',
|
||||||
|
#'oslo.sphinx'
|
||||||
|
]
|
||||||
|
|
||||||
|
# autodoc generation is a bit aggressive and a nuisance when doing heavy
|
||||||
|
# text edit cycles.
|
||||||
|
# execute "export SPHINX_DEBUG=1" in your terminal to disable
|
||||||
|
|
||||||
|
# The suffix of source filenames.
|
||||||
|
source_suffix = '.rst'
|
||||||
|
|
||||||
|
# The master toctree document.
|
||||||
|
master_doc = 'index'
|
||||||
|
|
||||||
|
# General information about the project.
|
||||||
|
project = u'senlin'
|
||||||
|
copyright = u'2015, OpenStack Foundation'
|
||||||
|
|
||||||
|
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||||
|
add_function_parentheses = True
|
||||||
|
|
||||||
|
# If true, the current module name will be prepended to all description
|
||||||
|
# unit titles (such as .. function::).
|
||||||
|
add_module_names = True
|
||||||
|
|
||||||
|
# The name of the Pygments (syntax highlighting) style to use.
|
||||||
|
pygments_style = 'sphinx'
|
||||||
|
|
||||||
|
# -- Options for HTML output --------------------------------------------------
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. Major themes that come with
|
||||||
|
# Sphinx are currently 'default' and 'sphinxdoc'.
|
||||||
|
# html_theme_path = ["."]
|
||||||
|
# html_theme = '_theme'
|
||||||
|
# html_static_path = ['static']
|
||||||
|
|
||||||
|
# Output file base name for HTML help builder.
|
||||||
|
htmlhelp_basename = '%sdoc' % project
|
||||||
|
|
||||||
|
# Grouping the document tree into LaTeX files. List of tuples
|
||||||
|
# (source start file, target name, title, author, documentclass
|
||||||
|
# [howto/manual]).
|
||||||
|
latex_documents = [
|
||||||
|
('index',
|
||||||
|
'%s.tex' % project,
|
||||||
|
u'%s Documentation' % project,
|
||||||
|
u'OpenStack Foundation', 'manual'),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Example configuration for intersphinx: refer to the Python standard library.
|
||||||
|
#intersphinx_mapping = {'http://docs.python.org/': None}
|
||||||
|
|
||||||
|
[extensions]
|
||||||
|
todo_include_todos=True
|
||||||
|
|
@ -9,7 +9,7 @@ eventlet>=0.16.1
|
|||||||
greenlet>=0.3.2
|
greenlet>=0.3.2
|
||||||
httplib2>=0.7.5
|
httplib2>=0.7.5
|
||||||
iso8601>=0.1.9
|
iso8601>=0.1.9
|
||||||
keystonemiddleware>=1.0.0,<1.4.0
|
keystonemiddleware>=1.0.0
|
||||||
kombu>=2.5.0
|
kombu>=2.5.0
|
||||||
lxml>=2.3
|
lxml>=2.3
|
||||||
netaddr>=0.7.12
|
netaddr>=0.7.12
|
||||||
@ -29,9 +29,9 @@ python-openstacksdk>=0.4.1
|
|||||||
python-heatclient>=0.2.9
|
python-heatclient>=0.2.9
|
||||||
python-keystoneclient>=1.1.0
|
python-keystoneclient>=1.1.0
|
||||||
python-neutronclient>=2.3.6,<3
|
python-neutronclient>=2.3.6,<3
|
||||||
python-novaclient>=2.18.0
|
python-novaclient>=2.18.0,!=2.21.0
|
||||||
PyYAML>=3.1.0
|
PyYAML>=3.1.0
|
||||||
qpid-python
|
# qpid-python
|
||||||
requests>=2.2.0,!=2.4.0
|
requests>=2.2.0,!=2.4.0
|
||||||
Routes>=1.12.3,!=2.0
|
Routes>=1.12.3,!=2.0
|
||||||
six>=1.9.0
|
six>=1.9.0
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright © 2013 Unitedstack Inc.
|
|
||||||
#
|
|
||||||
# Author: Jianing YANG (jianingy@unitedstack.com)
|
|
||||||
#
|
|
||||||
# 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
|
||||||
@ -16,9 +12,9 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
"""A middleware that turns exceptions into parsable string. Inspired by
|
'''
|
||||||
Cinder's faultwrapper
|
A middleware that turns exceptions into parsable string.
|
||||||
"""
|
'''
|
||||||
|
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
@ -92,6 +88,7 @@ class FaultWrapper(wsgi.Middleware):
|
|||||||
|
|
||||||
def _error(self, ex):
|
def _error(self, ex):
|
||||||
trace = None
|
trace = None
|
||||||
|
traceback_marker = 'Traceback (most recent call last)'
|
||||||
webob_exc = None
|
webob_exc = None
|
||||||
if isinstance(ex, exception.HTTPExceptionDisguise):
|
if isinstance(ex, exception.HTTPExceptionDisguise):
|
||||||
# An HTTP exception was disguised so it could make it here
|
# An HTTP exception was disguised so it could make it here
|
||||||
@ -108,10 +105,19 @@ class FaultWrapper(wsgi.Middleware):
|
|||||||
ex_type = ex_type[:-len('_Remote')]
|
ex_type = ex_type[:-len('_Remote')]
|
||||||
|
|
||||||
full_message = six.text_type(ex)
|
full_message = six.text_type(ex)
|
||||||
if full_message.find('\n') > -1 and is_remote:
|
if '\n' in full_message and is_remote:
|
||||||
message, msg_trace = full_message.split('\n', 1)
|
message, msg_trace = full_message.split('\n', 1)
|
||||||
|
elif traceback_marker in full_message:
|
||||||
|
message, msg_trace = full_message.split(traceback_marker, 1)
|
||||||
|
message = message.rstrip('\n')
|
||||||
|
msg_trace = traceback_marker + msg_trace
|
||||||
else:
|
else:
|
||||||
msg_trace = traceback.format_exc()
|
if six.PY3:
|
||||||
|
msg_trace = traceback.format_exception(type(ex), ex,
|
||||||
|
ex.__traceback__)
|
||||||
|
else:
|
||||||
|
msg_trace = traceback.format_exc()
|
||||||
|
|
||||||
message = full_message
|
message = full_message
|
||||||
|
|
||||||
if isinstance(ex, exception.SenlinException):
|
if isinstance(ex, exception.SenlinException):
|
||||||
|
@ -25,11 +25,12 @@ cfg.CONF.register_opts(ssl_middleware_opts)
|
|||||||
|
|
||||||
|
|
||||||
class SSLMiddleware(wsgi.Middleware):
|
class SSLMiddleware(wsgi.Middleware):
|
||||||
"""A middleware that replaces the request wsgi.url_scheme environment
|
'''Middleware for servers behind a SSL termination proxy.
|
||||||
|
|
||||||
|
A middleware that replaces the request wsgi.url_scheme environment
|
||||||
variable with the value of HTTP header configured in
|
variable with the value of HTTP header configured in
|
||||||
secure_proxy_ssl_header if exists in the incoming request.
|
secure_proxy_ssl_header if exists in the incoming request.
|
||||||
This is useful if the server is behind a SSL termination proxy.
|
'''
|
||||||
"""
|
|
||||||
def __init__(self, application):
|
def __init__(self, application):
|
||||||
super(SSLMiddleware, self).__init__(application)
|
super(SSLMiddleware, self).__init__(application)
|
||||||
self.secure_proxy_ssl_header = 'HTTP_{0}'.format(
|
self.secure_proxy_ssl_header = 'HTTP_{0}'.format(
|
||||||
|
@ -20,9 +20,7 @@ from senlin.rpc import client as rpc_client
|
|||||||
|
|
||||||
|
|
||||||
class BuildInfoController(object):
|
class BuildInfoController(object):
|
||||||
'''WSGI controller for BuildInfo in Senlin v1 API.
|
'''WSGI controller for BuildInfo in Senlin v1 API.'''
|
||||||
Returns build information for current app
|
|
||||||
'''
|
|
||||||
|
|
||||||
# Define request scope (must match what is in policy.json)
|
# Define request scope (must match what is in policy.json)
|
||||||
REQUEST_SCOPE = 'build_info'
|
REQUEST_SCOPE = 'build_info'
|
||||||
|
@ -184,7 +184,7 @@ class ClusterController(object):
|
|||||||
if len(body) > 1:
|
if len(body) > 1:
|
||||||
raise exc.HTTPBadRequest(_('Multiple actions specified'))
|
raise exc.HTTPBadRequest(_('Multiple actions specified'))
|
||||||
|
|
||||||
this_action = body.keys()[0]
|
this_action = list(body.keys())[0]
|
||||||
if this_action not in self.SUPPORTED_ACTIONS:
|
if this_action not in self.SUPPORTED_ACTIONS:
|
||||||
msg = _("Unrecognized action '%s' specified") % this_action
|
msg = _("Unrecognized action '%s' specified") % this_action
|
||||||
raise exc.HTTPBadRequest(msg)
|
raise exc.HTTPBadRequest(msg)
|
||||||
|
@ -180,7 +180,7 @@ class NodeController(object):
|
|||||||
if len(body) > 1:
|
if len(body) > 1:
|
||||||
raise exc.HTTPBadRequest(_('Multiple actions specified'))
|
raise exc.HTTPBadRequest(_('Multiple actions specified'))
|
||||||
|
|
||||||
this_action = body.keys()[0]
|
this_action = list(body.keys())[0]
|
||||||
if this_action not in self.SUPPORTED_ACTIONS:
|
if this_action not in self.SUPPORTED_ACTIONS:
|
||||||
msg = _('Unrecognized action "%s" specified') % this_action
|
msg = _('Unrecognized action "%s" specified') % this_action
|
||||||
raise exc.HTTPBadRequest(msg)
|
raise exc.HTTPBadRequest(msg)
|
||||||
|
@ -15,8 +15,13 @@
|
|||||||
Controller that returns information on the senlin API versions
|
Controller that returns information on the senlin API versions
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import httplib
|
|
||||||
import json
|
import json
|
||||||
|
import six
|
||||||
|
|
||||||
|
if six.PY2:
|
||||||
|
import httplib
|
||||||
|
else:
|
||||||
|
import http.client as httplib
|
||||||
|
|
||||||
import webob.dec
|
import webob.dec
|
||||||
|
|
||||||
|
@ -28,14 +28,15 @@ CONF = cfg.CONF
|
|||||||
|
|
||||||
|
|
||||||
def do_db_version():
|
def do_db_version():
|
||||||
"""Print database's current migration level."""
|
'''Print database's current migration level.'''
|
||||||
print(api.db_version(api.get_engine()))
|
print(api.db_version(api.get_engine()))
|
||||||
|
|
||||||
|
|
||||||
def do_db_sync():
|
def do_db_sync():
|
||||||
"""Place a database under migration control and upgrade,
|
'''Place a database under migration control and upgrade.
|
||||||
creating first if necessary.
|
|
||||||
"""
|
DB is created first if necessary.
|
||||||
|
'''
|
||||||
api.db_sync(api.get_engine(), CONF.command.version)
|
api.db_sync(api.get_engine(), CONF.command.version)
|
||||||
|
|
||||||
|
|
||||||
|
@ -132,16 +132,19 @@ for group, opts in list_opts():
|
|||||||
|
|
||||||
|
|
||||||
def _get_deployment_flavor():
|
def _get_deployment_flavor():
|
||||||
"""Retrieve the paste_deploy.flavor config item, formatted appropriately
|
"""Retrieve paste_deploy.flavor config item.
|
||||||
for appending to the application name.
|
|
||||||
|
The result is formatted appropriately to be appended to the
|
||||||
|
application name.
|
||||||
"""
|
"""
|
||||||
flavor = cfg.CONF.paste_deploy.flavor
|
flavor = cfg.CONF.paste_deploy.flavor
|
||||||
return '' if not flavor else ('-' + flavor)
|
return '' if not flavor else ('-' + flavor)
|
||||||
|
|
||||||
|
|
||||||
def _get_deployment_config_file():
|
def _get_deployment_config_file():
|
||||||
"""Retrieve the deployment_config_file config item, formatted as an
|
"""Retrieve item from deployment_config_file.
|
||||||
absolute pathname.
|
|
||||||
|
The retrieved item is formatted as an absolute pathname.
|
||||||
"""
|
"""
|
||||||
config_path = cfg.CONF.find_file(
|
config_path = cfg.CONF.find_file(
|
||||||
cfg.CONF.paste_deploy['api_paste_config'])
|
cfg.CONF.paste_deploy['api_paste_config'])
|
||||||
|
@ -40,6 +40,7 @@ class RequestContext(context.RequestContext):
|
|||||||
read_only=False, show_deleted=False,
|
read_only=False, show_deleted=False,
|
||||||
request_id=None, **kwargs):
|
request_id=None, **kwargs):
|
||||||
'''Initializer of request context.
|
'''Initializer of request context.
|
||||||
|
|
||||||
:param kwargs: Extra arguments that might be present, but we ignore
|
:param kwargs: Extra arguments that might be present, but we ignore
|
||||||
because they possibly came in from older rpc messages.
|
because they possibly came in from older rpc messages.
|
||||||
'''
|
'''
|
||||||
@ -134,9 +135,7 @@ class ContextMiddleware(wsgi.Middleware):
|
|||||||
return self.ctxcls(*args, **kwargs)
|
return self.ctxcls(*args, **kwargs)
|
||||||
|
|
||||||
def process_request(self, req):
|
def process_request(self, req):
|
||||||
'''Extract any authentication information in the request and
|
'''Build context from authentication info extracted from request.'''
|
||||||
construct an appropriate context from it.
|
|
||||||
'''
|
|
||||||
|
|
||||||
headers = req.headers
|
headers = req.headers
|
||||||
environ = req.environ
|
environ = req.environ
|
||||||
|
@ -60,7 +60,7 @@ def wrap_exception(notifier=None, publisher_id=None, event_type=None,
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Save exception since it can be clobbered during processing
|
# Save exception since it can be clobbered during processing
|
||||||
# below before we can re-raise
|
# below before we can re-raise
|
||||||
exc_info = sys.exc_info()
|
# exc_info = sys.exc_info()
|
||||||
|
|
||||||
if notifier:
|
if notifier:
|
||||||
payload = dict(args=args, exception=e)
|
payload = dict(args=args, exception=e)
|
||||||
@ -82,7 +82,8 @@ def wrap_exception(notifier=None, publisher_id=None, event_type=None,
|
|||||||
payload)
|
payload)
|
||||||
|
|
||||||
# re-raise original exception since it may have been clobbered
|
# re-raise original exception since it may have been clobbered
|
||||||
raise exc_info[0], exc_info[1], exc_info[2]
|
# raise exc_info[0], exc_info[1], exc_info[2]
|
||||||
|
raise
|
||||||
|
|
||||||
return functools.wraps(f)(wrapped)
|
return functools.wraps(f)(wrapped)
|
||||||
return inner
|
return inner
|
||||||
@ -100,11 +101,12 @@ class SenlinException(Exception):
|
|||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
self.kwargs = kwargs
|
self.kwargs = kwargs
|
||||||
|
self.__context__ = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.message = self.msg_fmt % kwargs
|
self.message = self.msg_fmt % kwargs
|
||||||
except KeyError:
|
except KeyError:
|
||||||
exc_info = sys.exc_info()
|
# exc_info = sys.exc_info()
|
||||||
# if kwargs doesn't match a variable in the message
|
# if kwargs doesn't match a variable in the message
|
||||||
# log the issue and the kwargs
|
# log the issue and the kwargs
|
||||||
LOG.exception(_LE('Exception in string format operation'))
|
LOG.exception(_LE('Exception in string format operation'))
|
||||||
@ -112,13 +114,14 @@ class SenlinException(Exception):
|
|||||||
LOG.error("%s: %s" % (name, value)) # noqa
|
LOG.error("%s: %s" % (name, value)) # noqa
|
||||||
|
|
||||||
if _FATAL_EXCEPTION_FORMAT_ERRORS:
|
if _FATAL_EXCEPTION_FORMAT_ERRORS:
|
||||||
raise exc_info[0], exc_info[1], exc_info[2]
|
raise
|
||||||
|
# raise exc_info[0], exc_info[1], exc_info[2]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return unicode(self.message).encode('UTF-8')
|
return six.text_type(self.message)
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return unicode(self.message)
|
return six.text_type(self.message)
|
||||||
|
|
||||||
def __deepcopy__(self, memo):
|
def __deepcopy__(self, memo):
|
||||||
return self.__class__(**self.kwargs)
|
return self.__class__(**self.kwargs)
|
||||||
@ -358,8 +361,10 @@ class DriverFailure(SenlinException):
|
|||||||
|
|
||||||
|
|
||||||
class HTTPExceptionDisguise(Exception):
|
class HTTPExceptionDisguise(Exception):
|
||||||
"""Disguises HTTP exceptions so they can be handled by the webob fault
|
"""Disguises HTTP exceptions.
|
||||||
application in the wsgi pipeline.
|
|
||||||
|
The purpose is to let them be handled by the webob fault application
|
||||||
|
in the wsgi pipeline.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, exception):
|
def __init__(self, exception):
|
||||||
|
@ -29,7 +29,7 @@ class AnyIndexDict(collections.Mapping):
|
|||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
if key != '*' and not isinstance(key, (int, long)):
|
if key != '*' and not isinstance(key, six.integer_types):
|
||||||
raise KeyError(_('Invalid key %s') % str(key))
|
raise KeyError(_('Invalid key %s') % str(key))
|
||||||
|
|
||||||
return self.value
|
return self.value
|
||||||
@ -188,7 +188,7 @@ class Integer(Schema):
|
|||||||
return super(Integer, self).__getitem__(key)
|
return super(Integer, self).__getitem__(key)
|
||||||
|
|
||||||
def to_schema_type(self, value):
|
def to_schema_type(self, value):
|
||||||
if isinstance(value, (int, long)):
|
if isinstance(value, six.integer_types):
|
||||||
return value
|
return value
|
||||||
try:
|
try:
|
||||||
num = int(value)
|
num = int(value)
|
||||||
@ -206,7 +206,7 @@ class Integer(Schema):
|
|||||||
raise exception.SpecValidationFailed(message=msg)
|
raise exception.SpecValidationFailed(message=msg)
|
||||||
|
|
||||||
def validate(self, value, context=None):
|
def validate(self, value, context=None):
|
||||||
if not isinstance(value, (int, long)):
|
if not isinstance(value, six.integer_types):
|
||||||
value = self.resolve(value)
|
value = self.resolve(value)
|
||||||
|
|
||||||
self.validate_constraints(value, self, context)
|
self.validate_constraints(value, self, context)
|
||||||
@ -389,6 +389,7 @@ class Spec(collections.Mapping):
|
|||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
'''Number of items in the spec.
|
'''Number of items in the spec.
|
||||||
|
|
||||||
A spec always contain all keys though some may be not specified.
|
A spec always contain all keys though some may be not specified.
|
||||||
'''
|
'''
|
||||||
return len(self._schema)
|
return len(self._schema)
|
||||||
|
@ -130,6 +130,7 @@ _EXCEPTION_MAP = {
|
|||||||
|
|
||||||
def parse_exception(ex):
|
def parse_exception(ex):
|
||||||
'''Parse exception code and yield useful information.
|
'''Parse exception code and yield useful information.
|
||||||
|
|
||||||
:param details: details of the exception.
|
:param details: details of the exception.
|
||||||
'''
|
'''
|
||||||
if isinstance(ex, exc.HttpException):
|
if isinstance(ex, exc.HttpException):
|
||||||
|
@ -18,6 +18,7 @@ import datetime
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
from oslo_utils import encodeutils
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -36,4 +37,4 @@ class JSONResponseSerializer(object):
|
|||||||
|
|
||||||
def default(self, response, result):
|
def default(self, response, result):
|
||||||
response.content_type = 'application/json'
|
response.content_type = 'application/json'
|
||||||
response.body = self.to_json(result)
|
response.body = encodeutils.safe_encode(self.to_json(result))
|
||||||
|
@ -21,7 +21,8 @@ LOG = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class SenlinTrust(object):
|
class SenlinTrust(object):
|
||||||
'''Stores information about the trust of requester.
|
'''Stores information about the trust of requester.
|
||||||
e.g. roles, trustor_user_id, trustee_user_id.
|
|
||||||
|
Sample information include roles, trustor_user_id, trustee_user_id.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, id=None, project_id=None,
|
def __init__(self, id=None, project_id=None,
|
||||||
@ -100,11 +101,11 @@ def list_trust(context, trustee_user_id=None, trustor_user_id=None):
|
|||||||
|
|
||||||
|
|
||||||
class TrustMiddleware(wsgi.Middleware):
|
class TrustMiddleware(wsgi.Middleware):
|
||||||
"""This middleware gets trusts information of the requester
|
'''Extract trust info from request.
|
||||||
and fill it into request context. This information will
|
|
||||||
be used by senlin engine later to support privilege
|
The extracted information is filled into the request context.
|
||||||
management.
|
Senlin engine will use this information for access control.
|
||||||
"""
|
'''
|
||||||
def process_request(self, req):
|
def process_request(self, req):
|
||||||
# Query trust list with detail information
|
# Query trust list with detail information
|
||||||
trusts = list_trust(req.context, req.context.user_id)
|
trusts = list_trust(req.context, req.context.user_id)
|
||||||
|
@ -23,6 +23,7 @@ import uuid
|
|||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
from oslo_utils import encodeutils
|
||||||
from oslo_utils import strutils
|
from oslo_utils import strutils
|
||||||
|
|
||||||
from senlin.common import exception
|
from senlin.common import exception
|
||||||
@ -62,7 +63,8 @@ def get_id(source_uuid):
|
|||||||
# (see RFC4122, Section 4.4)
|
# (see RFC4122, Section 4.4)
|
||||||
random_bytes = _to_byte_string(source_uuid.time, 60)
|
random_bytes = _to_byte_string(source_uuid.time, 60)
|
||||||
# The first 12 bytes (= 60 bits) of base32-encoded output is our data
|
# The first 12 bytes (= 60 bits) of base32-encoded output is our data
|
||||||
encoded = base64.b32encode(random_bytes)[:12]
|
res = base64.b32encode(encodeutils.safe_encode(random_bytes))
|
||||||
|
encoded = encodeutils.safe_decode(res)[:12]
|
||||||
|
|
||||||
return encoded.lower()
|
return encoded.lower()
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ import eventlet.greenio
|
|||||||
import eventlet.wsgi
|
import eventlet.wsgi
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
import oslo_i18n
|
import oslo_i18n
|
||||||
|
from oslo_utils import encodeutils
|
||||||
from oslo_utils import importutils
|
from oslo_utils import importutils
|
||||||
from paste import deploy
|
from paste import deploy
|
||||||
import routes
|
import routes
|
||||||
@ -320,8 +321,9 @@ class Middleware(object):
|
|||||||
|
|
||||||
|
|
||||||
class Debug(Middleware):
|
class Debug(Middleware):
|
||||||
'''Helper class that can be inserted into any WSGI application chain
|
'''Helper class that can be inserted into any WSGI application chain.
|
||||||
to get information about the request and response.
|
|
||||||
|
Use this to get information about the request and response.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@webob.dec.wsgify
|
@webob.dec.wsgify
|
||||||
@ -329,13 +331,13 @@ class Debug(Middleware):
|
|||||||
print(("*" * 40) + " REQUEST ENVIRON")
|
print(("*" * 40) + " REQUEST ENVIRON")
|
||||||
for key, value in req.environ.items():
|
for key, value in req.environ.items():
|
||||||
print(key, "=", value)
|
print(key, "=", value)
|
||||||
print
|
print('')
|
||||||
resp = req.get_response(self.application)
|
resp = req.get_response(self.application)
|
||||||
|
|
||||||
print(("*" * 40) + " RESPONSE HEADERS")
|
print(("*" * 40) + " RESPONSE HEADERS")
|
||||||
for (key, value) in six.iteritems(resp.headers):
|
for (key, value) in six.iteritems(resp.headers):
|
||||||
print(key, "=", value)
|
print(key, "=", value)
|
||||||
print
|
print('')
|
||||||
|
|
||||||
resp.app_iter = self.print_generator(resp.app_iter)
|
resp.app_iter = self.print_generator(resp.app_iter)
|
||||||
|
|
||||||
@ -350,7 +352,7 @@ class Debug(Middleware):
|
|||||||
sys.stdout.write(part)
|
sys.stdout.write(part)
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
yield part
|
yield part
|
||||||
print
|
print('')
|
||||||
|
|
||||||
|
|
||||||
def debug_filter(app, conf, **local_conf):
|
def debug_filter(app, conf, **local_conf):
|
||||||
@ -400,9 +402,10 @@ class Router(object):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
@webob.dec.wsgify
|
@webob.dec.wsgify
|
||||||
def _dispatch(req):
|
def _dispatch(req):
|
||||||
'''Called by self._router after matching the incoming request to
|
'''Private dispatcher method.
|
||||||
a route and putting the information into req.environ.
|
|
||||||
|
|
||||||
|
Called by self._router() after matching the incoming request to
|
||||||
|
a route and putting the information into req.environ.
|
||||||
Either returns 404 or the routed WSGI app's response.
|
Either returns 404 or the routed WSGI app's response.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
@ -452,16 +455,16 @@ def is_json_content_type(request):
|
|||||||
aws_content_type = request.params.get("ContentType")
|
aws_content_type = request.params.get("ContentType")
|
||||||
except Exception:
|
except Exception:
|
||||||
aws_content_type = None
|
aws_content_type = None
|
||||||
#respect aws_content_type when both available
|
# respect aws_content_type when both available
|
||||||
content_type = aws_content_type or request.content_type
|
content_type = aws_content_type or request.content_type
|
||||||
else:
|
else:
|
||||||
content_type = request.content_type
|
content_type = request.content_type
|
||||||
#bug #1887882
|
# bug #1887882
|
||||||
#for back compatible for null or plain content type
|
# for back compatible for null or plain content type
|
||||||
if not content_type or content_type.startswith('text/plain'):
|
if not content_type or content_type.startswith('text/plain'):
|
||||||
content_type = 'application/json'
|
content_type = 'application/json'
|
||||||
if content_type in ('JSON', 'application/json')\
|
if content_type in ('JSON', 'application/json')\
|
||||||
and request.body.startswith('{'):
|
and request.body.startswith(encodeutils.safe_encode('{')):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -472,6 +475,8 @@ class JSONRequestDeserializer(object):
|
|||||||
|
|
||||||
:param request: Webob.Request object
|
:param request: Webob.Request object
|
||||||
'''
|
'''
|
||||||
|
if request is None or request.content_length is None:
|
||||||
|
return False
|
||||||
|
|
||||||
if request.content_length > 0 and is_json_content_type(request):
|
if request.content_length > 0 and is_json_content_type(request):
|
||||||
return True
|
return True
|
||||||
@ -486,7 +491,7 @@ class JSONRequestDeserializer(object):
|
|||||||
{'len': len(datastring),
|
{'len': len(datastring),
|
||||||
'limit': cfg.CONF.max_json_body_size}
|
'limit': cfg.CONF.max_json_body_size}
|
||||||
raise exception.RequestLimitExceeded(message=msg)
|
raise exception.RequestLimitExceeded(message=msg)
|
||||||
return json.loads(datastring)
|
return json.loads(encodeutils.safe_decode(datastring))
|
||||||
except ValueError as ex:
|
except ValueError as ex:
|
||||||
raise webob.exc.HTTPBadRequest(six.text_type(ex))
|
raise webob.exc.HTTPBadRequest(six.text_type(ex))
|
||||||
|
|
||||||
@ -515,13 +520,14 @@ class Resource(object):
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, controller, deserializer, serializer=None):
|
def __init__(self, controller, deserializer, serializer=None):
|
||||||
"""Initializer.
|
'''Initializer.
|
||||||
|
|
||||||
:param controller: object that implement methods created by routes lib
|
:param controller: object that implement methods created by routes lib
|
||||||
:param deserializer: object that supports webob request deserialization
|
:param deserializer: object that supports webob request deserialization
|
||||||
through controller-like actions
|
through controller-like actions
|
||||||
:param serializer: object that supports webob response serialization
|
:param serializer: object that supports webob response serialization
|
||||||
through controller-like actions
|
through controller-like actions
|
||||||
"""
|
'''
|
||||||
self.controller = controller
|
self.controller = controller
|
||||||
self.deserializer = deserializer
|
self.deserializer = deserializer
|
||||||
self.serializer = serializer
|
self.serializer = serializer
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
|
|
||||||
from senlin.common import sdk
|
from senlin.common import sdk
|
||||||
from senlin.drivers import base
|
from senlin.drivers import base
|
||||||
from openstack import user_preference
|
|
||||||
from senlin.openstack.orchestration.v1 import stack
|
from senlin.openstack.orchestration.v1 import stack
|
||||||
|
|
||||||
|
|
||||||
|
@ -406,8 +406,8 @@ class ClusterAction(base.Action):
|
|||||||
return result, reason
|
return result, reason
|
||||||
|
|
||||||
def do_attach_policy(self, cluster, policy_data):
|
def do_attach_policy(self, cluster, policy_data):
|
||||||
'''Attach policy to the cluster.
|
'''Attach policy to the cluster.'''
|
||||||
'''
|
|
||||||
policy_id = self.inputs.get('policy_id', None)
|
policy_id = self.inputs.get('policy_id', None)
|
||||||
if not policy_id:
|
if not policy_id:
|
||||||
raise exception.PolicyNotSpecified()
|
raise exception.PolicyNotSpecified()
|
||||||
@ -506,6 +506,7 @@ class ClusterAction(base.Action):
|
|||||||
|
|
||||||
def execute(self, **kwargs):
|
def execute(self, **kwargs):
|
||||||
'''Wrapper of action execution.
|
'''Wrapper of action execution.
|
||||||
|
|
||||||
This is mainly a wrapper that executes an action with cluster lock
|
This is mainly a wrapper that executes an action with cluster lock
|
||||||
acquired.
|
acquired.
|
||||||
:return: A tuple (res, reason) that indicates whether the execution
|
:return: A tuple (res, reason) that indicates whether the execution
|
||||||
@ -515,8 +516,8 @@ class ClusterAction(base.Action):
|
|||||||
try:
|
try:
|
||||||
cluster = cluster_mod.Cluster.load(self.context, self.target)
|
cluster = cluster_mod.Cluster.load(self.context, self.target)
|
||||||
except exception.NotFound:
|
except exception.NotFound:
|
||||||
reason = _('Cluster %(id)s not found') % {'id': self.target}
|
reason = _LE('Cluster %(id)s not found') % {'id': self.target}
|
||||||
LOG.error(_LE(reason))
|
LOG.error(reason)
|
||||||
return self.RES_ERROR, reason
|
return self.RES_ERROR, reason
|
||||||
|
|
||||||
# Try to lock cluster before do real operation
|
# Try to lock cluster before do real operation
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
from senlin.common import exception
|
from senlin.common import exception
|
||||||
from senlin.common.i18n import _
|
|
||||||
from senlin.common.i18n import _LE
|
from senlin.common.i18n import _LE
|
||||||
from senlin.engine.actions import base
|
from senlin.engine.actions import base
|
||||||
from senlin.engine import node as node_mod
|
from senlin.engine import node as node_mod
|
||||||
@ -88,8 +87,8 @@ class NodeAction(base.Action):
|
|||||||
try:
|
try:
|
||||||
node = node_mod.Node.load(self.context, node_id=self.target)
|
node = node_mod.Node.load(self.context, node_id=self.target)
|
||||||
except exception.NotFound:
|
except exception.NotFound:
|
||||||
reason = _('Node with id (%s) is not found') % self.target
|
reason = _LE('Node with id (%s) is not found') % self.target
|
||||||
LOG.error(_LE(reason))
|
LOG.error(reason)
|
||||||
return self.RES_ERROR, reason
|
return self.RES_ERROR, reason
|
||||||
|
|
||||||
reason = ''
|
reason = ''
|
||||||
|
@ -254,7 +254,7 @@ class Cluster(periodic_task.PeriodicTasks):
|
|||||||
|
|
||||||
Set cluster status to DELETED.
|
Set cluster status to DELETED.
|
||||||
'''
|
'''
|
||||||
#self.set_status(context, self.DELETED)
|
# self.set_status(context, self.DELETED)
|
||||||
db_api.cluster_delete(context, self.id)
|
db_api.cluster_delete(context, self.id)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -50,9 +50,7 @@ class Dispatcher(service.Service):
|
|||||||
server.start()
|
server.start()
|
||||||
|
|
||||||
def listening(self, context):
|
def listening(self, context):
|
||||||
'''Respond affirmatively to confirm that the engine performing the
|
'''Respond affirmatively to confirm that engine is still alive.'''
|
||||||
action is still alive.
|
|
||||||
'''
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def new_action(self, context, action_id=None):
|
def new_action(self, context, action_id=None):
|
||||||
|
@ -18,8 +18,6 @@ take corresponding actions to recover the clusters based on the pre-defined
|
|||||||
health policies.
|
health policies.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import random
|
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
import oslo_messaging
|
import oslo_messaging
|
||||||
@ -58,14 +56,14 @@ class Health_Manager(service.Service, periodic_task.PeriodicTasks):
|
|||||||
self.topic = topic
|
self.topic = topic
|
||||||
self.version = version
|
self.version = version
|
||||||
|
|
||||||
#params for periodic running task
|
# params for periodic running task
|
||||||
self.periodic_interval_max = CONF.periodic_interval_max
|
self.periodic_interval_max = CONF.periodic_interval_max
|
||||||
self.periodic_enable = CONF.periodic_enable
|
self.periodic_enable = CONF.periodic_enable
|
||||||
self.periodic_fuzzy_delay = CONF.periodic_fuzzy_delay
|
self.periodic_fuzzy_delay = CONF.periodic_fuzzy_delay
|
||||||
|
|
||||||
def periodic_tasks(self, raise_on_error=False):
|
def periodic_tasks(self, raise_on_error=False):
|
||||||
"""Tasks to be run at a periodic interval."""
|
"""Tasks to be run at a periodic interval."""
|
||||||
#TODO(anyone): iterate clusters and call their periodic_tasks
|
# TODO(anyone): iterate clusters and call their periodic_tasks
|
||||||
return self.periodic_interval_max
|
return self.periodic_interval_max
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
@ -77,18 +75,16 @@ class Health_Manager(service.Service, periodic_task.PeriodicTasks):
|
|||||||
server.start()
|
server.start()
|
||||||
|
|
||||||
if self.periodic_enable:
|
if self.periodic_enable:
|
||||||
if self.periodic_fuzzy_delay:
|
# if self.periodic_fuzzy_delay:
|
||||||
initial_delay = random.randint(0, self.periodic_fuzzy_delay)
|
# initial_delay = random.randint(0, self.periodic_fuzzy_delay)
|
||||||
else:
|
# else:
|
||||||
initial_delay = None
|
# initial_delay = None
|
||||||
|
|
||||||
self.threadgroup.add_timer(self.periodic_interval_max,
|
self.threadgroup.add_timer(self.periodic_interval_max,
|
||||||
self.periodic_tasks)
|
self.periodic_tasks)
|
||||||
|
|
||||||
def listening(self, context):
|
def listening(self, context):
|
||||||
'''Respond affirmatively to confirm that the engine performing the
|
'''Respond to confirm that the engine is still alive.'''
|
||||||
action is still alive.
|
|
||||||
'''
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
|
@ -10,8 +10,11 @@
|
|||||||
# 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 io
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from oslo_utils import encodeutils
|
||||||
import requests
|
import requests
|
||||||
import six
|
import six
|
||||||
from six.moves import urllib
|
from six.moves import urllib
|
||||||
@ -37,7 +40,7 @@ else:
|
|||||||
|
|
||||||
class YamlLoader(Loader):
|
class YamlLoader(Loader):
|
||||||
def __init__(self, stream):
|
def __init__(self, stream):
|
||||||
if isinstance(stream, file):
|
if isinstance(stream, io.IOBase):
|
||||||
self._curdir = os.path.split(stream.name)[0]
|
self._curdir = os.path.split(stream.name)[0]
|
||||||
else:
|
else:
|
||||||
self._curdir = './'
|
self._curdir = './'
|
||||||
@ -82,7 +85,7 @@ YamlLoader.add_constructor(u'tag:yaml.org,2002:timestamp',
|
|||||||
|
|
||||||
def simple_parse(in_str):
|
def simple_parse(in_str):
|
||||||
try:
|
try:
|
||||||
out_dict = json.loads(in_str)
|
out_dict = json.loads(encodeutils.safe_decode(in_str))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
try:
|
try:
|
||||||
out_dict = yaml.load(in_str, Loader=YamlLoader)
|
out_dict = yaml.load(in_str, Loader=YamlLoader)
|
||||||
|
@ -100,8 +100,9 @@ class ThreadGroupManager(object):
|
|||||||
action.signal(context, action.SIG_RESUME)
|
action.signal(context, action.SIG_RESUME)
|
||||||
|
|
||||||
def add_timer(self, interval, func, *args, **kwargs):
|
def add_timer(self, interval, func, *args, **kwargs):
|
||||||
'''Define a periodic task, to be run in a separate thread, in the
|
'''Define a periodic task to be run in the thread group.
|
||||||
target threadgroups.
|
|
||||||
|
The task will be executed in a separate green thread.
|
||||||
Interval is from cfg.CONF.periodic_interval
|
Interval is from cfg.CONF.periodic_interval
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
@ -197,7 +197,8 @@ class EngineService(service.Service):
|
|||||||
|
|
||||||
@request_context
|
@request_context
|
||||||
def profile_create(self, context, name, type, spec, perm=None, tags=None):
|
def profile_create(self, context, name, type, spec, perm=None, tags=None):
|
||||||
LOG.info(_LI('Creating profile %s: %s'), type, name)
|
LOG.info(_LI('Creating profile %(type)s: %(name)s'),
|
||||||
|
{'type': type, 'name': name})
|
||||||
plugin = environment.global_env().get_profile(type)
|
plugin = environment.global_env().get_profile(type)
|
||||||
|
|
||||||
kwargs = {
|
kwargs = {
|
||||||
@ -314,7 +315,8 @@ class EngineService(service.Service):
|
|||||||
cooldown = utils.parse_int_param('cooldown', cooldown)
|
cooldown = utils.parse_int_param('cooldown', cooldown)
|
||||||
plugin = environment.global_env().get_policy(type)
|
plugin = environment.global_env().get_policy(type)
|
||||||
|
|
||||||
LOG.info(_LI('Creating policy %s:%s'), type, name)
|
LOG.info(_LI('Creating policy %(type)s: %(name)s'),
|
||||||
|
{'type': type, 'name': name})
|
||||||
|
|
||||||
kwargs = {
|
kwargs = {
|
||||||
'spec': spec,
|
'spec': spec,
|
||||||
|
@ -176,23 +176,19 @@ class Policy(object):
|
|||||||
self.spec_data.validate()
|
self.spec_data.validate()
|
||||||
|
|
||||||
def attach(self, context, cluster, policy_data):
|
def attach(self, context, cluster, policy_data):
|
||||||
'''Method to be invoked before the policy is attached to a cluster.
|
'''Method to be invoked before policy is attached to a cluster.'''
|
||||||
'''
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def detach(self, context, cluster, policy_data):
|
def detach(self, context, cluster, policy_data):
|
||||||
'''Method to be invoked before the policy is detached from a cluster.
|
'''Method to be invoked before policy is detached from a cluster.'''
|
||||||
'''
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def pre_op(self, cluster_id, action, policy_data):
|
def pre_op(self, cluster_id, action, policy_data):
|
||||||
'''A method that will be invoked before an action execution.
|
'''A method that will be invoked before an action execution.'''
|
||||||
'''
|
|
||||||
return policy_data
|
return policy_data
|
||||||
|
|
||||||
def post_op(self, cluster_id, action, policy_data):
|
def post_op(self, cluster_id, action, policy_data):
|
||||||
'''A method that will be invoked after an action execution.
|
'''A method that will be invoked after an action execution.'''
|
||||||
'''
|
|
||||||
return policy_data
|
return policy_data
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
|
@ -71,7 +71,6 @@ class PlacementPolicy(base.Policy):
|
|||||||
self.AZs = self.spec.get('AZs')
|
self.AZs = self.spec.get('AZs')
|
||||||
|
|
||||||
def pre_op(self, cluster_id, action, policy_data):
|
def pre_op(self, cluster_id, action, policy_data):
|
||||||
'''Call back when new nodes are created for a cluster.
|
'''Call back when new nodes are created for a cluster.'''
|
||||||
'''
|
|
||||||
# TODO(anyone): calculate available AZs and or regions
|
# TODO(anyone): calculate available AZs and or regions
|
||||||
return policy_data
|
return policy_data
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
#from senlin.drivers import heat_v1 as heat
|
# from senlin.drivers import heat_v1 as heat
|
||||||
from senlin.profiles import base
|
from senlin.profiles import base
|
||||||
|
|
||||||
__type_name__ = 'aws.autoscaling.launchconfig'
|
__type_name__ = 'aws.autoscaling.launchconfig'
|
||||||
@ -59,5 +59,5 @@ class LaunchConfigProfile(base.Profile):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def do_check(self, id):
|
def do_check(self, id):
|
||||||
#TODO(liuh): add actual checking logic
|
# TODO(liuh): add actual checking logic
|
||||||
return True
|
return True
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
#from senlin.drivers import heat_v1 as heat
|
# from senlin.drivers import heat_v1 as heat
|
||||||
from senlin.profiles import base
|
from senlin.profiles import base
|
||||||
|
|
||||||
__type_name__ = 'os.heat.resource'
|
__type_name__ = 'os.heat.resource'
|
||||||
@ -40,5 +40,5 @@ class ResourceProfile(base.Profile):
|
|||||||
return {}
|
return {}
|
||||||
|
|
||||||
def do_check(self, id):
|
def do_check(self, id):
|
||||||
#TODO(liuh): add actual checking logic
|
# TODO(liuh): add actual checking logic
|
||||||
return True
|
return True
|
||||||
|
@ -212,8 +212,7 @@ class StackProfile(base.Profile):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def do_check(self, obj):
|
def do_check(self, obj):
|
||||||
#TODO(anyone):
|
# TODO(anyone): Use heat client to query stack status
|
||||||
#Use heat client to query stack status
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_template(self):
|
def get_template(self):
|
||||||
|
@ -24,10 +24,7 @@ LOG = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
class EngineClient(object):
|
class EngineClient(object):
|
||||||
'''Client side of the senlin engine rpc API.
|
'''Client side of the senlin engine rpc API.'''
|
||||||
API version history::
|
|
||||||
1.0 - Initial version.
|
|
||||||
'''
|
|
||||||
|
|
||||||
BASE_RPC_API_VERSION = '1.0'
|
BASE_RPC_API_VERSION = '1.0'
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ def fake_translate_msgid(msgid, domain, desired_locale=None):
|
|||||||
|
|
||||||
oslo_i18n.enable_lazy()
|
oslo_i18n.enable_lazy()
|
||||||
|
|
||||||
#To ensure messages don't really get translated while running tests.
|
# To ensure messages don't really get translated while running tests.
|
||||||
#As there are lots of places where matching is expected when comparing
|
# As there are lots of places where matching is expected when comparing
|
||||||
#exception message(translated) with raw message.
|
# exception message(translated) with raw message.
|
||||||
oslo_i18n._translate_msgid = fake_translate_msgid
|
oslo_i18n._translate_msgid = fake_translate_msgid
|
||||||
|
@ -15,6 +15,7 @@ import webob
|
|||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
from oslo_messaging._drivers import common as rpc_common
|
from oslo_messaging._drivers import common as rpc_common
|
||||||
|
from oslo_utils import encodeutils
|
||||||
|
|
||||||
from senlin.common import consts
|
from senlin.common import consts
|
||||||
from senlin.common import wsgi
|
from senlin.common import wsgi
|
||||||
@ -32,8 +33,8 @@ def request_with_middleware(middleware, func, req, *args, **kwargs):
|
|||||||
|
|
||||||
|
|
||||||
def to_remote_error(error):
|
def to_remote_error(error):
|
||||||
"""Converts the given exception to the one with the _Remote suffix.
|
'''Prepend the given exception with the _Remote suffix.'''
|
||||||
"""
|
|
||||||
exc_info = (type(error), error, None)
|
exc_info = (type(error), error, None)
|
||||||
serialized = rpc_common.serialize_remote_exception(exc_info)
|
serialized = rpc_common.serialize_remote_exception(exc_info)
|
||||||
remote_error = rpc_common.deserialize_remote_exception(
|
remote_error = rpc_common.deserialize_remote_exception(
|
||||||
@ -93,7 +94,7 @@ class ControllerTest(object):
|
|||||||
req = wsgi.Request(environ)
|
req = wsgi.Request(environ)
|
||||||
req.context = utils.dummy_context('api_test_user', self.tenant)
|
req.context = utils.dummy_context('api_test_user', self.tenant)
|
||||||
self.context = req.context
|
self.context = req.context
|
||||||
req.body = data
|
req.body = encodeutils.safe_encode(data)
|
||||||
return req
|
return req
|
||||||
|
|
||||||
def _post(self, path, data, content_type='application/json'):
|
def _post(self, path, data, content_type='application/json'):
|
||||||
|
@ -90,7 +90,7 @@ class RoutesTest(base.SenlinTestCase):
|
|||||||
self.assertRoute(
|
self.assertRoute(
|
||||||
self.m,
|
self.m,
|
||||||
'/aaaa/profiles/bbbb',
|
'/aaaa/profiles/bbbb',
|
||||||
'PUT',
|
'PATCH',
|
||||||
'update',
|
'update',
|
||||||
'ProfileController',
|
'ProfileController',
|
||||||
{
|
{
|
||||||
@ -166,7 +166,7 @@ class RoutesTest(base.SenlinTestCase):
|
|||||||
self.assertRoute(
|
self.assertRoute(
|
||||||
self.m,
|
self.m,
|
||||||
'/aaaa/policies/bbbb',
|
'/aaaa/policies/bbbb',
|
||||||
'PUT',
|
'PATCH',
|
||||||
'update',
|
'update',
|
||||||
'PolicyController',
|
'PolicyController',
|
||||||
{
|
{
|
||||||
@ -220,7 +220,7 @@ class RoutesTest(base.SenlinTestCase):
|
|||||||
self.assertRoute(
|
self.assertRoute(
|
||||||
self.m,
|
self.m,
|
||||||
'/aaaa/clusters/bbbb',
|
'/aaaa/clusters/bbbb',
|
||||||
'PUT',
|
'PATCH',
|
||||||
'update',
|
'update',
|
||||||
'ClusterController',
|
'ClusterController',
|
||||||
{
|
{
|
||||||
@ -285,7 +285,7 @@ class RoutesTest(base.SenlinTestCase):
|
|||||||
self.assertRoute(
|
self.assertRoute(
|
||||||
self.m,
|
self.m,
|
||||||
'/aaaa/nodes/bbbb',
|
'/aaaa/nodes/bbbb',
|
||||||
'PUT',
|
'PATCH',
|
||||||
'update',
|
'update',
|
||||||
'NodeController',
|
'NodeController',
|
||||||
{
|
{
|
||||||
|
@ -86,9 +86,7 @@ class SenlinTestCase(testscenarios.WithScenarios,
|
|||||||
self.addCleanup(utils.reset_dummy_db)
|
self.addCleanup(utils.reset_dummy_db)
|
||||||
|
|
||||||
def stub_wallclock(self):
|
def stub_wallclock(self):
|
||||||
"""
|
# Overrides scheduler wallclock to speed up tests expecting timeouts.
|
||||||
Overrides scheduler wallclock to speed up tests expecting timeouts.
|
|
||||||
"""
|
|
||||||
self._wallclock = time.time()
|
self._wallclock = time.time()
|
||||||
|
|
||||||
def fake_wallclock():
|
def fake_wallclock():
|
||||||
|
@ -19,9 +19,7 @@ from keystoneclient import exceptions
|
|||||||
|
|
||||||
class FakeClient(object):
|
class FakeClient(object):
|
||||||
def assert_called(self, method, url, body=None, pos=-1):
|
def assert_called(self, method, url, body=None, pos=-1):
|
||||||
"""
|
# Assert than an API method was just called.
|
||||||
Assert than an API method was just called.
|
|
||||||
"""
|
|
||||||
expected = (method, url)
|
expected = (method, url)
|
||||||
called = self.client.callstack[pos][0:2]
|
called = self.client.callstack[pos][0:2]
|
||||||
|
|
||||||
@ -35,9 +33,7 @@ class FakeClient(object):
|
|||||||
assert self.client.callstack[pos][2] == body
|
assert self.client.callstack[pos][2] == body
|
||||||
|
|
||||||
def assert_called_anytime(self, method, url, body=None):
|
def assert_called_anytime(self, method, url, body=None):
|
||||||
"""
|
# Assert than an API method was called anytime in the test.
|
||||||
Assert than an API method was called anytime in the test.
|
|
||||||
"""
|
|
||||||
expected = (method, url)
|
expected = (method, url)
|
||||||
|
|
||||||
assert self.client.callstack, \
|
assert self.client.callstack, \
|
||||||
|
@ -283,7 +283,7 @@ class DBAPIActionTest(base.SenlinTestCase):
|
|||||||
for spec in specs:
|
for spec in specs:
|
||||||
action = _create_action(self.ctx, action=shared.sample_action,
|
action = _create_action(self.ctx, action=shared.sample_action,
|
||||||
**spec)
|
**spec)
|
||||||
#action.status = db_api.ACTION_INIT
|
# action.status = db_api.ACTION_INIT
|
||||||
id_of[spec['name']] = action.id
|
id_of[spec['name']] = action.id
|
||||||
|
|
||||||
db_api.action_add_dependency(self.ctx,
|
db_api.action_add_dependency(self.ctx,
|
||||||
|
@ -284,7 +284,7 @@ class PolicyTest(base.SenlinTestCase):
|
|||||||
p = self.eng.policy_get(self.ctx, pid)
|
p = self.eng.policy_get(self.ctx, pid)
|
||||||
self.assertEqual('p-2', p['name'])
|
self.assertEqual('p-2', p['name'])
|
||||||
|
|
||||||
# 2. update cooldown
|
# 2. update cooldown
|
||||||
p2 = self.eng.policy_update(self.ctx, pid, cooldown=120)
|
p2 = self.eng.policy_update(self.ctx, pid, cooldown=120)
|
||||||
self.assertEqual(pid, p2['id'])
|
self.assertEqual(pid, p2['id'])
|
||||||
self.assertEqual(120, p2['cooldown'])
|
self.assertEqual(120, p2['cooldown'])
|
||||||
@ -293,7 +293,7 @@ class PolicyTest(base.SenlinTestCase):
|
|||||||
p = self.eng.policy_get(self.ctx, pid)
|
p = self.eng.policy_get(self.ctx, pid)
|
||||||
self.assertEqual(120, p['cooldown'])
|
self.assertEqual(120, p['cooldown'])
|
||||||
|
|
||||||
# 3. update level
|
# 3. update level
|
||||||
p2 = self.eng.policy_update(self.ctx, pid, level=50)
|
p2 = self.eng.policy_update(self.ctx, pid, level=50)
|
||||||
self.assertEqual(pid, p2['id'])
|
self.assertEqual(pid, p2['id'])
|
||||||
self.assertEqual(50, p2['level'])
|
self.assertEqual(50, p2['level'])
|
||||||
|
@ -100,19 +100,16 @@ class FaultMiddlewareTest(base.SenlinTestCase):
|
|||||||
|
|
||||||
wrapper = fault.FaultWrapper(None)
|
wrapper = fault.FaultWrapper(None)
|
||||||
msg = wrapper._error(TestException())
|
msg = wrapper._error(TestException())
|
||||||
expected = {
|
|
||||||
'code': 500,
|
self.assertEqual(500, msg['code'])
|
||||||
'error': {
|
self.assertEqual(500, msg['error']['code'])
|
||||||
'code': 500,
|
self.assertEqual(u'Error with non-ascii chars \x80',
|
||||||
'message': u'Error with non-ascii chars \x80',
|
msg['error']['message'])
|
||||||
'traceback': 'None\n',
|
self.assertEqual('TestException', msg['error']['type'])
|
||||||
'type': 'TestException'
|
self.assertEqual('The server has either erred or is incapable of '
|
||||||
},
|
'performing the requested operation.',
|
||||||
'explanation': 'The server has either erred or is incapable of '
|
msg['explanation'])
|
||||||
'performing the requested operation.',
|
self.assertEqual('Internal Server Error', msg['title'])
|
||||||
'title': 'Internal Server Error'
|
|
||||||
}
|
|
||||||
self.assertEqual(expected, msg)
|
|
||||||
|
|
||||||
def test_remote_exception(self):
|
def test_remote_exception(self):
|
||||||
# We want tracebacks
|
# We want tracebacks
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
from oslo_utils import encodeutils
|
||||||
import webob
|
import webob
|
||||||
from webob import exc
|
from webob import exc
|
||||||
|
|
||||||
@ -28,7 +29,7 @@ class FakeApp(object):
|
|||||||
def __call__(self, environ, start_response):
|
def __call__(self, environ, start_response):
|
||||||
"""Assert that headers are correctly set up when finally called."""
|
"""Assert that headers are correctly set up when finally called."""
|
||||||
resp = webob.Response()
|
resp = webob.Response()
|
||||||
resp.body = 'SUCCESS'
|
resp.body = encodeutils.safe_encode('SUCCESS')
|
||||||
return resp(environ, start_response)
|
return resp(environ, start_response)
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ from oslo_config import cfg
|
|||||||
from senlin.common import exception
|
from senlin.common import exception
|
||||||
from senlin.common import policy
|
from senlin.common import policy
|
||||||
from senlin.openstack.common import policy as base_policy
|
from senlin.openstack.common import policy as base_policy
|
||||||
from senlin.tests.common import base
|
from senlin.tests.common import base
|
||||||
from senlin.tests.common import utils
|
from senlin.tests.common import utils
|
||||||
|
|
||||||
policy_path = os.path.dirname(os.path.realpath(__file__)) + "/policy/"
|
policy_path = os.path.dirname(os.path.realpath(__file__)) + "/policy/"
|
||||||
|
@ -16,6 +16,7 @@ import six
|
|||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
from oslo_utils import encodeutils
|
||||||
|
|
||||||
from senlin.common import exception
|
from senlin.common import exception
|
||||||
from senlin.common import utils
|
from senlin.common import utils
|
||||||
@ -72,7 +73,8 @@ class ShortIdTest(base.SenlinTestCase):
|
|||||||
|
|
||||||
for id in ids:
|
for id in ids:
|
||||||
self.assertEqual(12, len(id))
|
self.assertEqual(12, len(id))
|
||||||
self.assertFalse(id.translate(None, allowed_chars))
|
tid = encodeutils.safe_encode(id)
|
||||||
|
self.assertFalse(tid.translate(None, allowed_chars))
|
||||||
self.assertEqual(1, ids.count(id))
|
self.assertEqual(1, ids.count(id))
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
|
from oslo_utils import encodeutils
|
||||||
import webob
|
import webob
|
||||||
|
|
||||||
from senlin.common import serializers
|
from senlin.common import serializers
|
||||||
@ -45,6 +46,9 @@ class JSONResponseSerializerTest(base.SenlinTestCase):
|
|||||||
self.assertEqual(200, response.status_int)
|
self.assertEqual(200, response.status_int)
|
||||||
content_types = filter(lambda h: h[0] == 'Content-Type',
|
content_types = filter(lambda h: h[0] == 'Content-Type',
|
||||||
response.headerlist)
|
response.headerlist)
|
||||||
self.assertEqual(1, len(content_types))
|
# NOTE: filter returns a iterator in python 3.
|
||||||
|
types = [t for t in content_types]
|
||||||
|
self.assertEqual(1, len(types))
|
||||||
self.assertEqual('application/json', response.content_type)
|
self.assertEqual('application/json', response.content_type)
|
||||||
self.assertEqual('{"key": "value"}', response.body)
|
self.assertEqual('{"key": "value"}',
|
||||||
|
encodeutils.safe_decode(response.body))
|
||||||
|
@ -15,6 +15,7 @@ import json
|
|||||||
import six
|
import six
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
|
from oslo_utils import encodeutils
|
||||||
import stubout
|
import stubout
|
||||||
import webob
|
import webob
|
||||||
|
|
||||||
@ -77,27 +78,6 @@ class RequestTest(base.SenlinTestCase):
|
|||||||
result = request.best_match_content_type()
|
result = request.best_match_content_type()
|
||||||
self.assertEqual("application/json", result)
|
self.assertEqual("application/json", result)
|
||||||
|
|
||||||
def test_best_match_language(self):
|
|
||||||
# Test that we are actually invoking language negotiation by webop
|
|
||||||
request = wsgi.Request.blank('/')
|
|
||||||
accepted = 'unknown-lang'
|
|
||||||
request.headers = {'Accept-Language': accepted}
|
|
||||||
|
|
||||||
def fake_best_match(self, offers, default_match=None):
|
|
||||||
# Best match on an unknown locale returns None
|
|
||||||
return None
|
|
||||||
|
|
||||||
self.stubs.SmartSet(request.accept_language,
|
|
||||||
'best_match', fake_best_match)
|
|
||||||
|
|
||||||
self.assertIsNone(request.best_match_language())
|
|
||||||
|
|
||||||
# If Accept-Language is missing or empty, match should be None
|
|
||||||
request.headers = {'Accept-Language': ''}
|
|
||||||
self.assertIsNone(request.best_match_language())
|
|
||||||
request.headers.pop('Accept-Language')
|
|
||||||
self.assertIsNone(request.best_match_language())
|
|
||||||
|
|
||||||
|
|
||||||
class ResourceTest(base.SenlinTestCase):
|
class ResourceTest(base.SenlinTestCase):
|
||||||
|
|
||||||
@ -182,7 +162,7 @@ class ResourceTest(base.SenlinTestCase):
|
|||||||
actions = {'action': 'delete', 'id': 12, 'body': 'data'}
|
actions = {'action': 'delete', 'id': 12, 'body': 'data'}
|
||||||
env = {'wsgiorg.routing_args': [None, actions]}
|
env = {'wsgiorg.routing_args': [None, actions]}
|
||||||
request = wsgi.Request.blank('/tests/123', environ=env)
|
request = wsgi.Request.blank('/tests/123', environ=env)
|
||||||
request.body = '{"foo" : "value"}'
|
request.body = encodeutils.safe_encode('{"foo" : "value"}')
|
||||||
resource = wsgi.Resource(Controller(),
|
resource = wsgi.Resource(Controller(),
|
||||||
wsgi.JSONRequestDeserializer(),
|
wsgi.JSONRequestDeserializer(),
|
||||||
None)
|
None)
|
||||||
@ -203,7 +183,7 @@ class ResourceTest(base.SenlinTestCase):
|
|||||||
actions = {'action': 'delete', 'id': 12, 'body': 'data'}
|
actions = {'action': 'delete', 'id': 12, 'body': 'data'}
|
||||||
env = {'wsgiorg.routing_args': [None, actions]}
|
env = {'wsgiorg.routing_args': [None, actions]}
|
||||||
request = wsgi.Request.blank('/tests/123', environ=env)
|
request = wsgi.Request.blank('/tests/123', environ=env)
|
||||||
request.body = '{"foo" : "value"}'
|
request.body = encodeutils.safe_encode('{"foo" : "value"}')
|
||||||
message_es = "No Encontrado"
|
message_es = "No Encontrado"
|
||||||
translated_ex = webob.exc.HTTPBadRequest(message_es)
|
translated_ex = webob.exc.HTTPBadRequest(message_es)
|
||||||
|
|
||||||
@ -246,7 +226,7 @@ class ResourceExceptionHandlingTest(base.SenlinTestCase):
|
|||||||
actions = {'action': 'raise_exception', 'body': 'data'}
|
actions = {'action': 'raise_exception', 'body': 'data'}
|
||||||
env = {'wsgiorg.routing_args': [None, actions]}
|
env = {'wsgiorg.routing_args': [None, actions]}
|
||||||
request = wsgi.Request.blank('/tests/123', environ=env)
|
request = wsgi.Request.blank('/tests/123', environ=env)
|
||||||
request.body = '{"foo" : "value"}'
|
request.body = encodeutils.safe_encode('{"foo": "value"}')
|
||||||
resource = wsgi.Resource(Controller(self.exception),
|
resource = wsgi.Resource(Controller(self.exception),
|
||||||
wsgi.JSONRequestDeserializer(),
|
wsgi.JSONRequestDeserializer(),
|
||||||
None)
|
None)
|
||||||
@ -260,7 +240,7 @@ class JSONRequestDeserializerTest(base.SenlinTestCase):
|
|||||||
def test_has_body_no_content_length(self):
|
def test_has_body_no_content_length(self):
|
||||||
request = wsgi.Request.blank('/')
|
request = wsgi.Request.blank('/')
|
||||||
request.method = 'POST'
|
request.method = 'POST'
|
||||||
request.body = 'asdf'
|
request.body = encodeutils.safe_encode('asdf')
|
||||||
request.headers.pop('Content-Length')
|
request.headers.pop('Content-Length')
|
||||||
request.headers['Content-Type'] = 'application/json'
|
request.headers['Content-Type'] = 'application/json'
|
||||||
self.assertFalse(wsgi.JSONRequestDeserializer().has_body(request))
|
self.assertFalse(wsgi.JSONRequestDeserializer().has_body(request))
|
||||||
@ -268,7 +248,7 @@ class JSONRequestDeserializerTest(base.SenlinTestCase):
|
|||||||
def test_has_body_zero_content_length(self):
|
def test_has_body_zero_content_length(self):
|
||||||
request = wsgi.Request.blank('/')
|
request = wsgi.Request.blank('/')
|
||||||
request.method = 'POST'
|
request.method = 'POST'
|
||||||
request.body = 'asdf'
|
request.body = encodeutils.safe_encode('asdf')
|
||||||
request.headers['Content-Length'] = 0
|
request.headers['Content-Length'] = 0
|
||||||
request.headers['Content-Type'] = 'application/json'
|
request.headers['Content-Type'] = 'application/json'
|
||||||
self.assertFalse(wsgi.JSONRequestDeserializer().has_body(request))
|
self.assertFalse(wsgi.JSONRequestDeserializer().has_body(request))
|
||||||
@ -276,14 +256,14 @@ class JSONRequestDeserializerTest(base.SenlinTestCase):
|
|||||||
def test_has_body_has_content_length_no_content_type(self):
|
def test_has_body_has_content_length_no_content_type(self):
|
||||||
request = wsgi.Request.blank('/')
|
request = wsgi.Request.blank('/')
|
||||||
request.method = 'POST'
|
request.method = 'POST'
|
||||||
request.body = '{"key": "value"}'
|
request.body = encodeutils.safe_encode('{"key": "value"}')
|
||||||
self.assertIn('Content-Length', request.headers)
|
self.assertIn('Content-Length', request.headers)
|
||||||
self.assertTrue(wsgi.JSONRequestDeserializer().has_body(request))
|
self.assertTrue(wsgi.JSONRequestDeserializer().has_body(request))
|
||||||
|
|
||||||
def test_has_body_has_content_length_plain_content_type(self):
|
def test_has_body_has_content_length_plain_content_type(self):
|
||||||
request = wsgi.Request.blank('/')
|
request = wsgi.Request.blank('/')
|
||||||
request.method = 'POST'
|
request.method = 'POST'
|
||||||
request.body = '{"key": "value"}'
|
request.body = encodeutils.safe_encode('{"key": "value"}')
|
||||||
self.assertIn('Content-Length', request.headers)
|
self.assertIn('Content-Length', request.headers)
|
||||||
request.headers['Content-Type'] = 'text/plain'
|
request.headers['Content-Type'] = 'text/plain'
|
||||||
self.assertTrue(wsgi.JSONRequestDeserializer().has_body(request))
|
self.assertTrue(wsgi.JSONRequestDeserializer().has_body(request))
|
||||||
@ -291,7 +271,7 @@ class JSONRequestDeserializerTest(base.SenlinTestCase):
|
|||||||
def test_has_body_has_content_type_malformed(self):
|
def test_has_body_has_content_type_malformed(self):
|
||||||
request = wsgi.Request.blank('/')
|
request = wsgi.Request.blank('/')
|
||||||
request.method = 'POST'
|
request.method = 'POST'
|
||||||
request.body = 'asdf'
|
request.body = encodeutils.safe_encode('asdf')
|
||||||
self.assertIn('Content-Length', request.headers)
|
self.assertIn('Content-Length', request.headers)
|
||||||
request.headers['Content-Type'] = 'application/json'
|
request.headers['Content-Type'] = 'application/json'
|
||||||
self.assertFalse(wsgi.JSONRequestDeserializer().has_body(request))
|
self.assertFalse(wsgi.JSONRequestDeserializer().has_body(request))
|
||||||
@ -299,7 +279,7 @@ class JSONRequestDeserializerTest(base.SenlinTestCase):
|
|||||||
def test_has_body_has_content_type(self):
|
def test_has_body_has_content_type(self):
|
||||||
request = wsgi.Request.blank('/')
|
request = wsgi.Request.blank('/')
|
||||||
request.method = 'POST'
|
request.method = 'POST'
|
||||||
request.body = '{"key": "value"}'
|
request.body = encodeutils.safe_encode('{"key": "value"}')
|
||||||
self.assertIn('Content-Length', request.headers)
|
self.assertIn('Content-Length', request.headers)
|
||||||
request.headers['Content-Type'] = 'application/json'
|
request.headers['Content-Type'] = 'application/json'
|
||||||
self.assertTrue(wsgi.JSONRequestDeserializer().has_body(request))
|
self.assertTrue(wsgi.JSONRequestDeserializer().has_body(request))
|
||||||
@ -307,7 +287,7 @@ class JSONRequestDeserializerTest(base.SenlinTestCase):
|
|||||||
def test_has_body_has_wrong_content_type(self):
|
def test_has_body_has_wrong_content_type(self):
|
||||||
request = wsgi.Request.blank('/')
|
request = wsgi.Request.blank('/')
|
||||||
request.method = 'POST'
|
request.method = 'POST'
|
||||||
request.body = '{"key": "value"}'
|
request.body = encodeutils.safe_encode('{"key": "value"}')
|
||||||
self.assertIn('Content-Length', request.headers)
|
self.assertIn('Content-Length', request.headers)
|
||||||
request.headers['Content-Type'] = 'application/xml'
|
request.headers['Content-Type'] = 'application/xml'
|
||||||
self.assertFalse(wsgi.JSONRequestDeserializer().has_body(request))
|
self.assertFalse(wsgi.JSONRequestDeserializer().has_body(request))
|
||||||
@ -315,14 +295,14 @@ class JSONRequestDeserializerTest(base.SenlinTestCase):
|
|||||||
def test_has_body_has_aws_content_type_only(self):
|
def test_has_body_has_aws_content_type_only(self):
|
||||||
request = wsgi.Request.blank('/?ContentType=JSON')
|
request = wsgi.Request.blank('/?ContentType=JSON')
|
||||||
request.method = 'GET'
|
request.method = 'GET'
|
||||||
request.body = '{"key": "value"}'
|
request.body = encodeutils.safe_encode('{"key": "value"}')
|
||||||
self.assertIn('Content-Length', request.headers)
|
self.assertIn('Content-Length', request.headers)
|
||||||
self.assertTrue(wsgi.JSONRequestDeserializer().has_body(request))
|
self.assertTrue(wsgi.JSONRequestDeserializer().has_body(request))
|
||||||
|
|
||||||
def test_has_body_respect_aws_content_type(self):
|
def test_has_body_respect_aws_content_type(self):
|
||||||
request = wsgi.Request.blank('/?ContentType=JSON')
|
request = wsgi.Request.blank('/?ContentType=JSON')
|
||||||
request.method = 'GET'
|
request.method = 'GET'
|
||||||
request.body = '{"key": "value"}'
|
request.body = encodeutils.safe_encode('{"key": "value"}')
|
||||||
self.assertIn('Content-Length', request.headers)
|
self.assertIn('Content-Length', request.headers)
|
||||||
request.headers['Content-Type'] = 'application/xml'
|
request.headers['Content-Type'] = 'application/xml'
|
||||||
self.assertTrue(wsgi.JSONRequestDeserializer().has_body(request))
|
self.assertTrue(wsgi.JSONRequestDeserializer().has_body(request))
|
||||||
@ -330,7 +310,7 @@ class JSONRequestDeserializerTest(base.SenlinTestCase):
|
|||||||
def test_has_body_content_type_with_get(self):
|
def test_has_body_content_type_with_get(self):
|
||||||
request = wsgi.Request.blank('/')
|
request = wsgi.Request.blank('/')
|
||||||
request.method = 'GET'
|
request.method = 'GET'
|
||||||
request.body = '{"key": "value"}'
|
request.body = encodeutils.safe_encode('{"key": "value"}')
|
||||||
self.assertIn('Content-Length', request.headers)
|
self.assertIn('Content-Length', request.headers)
|
||||||
self.assertTrue(wsgi.JSONRequestDeserializer().has_body(request))
|
self.assertTrue(wsgi.JSONRequestDeserializer().has_body(request))
|
||||||
|
|
||||||
@ -358,7 +338,7 @@ class JSONRequestDeserializerTest(base.SenlinTestCase):
|
|||||||
def test_default_with_body(self):
|
def test_default_with_body(self):
|
||||||
request = wsgi.Request.blank('/')
|
request = wsgi.Request.blank('/')
|
||||||
request.method = 'POST'
|
request.method = 'POST'
|
||||||
request.body = '{"key": "value"}'
|
request.body = encodeutils.safe_encode('{"key": "value"}')
|
||||||
actual = wsgi.JSONRequestDeserializer().default(request)
|
actual = wsgi.JSONRequestDeserializer().default(request)
|
||||||
expected = {"body": {"key": "value"}}
|
expected = {"body": {"key": "value"}}
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
@ -366,7 +346,7 @@ class JSONRequestDeserializerTest(base.SenlinTestCase):
|
|||||||
def test_default_with_get_with_body(self):
|
def test_default_with_get_with_body(self):
|
||||||
request = wsgi.Request.blank('/')
|
request = wsgi.Request.blank('/')
|
||||||
request.method = 'GET'
|
request.method = 'GET'
|
||||||
request.body = '{"key": "value"}'
|
request.body = encodeutils.safe_encode('{"key": "value"}')
|
||||||
actual = wsgi.JSONRequestDeserializer().default(request)
|
actual = wsgi.JSONRequestDeserializer().default(request)
|
||||||
expected = {"body": {"key": "value"}}
|
expected = {"body": {"key": "value"}}
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
@ -374,7 +354,7 @@ class JSONRequestDeserializerTest(base.SenlinTestCase):
|
|||||||
def test_default_with_get_with_body_with_aws(self):
|
def test_default_with_get_with_body_with_aws(self):
|
||||||
request = wsgi.Request.blank('/?ContentType=JSON')
|
request = wsgi.Request.blank('/?ContentType=JSON')
|
||||||
request.method = 'GET'
|
request.method = 'GET'
|
||||||
request.body = '{"key": "value"}'
|
request.body = encodeutils.safe_encode('{"key": "value"}')
|
||||||
actual = wsgi.JSONRequestDeserializer().default(request)
|
actual = wsgi.JSONRequestDeserializer().default(request)
|
||||||
expected = {"body": {"key": "value"}}
|
expected = {"body": {"key": "value"}}
|
||||||
self.assertEqual(expected, actual)
|
self.assertEqual(expected, actual)
|
||||||
|
@ -3,16 +3,17 @@
|
|||||||
# process, which may cause wedges in the gate later.
|
# process, which may cause wedges in the gate later.
|
||||||
|
|
||||||
# Hacking already pins down pep8, pyflakes and flake8
|
# Hacking already pins down pep8, pyflakes and flake8
|
||||||
hacking>=0.8.0,<0.9
|
hacking>=0.10.0,<0.11
|
||||||
coverage>=3.6
|
coverage>=3.6
|
||||||
discover
|
discover
|
||||||
mock>=1.0
|
mock>=1.0
|
||||||
mox>=0.5.3
|
mox>=0.5.3
|
||||||
MySQL-python
|
#MySQL-python
|
||||||
oslosphinx>=2.2.0 # Apache-2.0
|
oslosphinx>=2.2.0 # Apache-2.0
|
||||||
oslotest>=1.2.0 # Apache-2.0
|
oslotest>=1.2.0 # Apache-2.0
|
||||||
paramiko>=1.13.0
|
paramiko>=1.13.0
|
||||||
psycopg2
|
#psycopg2
|
||||||
|
#pysqlite
|
||||||
sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3
|
sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3
|
||||||
testrepository>=0.0.18
|
testrepository>=0.0.18
|
||||||
testscenarios>=0.4
|
testscenarios>=0.4
|
||||||
|
2
tox.ini
2
tox.ini
@ -22,7 +22,7 @@ whitelist_externals = bash
|
|||||||
commands =
|
commands =
|
||||||
flake8 senlin bin/senlin-api bin/senlin-engine bin/senlin-manage
|
flake8 senlin bin/senlin-api bin/senlin-engine bin/senlin-manage
|
||||||
# Check that .po and .pot files are valid:
|
# Check that .po and .pot files are valid:
|
||||||
bash -c "find senlin -type f -regex '.*\.pot?' -print0|xargs -0 -n 1 msgfmt --check-format -o /dev/null"
|
# bash -c "find senlin -type f -regex '.*\.pot?' -print0|xargs -0 -n 1 msgfmt --check-format -o /dev/null"
|
||||||
|
|
||||||
[testenv:venv]
|
[testenv:venv]
|
||||||
commands = {posargs}
|
commands = {posargs}
|
||||||
|
Loading…
Reference in New Issue
Block a user