Merge "Fix health monitor API handling of None updates"
This commit is contained in:
commit
b2d40c1120
|
@ -285,14 +285,13 @@ class HealthMonitorController(base.BaseController):
|
|||
raise exceptions.InvalidOption(
|
||||
value=consts.EXPECTED_CODES, option='health monitors of '
|
||||
'type {}'.format(db_hm.type))
|
||||
else:
|
||||
# For HTTP health monitor these cannot be null/None
|
||||
if health_monitor.http_method is None:
|
||||
health_monitor.http_method = wtypes.Unset
|
||||
if health_monitor.url_path is None:
|
||||
health_monitor.url_path = wtypes.Unset
|
||||
if health_monitor.expected_codes is None:
|
||||
health_monitor.expected_codes = wtypes.Unset
|
||||
if health_monitor.delay is None:
|
||||
raise exceptions.InvalidOption(value=None, option=consts.DELAY)
|
||||
if health_monitor.max_retries is None:
|
||||
raise exceptions.InvalidOption(value=None,
|
||||
option=consts.MAX_RETRIES)
|
||||
if health_monitor.timeout is None:
|
||||
raise exceptions.InvalidOption(value=None, option=consts.TIMEOUT)
|
||||
|
||||
if health_monitor.domain_name and not (
|
||||
db_hm.http_version or health_monitor.http_version):
|
||||
|
@ -308,6 +307,29 @@ class HealthMonitorController(base.BaseController):
|
|||
value='http_version %s' % http_version,
|
||||
option='health monitors HTTP 1.1 domain name health check')
|
||||
|
||||
def _set_default_on_none(self, health_monitor):
|
||||
"""Reset settings to their default values if None/null was passed in
|
||||
|
||||
A None/null value can be passed in to clear a value. PUT values
|
||||
that were not provided by the user have a type of wtypes.UnsetType.
|
||||
If the user is attempting to clear values, they should either
|
||||
be set to None (for example in the name field) or they should be
|
||||
reset to their default values.
|
||||
This method is intended to handle those values that need to be set
|
||||
back to a default value.
|
||||
"""
|
||||
if health_monitor.http_method is None:
|
||||
health_monitor.http_method = (
|
||||
consts.HEALTH_MONITOR_HTTP_DEFAULT_METHOD)
|
||||
if health_monitor.url_path is None:
|
||||
health_monitor.url_path = (
|
||||
consts.HEALTH_MONITOR_DEFAULT_URL_PATH)
|
||||
if health_monitor.expected_codes is None:
|
||||
health_monitor.expected_codes = (
|
||||
consts.HEALTH_MONITOR_DEFAULT_EXPECTED_CODES)
|
||||
if health_monitor.max_retries_down is None:
|
||||
health_monitor.max_retries_down = consts.DEFAULT_MAX_RETRIES_DOWN
|
||||
|
||||
@wsme_pecan.wsexpose(hm_types.HealthMonitorRootResponse, wtypes.text,
|
||||
body=hm_types.HealthMonitorRootPUT, status_code=200)
|
||||
def put(self, id, health_monitor_):
|
||||
|
@ -327,6 +349,9 @@ class HealthMonitorController(base.BaseController):
|
|||
if (pool.protocol == consts.PROTOCOL_UDP and
|
||||
db_hm.type == consts.HEALTH_MONITOR_UDP_CONNECT):
|
||||
self._validate_healthmonitor_request_for_udp(health_monitor)
|
||||
|
||||
self._set_default_on_none(health_monitor)
|
||||
|
||||
# Load the driver early as it also provides validation
|
||||
driver = driver_factory.get_driver(provider)
|
||||
|
||||
|
|
|
@ -86,7 +86,8 @@ class HealthMonitorPOST(BaseHealthMonitorType):
|
|||
timeout = wtypes.wsattr(wtypes.IntegerType(minimum=0), mandatory=True)
|
||||
max_retries_down = wtypes.wsattr(
|
||||
wtypes.IntegerType(minimum=constants.MIN_HM_RETRIES,
|
||||
maximum=constants.MAX_HM_RETRIES), default=3)
|
||||
maximum=constants.MAX_HM_RETRIES),
|
||||
default=constants.DEFAULT_MAX_RETRIES_DOWN)
|
||||
max_retries = wtypes.wsattr(
|
||||
wtypes.IntegerType(minimum=constants.MIN_HM_RETRIES,
|
||||
maximum=constants.MAX_HM_RETRIES),
|
||||
|
@ -152,7 +153,8 @@ class HealthMonitorSingleCreate(BaseHealthMonitorType):
|
|||
timeout = wtypes.wsattr(wtypes.IntegerType(minimum=0), mandatory=True)
|
||||
max_retries_down = wtypes.wsattr(
|
||||
wtypes.IntegerType(minimum=constants.MIN_HM_RETRIES,
|
||||
maximum=constants.MAX_HM_RETRIES), default=3)
|
||||
maximum=constants.MAX_HM_RETRIES),
|
||||
default=constants.DEFAULT_MAX_RETRIES_DOWN)
|
||||
max_retries = wtypes.wsattr(
|
||||
wtypes.IntegerType(minimum=constants.MIN_HM_RETRIES,
|
||||
maximum=constants.MAX_HM_RETRIES),
|
||||
|
|
|
@ -193,11 +193,14 @@ HEALTH_MONITOR_DEFAULT_URL_PATH = '/'
|
|||
TYPE = 'type'
|
||||
URL_PATH = 'url_path'
|
||||
HTTP_METHOD = 'http_method'
|
||||
HTTP_VERSION = 'http_version'
|
||||
EXPECTED_CODES = 'expected_codes'
|
||||
DELAY = 'delay'
|
||||
TIMEOUT = 'timeout'
|
||||
MAX_RETRIES = 'max_retries'
|
||||
MAX_RETRIES_DOWN = 'max_retries_down'
|
||||
RISE_THRESHOLD = 'rise_threshold'
|
||||
DOMAIN_NAME = 'domain_name'
|
||||
|
||||
UPDATE_STATS = 'UPDATE_STATS'
|
||||
UPDATE_HEALTH = 'UPDATE_HEALTH'
|
||||
|
@ -212,6 +215,7 @@ MIN_CONNECTION_LIMIT = -1
|
|||
MIN_WEIGHT = 0
|
||||
MAX_WEIGHT = 256
|
||||
|
||||
DEFAULT_MAX_RETRIES_DOWN = 3
|
||||
MIN_HM_RETRIES = 1
|
||||
MAX_HM_RETRIES = 10
|
||||
|
||||
|
|
|
@ -1519,6 +1519,42 @@ class TestHealthMonitor(base.BaseAPITest):
|
|||
self.put(self.HM_PATH.format(healthmonitor_id=api_hm.get('id')),
|
||||
self._build_body(new_hm), status=400)
|
||||
|
||||
def test_update_delay_none(self):
|
||||
api_hm = self.create_health_monitor(self.pool_with_listener_id,
|
||||
constants.HEALTH_MONITOR_HTTP,
|
||||
1, 1, 1, 1).get(self.root_tag)
|
||||
new_hm = {constants.DELAY: None}
|
||||
self.set_lb_status(self.lb_id)
|
||||
expect_error_msg = ("None is not a valid option for %s" %
|
||||
constants.DELAY)
|
||||
res = self.put(self.HM_PATH.format(healthmonitor_id=api_hm.get('id')),
|
||||
self._build_body(new_hm), status=400)
|
||||
self.assertEqual(expect_error_msg, res.json['faultstring'])
|
||||
|
||||
def test_update_max_retries_none(self):
|
||||
api_hm = self.create_health_monitor(self.pool_with_listener_id,
|
||||
constants.HEALTH_MONITOR_HTTP,
|
||||
1, 1, 1, 1).get(self.root_tag)
|
||||
new_hm = {constants.MAX_RETRIES: None}
|
||||
self.set_lb_status(self.lb_id)
|
||||
expect_error_msg = ("None is not a valid option for %s" %
|
||||
constants.MAX_RETRIES)
|
||||
res = self.put(self.HM_PATH.format(healthmonitor_id=api_hm.get('id')),
|
||||
self._build_body(new_hm), status=400)
|
||||
self.assertEqual(expect_error_msg, res.json['faultstring'])
|
||||
|
||||
def test_update_timeout_none(self):
|
||||
api_hm = self.create_health_monitor(self.pool_with_listener_id,
|
||||
constants.HEALTH_MONITOR_HTTP,
|
||||
1, 1, 1, 1).get(self.root_tag)
|
||||
new_hm = {constants.TIMEOUT: None}
|
||||
self.set_lb_status(self.lb_id)
|
||||
expect_error_msg = ("None is not a valid option for %s" %
|
||||
constants.TIMEOUT)
|
||||
res = self.put(self.HM_PATH.format(healthmonitor_id=api_hm.get('id')),
|
||||
self._build_body(new_hm), status=400)
|
||||
self.assertEqual(expect_error_msg, res.json['faultstring'])
|
||||
|
||||
@mock.patch('octavia.api.drivers.utils.call_provider')
|
||||
def test_update_with_bad_provider(self, mock_provider):
|
||||
api_hm = self.create_health_monitor(
|
||||
|
@ -1631,6 +1667,31 @@ class TestHealthMonitor(base.BaseAPITest):
|
|||
'domain_name'], constants.DOMAIN_NAME_REGEX)
|
||||
self.assertEqual(expect_error_msg, response.json['faultstring'])
|
||||
|
||||
def test_update_unset_defaults(self):
|
||||
api_hm = self.create_health_monitor(
|
||||
self.pool_with_listener_id, constants.HEALTH_MONITOR_HTTP,
|
||||
1, 1, 1, 1, name='test', domain_name='test.example.com',
|
||||
expected_codes='400', http_method='HEAD', http_version='1.1',
|
||||
url_path='/test').get(self.root_tag)
|
||||
new_hm = {constants.DOMAIN_NAME: None, constants.EXPECTED_CODES: None,
|
||||
constants.HTTP_METHOD: None, constants.HTTP_VERSION: None,
|
||||
constants.MAX_RETRIES_DOWN: None, 'name': None,
|
||||
constants.URL_PATH: None}
|
||||
self.set_lb_status(self.lb_id)
|
||||
res = self.put(self.HM_PATH.format(healthmonitor_id=api_hm.get('id')),
|
||||
self._build_body(new_hm)).json.get(self.root_tag)
|
||||
self.assertIsNone(res[constants.DOMAIN_NAME])
|
||||
self.assertEqual(constants.HEALTH_MONITOR_DEFAULT_EXPECTED_CODES,
|
||||
res[constants.EXPECTED_CODES])
|
||||
self.assertEqual(constants.HEALTH_MONITOR_HTTP_DEFAULT_METHOD,
|
||||
res[constants.HTTP_METHOD])
|
||||
self.assertIsNone(res[constants.HTTP_VERSION])
|
||||
self.assertEqual(constants.DEFAULT_MAX_RETRIES_DOWN,
|
||||
res[constants.MAX_RETRIES_DOWN])
|
||||
self.assertEqual('', res['name'])
|
||||
self.assertEqual(constants.HEALTH_MONITOR_DEFAULT_URL_PATH,
|
||||
res[constants.URL_PATH])
|
||||
|
||||
def test_delete(self):
|
||||
api_hm = self.create_health_monitor(
|
||||
self.pool_with_listener_id,
|
||||
|
|
Loading…
Reference in New Issue