Merge "Fix member API handling of None/null updates"

This commit is contained in:
Zuul 2019-07-27 00:49:25 +00:00 committed by Gerrit Code Review
commit 80f4647648
4 changed files with 43 additions and 2 deletions

View File

@ -206,6 +206,22 @@ class MemberController(base.BaseController):
return db_member return db_member
def _set_default_on_none(self, member):
"""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 member.backup is None:
member.backup = False
if member.weight is None:
member.weight = constants.DEFAULT_WEIGHT
@wsme_pecan.wsexpose(member_types.MemberRootResponse, @wsme_pecan.wsexpose(member_types.MemberRootResponse,
wtypes.text, body=member_types.MemberRootPUT, wtypes.text, body=member_types.MemberRootPUT,
status_code=200) status_code=200)
@ -225,6 +241,8 @@ class MemberController(base.BaseController):
self._validate_pool_id(id, db_member.pool_id) self._validate_pool_id(id, db_member.pool_id)
self._set_default_on_none(member)
# Load the driver early as it also provides validation # Load the driver early as it also provides validation
driver = driver_factory.get_driver(provider) driver = driver_factory.get_driver(provider)

View File

@ -74,7 +74,8 @@ class MemberPOST(BaseMemberType):
minimum=constants.MIN_PORT_NUMBER, maximum=constants.MAX_PORT_NUMBER), minimum=constants.MIN_PORT_NUMBER, maximum=constants.MAX_PORT_NUMBER),
mandatory=True) mandatory=True)
weight = wtypes.wsattr(wtypes.IntegerType( weight = wtypes.wsattr(wtypes.IntegerType(
minimum=constants.MIN_WEIGHT, maximum=constants.MAX_WEIGHT), default=1) minimum=constants.MIN_WEIGHT, maximum=constants.MAX_WEIGHT),
default=constants.DEFAULT_WEIGHT)
backup = wtypes.wsattr(bool, default=False) backup = wtypes.wsattr(bool, default=False)
subnet_id = wtypes.wsattr(wtypes.UuidType()) subnet_id = wtypes.wsattr(wtypes.UuidType())
# TODO(johnsom) Remove after deprecation (R series) # TODO(johnsom) Remove after deprecation (R series)
@ -120,7 +121,8 @@ class MemberSingleCreate(BaseMemberType):
minimum=constants.MIN_PORT_NUMBER, maximum=constants.MAX_PORT_NUMBER), minimum=constants.MIN_PORT_NUMBER, maximum=constants.MAX_PORT_NUMBER),
mandatory=True) mandatory=True)
weight = wtypes.wsattr(wtypes.IntegerType( weight = wtypes.wsattr(wtypes.IntegerType(
minimum=constants.MIN_WEIGHT, maximum=constants.MAX_WEIGHT), default=1) minimum=constants.MIN_WEIGHT, maximum=constants.MAX_WEIGHT),
default=constants.DEFAULT_WEIGHT)
backup = wtypes.wsattr(bool, default=False) backup = wtypes.wsattr(bool, default=False)
subnet_id = wtypes.wsattr(wtypes.UuidType()) subnet_id = wtypes.wsattr(wtypes.UuidType())
monitor_port = wtypes.wsattr(wtypes.IntegerType( monitor_port = wtypes.wsattr(wtypes.IntegerType(

View File

@ -212,6 +212,7 @@ MAX_PORT_NUMBER = 65535
DEFAULT_CONNECTION_LIMIT = -1 DEFAULT_CONNECTION_LIMIT = -1
MIN_CONNECTION_LIMIT = -1 MIN_CONNECTION_LIMIT = -1
DEFAULT_WEIGHT = 1
MIN_WEIGHT = 0 MIN_WEIGHT = 0
MAX_WEIGHT = 256 MAX_WEIGHT = 256

View File

@ -1082,6 +1082,26 @@ class TestMember(base.BaseAPITest):
self.assertIn('Provider \'bad_driver\' reports error: broken', self.assertIn('Provider \'bad_driver\' reports error: broken',
response.json.get('faultstring')) response.json.get('faultstring'))
def test_update_unset_defaults(self):
old_name = "name1"
api_member = self.create_member(
self.pool_with_listener_id, '192.0.2.1', 80,
name=old_name, backup=True, monitor_address='192.0.2.2',
monitor_port=8888, weight=10).get(self.root_tag)
self.set_lb_status(self.lb_id)
unset_params = {'name': None, 'backup': None, 'monitor_address': None,
'monitor_port': None, 'weight': None}
member_path = self.member_path_listener.format(
member_id=api_member.get('id'))
response = self.put(member_path, self._build_body(unset_params))
response = response.json.get(self.root_tag)
self.assertFalse(response['backup'])
self.assertIsNone(response['monitor_address'])
self.assertIsNone(response['monitor_port'])
self.assertEqual('', response['name'])
self.assertEqual(constants.DEFAULT_WEIGHT, response['weight'])
def test_delete(self): def test_delete(self):
api_member = self.create_member( api_member = self.create_member(
self.pool_with_listener_id, '192.0.2.1', 80).get(self.root_tag) self.pool_with_listener_id, '192.0.2.1', 80).get(self.root_tag)