Fix listener API handling of None/null updates
The current listener API does not properly handle clearing/reseting
values on update. Some integer only fields, such as connection-limit,
will accept null, but will store the value as "None". These will
will cause failures updating the amphora configuration.
This patch corrects this to appropriately handle None/null updates
to the listener parameters.
Change-Id: I41c9bedd8a3452513af3d409fbacd65ea287f02a
Story: 2005374
Task: 30352
(cherry picked from commit 930a3236bf
)
This commit is contained in:
parent
6da36f03c2
commit
85584435a5
|
@ -299,6 +299,32 @@ class ListenersController(base.BaseController):
|
|||
db_listener.l7policies = new_l7ps
|
||||
return db_listener
|
||||
|
||||
def _set_default_on_none(self, listener):
|
||||
"""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 listener.connection_limit is None:
|
||||
listener.connection_limit = constants.DEFAULT_CONNECTION_LIMIT
|
||||
if listener.timeout_client_data is None:
|
||||
listener.timeout_client_data = (
|
||||
constants.DEFAULT_TIMEOUT_CLIENT_DATA)
|
||||
if listener.timeout_member_connect is None:
|
||||
listener.timeout_member_connect = (
|
||||
constants.DEFAULT_TIMEOUT_MEMBER_CONNECT)
|
||||
if listener.timeout_member_data is None:
|
||||
listener.timeout_member_data = (
|
||||
constants.DEFAULT_TIMEOUT_MEMBER_DATA)
|
||||
if listener.timeout_tcp_inspect is None:
|
||||
listener.timeout_tcp_inspect = (
|
||||
constants.DEFAULT_TIMEOUT_TCP_INSPECT)
|
||||
|
||||
@wsme_pecan.wsexpose(listener_types.ListenerRootResponse, wtypes.text,
|
||||
body=listener_types.ListenerRootPUT, status_code=200)
|
||||
def put(self, id, listener_):
|
||||
|
@ -326,6 +352,8 @@ class ListenersController(base.BaseController):
|
|||
"%s protocol listener does not support TLS or header "
|
||||
"insertion.") % constants.PROTOCOL_UDP)
|
||||
|
||||
self._set_default_on_none(listener)
|
||||
|
||||
if listener.default_pool_id:
|
||||
self._validate_pool(context.session, load_balancer_id,
|
||||
listener.default_pool_id, db_listener.protocol)
|
||||
|
|
|
@ -101,7 +101,8 @@ class ListenerPOST(BaseListenerType):
|
|||
wtypes.IntegerType(minimum=constants.MIN_PORT_NUMBER,
|
||||
maximum=constants.MAX_PORT_NUMBER), mandatory=True)
|
||||
connection_limit = wtypes.wsattr(
|
||||
wtypes.IntegerType(minimum=constants.MIN_CONNECTION_LIMIT), default=-1)
|
||||
wtypes.IntegerType(minimum=constants.MIN_CONNECTION_LIMIT),
|
||||
default=constants.DEFAULT_CONNECTION_LIMIT)
|
||||
default_tls_container_ref = wtypes.wsattr(
|
||||
wtypes.StringType(max_length=255))
|
||||
sni_container_refs = [wtypes.StringType(max_length=255)]
|
||||
|
@ -177,7 +178,8 @@ class ListenerSingleCreate(BaseListenerType):
|
|||
wtypes.IntegerType(minimum=constants.MIN_PORT_NUMBER,
|
||||
maximum=constants.MAX_PORT_NUMBER), mandatory=True)
|
||||
connection_limit = wtypes.wsattr(
|
||||
wtypes.IntegerType(minimum=constants.MIN_CONNECTION_LIMIT), default=-1)
|
||||
wtypes.IntegerType(minimum=constants.MIN_CONNECTION_LIMIT),
|
||||
default=constants.DEFAULT_CONNECTION_LIMIT)
|
||||
default_tls_container_ref = wtypes.wsattr(
|
||||
wtypes.StringType(max_length=255))
|
||||
sni_container_refs = [wtypes.StringType(max_length=255)]
|
||||
|
|
|
@ -79,6 +79,7 @@ SUPPORTED_PROTOCOLS = (PROTOCOL_TCP, PROTOCOL_HTTPS, PROTOCOL_HTTP,
|
|||
MIN_PORT_NUMBER = 1
|
||||
MAX_PORT_NUMBER = 65535
|
||||
|
||||
DEFAULT_CONNECTION_LIMIT = -1
|
||||
MIN_CONNECTION_LIMIT = -1
|
||||
|
||||
MIN_WEIGHT = 0
|
||||
|
|
|
@ -933,6 +933,49 @@ class TestListener(base.BaseAPITest):
|
|||
listener['listener']['id'])
|
||||
|
||||
# TODO(johnsom) Fix this when there is a noop certificate manager
|
||||
@mock.patch('octavia.common.tls_utils.cert_parser.load_certificates_data')
|
||||
def test_update_unset_defaults(self, mock_cert_data):
|
||||
cert1 = data_models.TLSContainer(certificate='cert 1')
|
||||
mock_cert_data.return_value = {'tls_cert': cert1}
|
||||
tls_uuid = uuidutils.generate_uuid()
|
||||
listener = self.create_listener(
|
||||
constants.PROTOCOL_TERMINATED_HTTPS, 80, self.lb_id,
|
||||
name='listener1', description='desc1',
|
||||
admin_state_up=False, connection_limit=10,
|
||||
default_tls_container_ref=tls_uuid,
|
||||
default_pool_id=self.pool_id,
|
||||
insert_headers={'X-Forwarded-For': 'true'},
|
||||
timeout_client_data=1, timeout_member_connect=2,
|
||||
timeout_member_data=3, timeout_tcp_inspect=4).get(self.root_tag)
|
||||
self.set_lb_status(self.lb_id)
|
||||
unset_params = {
|
||||
'name': None, 'description': None, 'connection_limit': None,
|
||||
'default_tls_container_ref': None, 'sni_container_refs': None,
|
||||
'insert_headers': None, 'timeout_client_data': None,
|
||||
'timeout_member_connect': None, 'timeout_member_data': None,
|
||||
'timeout_tcp_inspect': None, 'default_pool_id': None}
|
||||
body = self._build_body(unset_params)
|
||||
listener_path = self.LISTENER_PATH.format(
|
||||
listener_id=listener['id'])
|
||||
api_listener = self.put(listener_path, body).json.get(self.root_tag)
|
||||
|
||||
self.assertEqual('', api_listener['name'])
|
||||
self.assertEqual('', api_listener['description'])
|
||||
self.assertEqual(constants.DEFAULT_CONNECTION_LIMIT,
|
||||
api_listener['connection_limit'])
|
||||
self.assertIsNone(api_listener['default_tls_container_ref'])
|
||||
self.assertEqual([], api_listener['sni_container_refs'])
|
||||
self.assertEqual({}, api_listener['insert_headers'])
|
||||
self.assertEqual(constants.DEFAULT_TIMEOUT_CLIENT_DATA,
|
||||
api_listener['timeout_client_data'])
|
||||
self.assertEqual(constants.DEFAULT_TIMEOUT_MEMBER_CONNECT,
|
||||
api_listener['timeout_member_connect'])
|
||||
self.assertEqual(constants.DEFAULT_TIMEOUT_MEMBER_DATA,
|
||||
api_listener['timeout_member_data'])
|
||||
self.assertEqual(constants.DEFAULT_TIMEOUT_TCP_INSPECT,
|
||||
api_listener['timeout_tcp_inspect'])
|
||||
self.assertIsNone(api_listener['default_pool_id'])
|
||||
|
||||
@mock.patch('octavia.common.tls_utils.cert_parser.load_certificates_data')
|
||||
def test_update_authorized(self, mock_cert_data):
|
||||
cert1 = data_models.TLSContainer(certificate='cert 1')
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
fixes:
|
||||
- |
|
||||
Fixed an issue where the listener API would accept null/None values for
|
||||
fields that must have a valid value, such as connection-limit.
|
||||
Now when a PUT call is made to one of these fields with null as the value
|
||||
the API will reset the field value to the field default value.
|
Loading…
Reference in New Issue