Merge "Fix url_path valid check"

This commit is contained in:
Jenkins 2017-07-27 02:41:43 +00:00 committed by Gerrit Code Review
commit bc1491e07b
6 changed files with 88 additions and 5 deletions

View File

@ -60,6 +60,20 @@ class URLType(wtypes.UserType):
return value
class URLPathType(wtypes.UserType):
basetype = unicode
name = 'url_path'
@staticmethod
def validate(value):
try:
validate.url_path(value)
except exceptions.InvalidURLPath:
error = 'Value must be a valid URL Path string'
raise ValueError(error)
return value
class BaseType(wtypes.Base):
@classmethod
def _full_response(cls):

View File

@ -92,7 +92,7 @@ class HealthMonitorPOST(BaseHealthMonitorType):
wtypes.Enum(str, *constants.SUPPORTED_HEALTH_MONITOR_HTTP_METHODS),
default=constants.HEALTH_MONITOR_HTTP_DEFAULT_METHOD)
url_path = wtypes.wsattr(
types.URLType(require_scheme=False),
types.URLPathType(),
default=constants.HEALTH_MONITOR_DEFAULT_URL_PATH)
expected_codes = wtypes.wsattr(
wtypes.StringType(pattern=r'^(\d{3}(\s*,\s*\d{3})*)$|^(\d{3}-\d{3})$'),
@ -120,7 +120,7 @@ class HealthMonitorPUT(BaseHealthMonitorType):
maximum=constants.MAX_HM_RETRIES))
http_method = wtypes.wsattr(
wtypes.Enum(str, *constants.SUPPORTED_HEALTH_MONITOR_HTTP_METHODS))
url_path = wtypes.wsattr(types.URLType(require_scheme=False))
url_path = wtypes.wsattr(types.URLPathType())
expected_codes = wtypes.wsattr(
wtypes.StringType(pattern=r'^(\d{3}(\s*,\s*\d{3})*)$|^(\d{3}-\d{3})$'))
admin_state_up = wtypes.wsattr(bool)
@ -149,7 +149,7 @@ class HealthMonitorSingleCreate(BaseHealthMonitorType):
wtypes.Enum(str, *constants.SUPPORTED_HEALTH_MONITOR_HTTP_METHODS),
default=constants.HEALTH_MONITOR_HTTP_DEFAULT_METHOD)
url_path = wtypes.wsattr(
types.URLType(require_scheme=False),
types.URLPathType(),
default=constants.HEALTH_MONITOR_DEFAULT_URL_PATH)
expected_codes = wtypes.wsattr(
wtypes.StringType(pattern=r'^(\d{3}(\s*,\s*\d{3})*)$|^(\d{3}-\d{3})$'),

View File

@ -239,6 +239,11 @@ class InvalidURL(OctaviaException):
message = _('Not a valid URL: %(url)s')
class InvalidURLPath(APIException):
msg = _('Not a valid URLPath: %(url_path)s')
code = 400
class InvalidString(OctaviaException):
message = _('Invalid characters in %(what)s')

View File

@ -46,6 +46,22 @@ def url(url, require_scheme=True):
return True
def url_path(url_path):
"""Raises an error if the url_path doesn't look like a URL Path."""
try:
p_url = rfc3986.urlparse(rfc3986.normalize_uri(url_path))
if (
p_url.scheme or p_url.userinfo or p_url.host or
p_url.port or
p_url.path is None
):
raise exceptions.InvalidURLPath(url_path=url_path)
except Exception:
raise exceptions.InvalidURLPath(url_path=url_path)
return True
def header_name(header, what=None):
"""Raises an error if header does not look like an HTML header name."""
p = re.compile(constants.HTTP_HEADER_NAME_REGEX)

View File

@ -572,6 +572,19 @@ class TestHealthMonitor(base.BaseAPITest):
hm_prov_status=constants.PENDING_CREATE,
hm_op_status=constants.OFFLINE)
def test_create_http_monitor_with_url_path(self):
api_hm = self.create_health_monitor(
self.pool_id, constants.HEALTH_MONITOR_HTTP,
1, 1, 1, 1, url_path="/v2/api/index").get(self.root_tag)
self.assert_correct_status(
lb_id=self.lb_id, listener_id=self.listener_id,
pool_id=self.pool_id, hm_id=api_hm.get('id'),
lb_prov_status=constants.PENDING_UPDATE,
listener_prov_status=constants.ACTIVE,
pool_prov_status=constants.PENDING_UPDATE,
hm_prov_status=constants.PENDING_CREATE,
hm_op_status=constants.OFFLINE)
def test_create_sans_listener(self):
api_hm = self.create_health_monitor(
self.pool_id, constants.HEALTH_MONITOR_HTTP,
@ -704,6 +717,19 @@ class TestHealthMonitor(base.BaseAPITest):
lb_id=self.lb_id, listener_id=self.listener_id,
pool_id=self.pool_id)
def test_bad_create_with_invalid_url_path(self):
req_dict = {'pool_id': self.pool_id,
'type': constants.HEALTH_MONITOR_HTTP,
'delay': 1,
'timeout': 1,
'max_retries_down': 1,
'max_retries': 1,
'url_path': 'https://openstack.org'}
self.post(self.HMS_PATH, self._build_body(req_dict), status=400)
self.assert_correct_status(
lb_id=self.lb_id, listener_id=self.listener_id,
pool_id=self.pool_id)
def test_create_with_bad_handler(self):
self.handler_mock().health_monitor.create.side_effect = Exception()
api_hm = self.create_health_monitor(

View File

@ -75,8 +75,17 @@ class TestHealthMonitor(object):
if self._type is hm_type.HealthMonitorPOST:
body.update({"type": constants.PROTOCOL_HTTP,
"pool_id": uuidutils.generate_uuid()})
self.assertRaises(exc.InvalidInput, wsme_json.fromjson, self._type,
body)
self.assertRaises(exc.InvalidInput, wsme_json.fromjson,
self._type, body)
def test_invalid_url_path_with_url(self):
body = {"delay": 1, "timeout": 1, "max_retries": 1,
"url_path": 'https://www.openstack.org'}
if self._type is hm_type.HealthMonitorPOST:
body.update({"type": constants.PROTOCOL_HTTP,
"pool_id": uuidutils.generate_uuid()})
self.assertRaises(exc.InvalidInput, wsme_json.fromjson,
self._type, body)
def test_invalid_expected_codes(self):
body = {"delay": 1, "timeout": 1, "max_retries": 1,
@ -140,6 +149,19 @@ class TestHealthMonitorPOST(base.BaseTypesTest, TestHealthMonitor):
self.assertEqual(3, hmpost.max_retries_down)
self.assertTrue(hmpost.admin_state_up)
def test_url_path_with_query_and_fragment(self):
url_path = "/v2/index?a=12,b=34#123dd"
body = {"type": constants.HEALTH_MONITOR_HTTP, "delay": 1,
"timeout": 1, "max_retries": 1,
"pool_id": uuidutils.generate_uuid(),
"url_path": url_path}
hmpost = wsme_json.fromjson(self._type, body)
self.assertEqual('GET', hmpost.http_method)
self.assertEqual(url_path, hmpost.url_path)
self.assertEqual('200', hmpost.expected_codes)
self.assertEqual(3, hmpost.max_retries_down)
self.assertTrue(hmpost.admin_state_up)
def test_non_uuid_project_id(self):
body = {"type": constants.HEALTH_MONITOR_HTTP, "delay": 1,
"timeout": 1, "max_retries_down": 1, "max_retries": 1,