def put(self, id, listener_): """Updates a listener on a load balancer.""" listener = listener_.listener context = pecan_request.context.get('octavia_context') db_listener = self._get_db_listener(context.session, id, show_deleted=False) load_balancer_id = db_listener.load_balancer_id project_id, provider = self._get_lb_project_id_provider( context.session, load_balancer_id) self._auth_validate_action(context, project_id, constants.RBAC_PUT) self._validate_listener_PUT(listener, db_listener) 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) # Load the driver early as it also provides validation driver = driver_factory.get_driver(provider) with db_api.get_lock_session() as lock_session: self._test_lb_and_listener_statuses(lock_session, load_balancer_id, id=id) # Prepare the data for the driver data model listener_dict = listener.to_dict(render_unsets=False) listener_dict['id'] = id provider_listener_dict = ( driver_utils.listener_dict_to_provider_dict(listener_dict)) # Also prepare the baseline object data old_provider_listener = ( driver_utils.db_listener_to_provider_listener(db_listener, for_delete=True)) # Dispatch to the driver LOG.info("Sending update Listener %s to provider %s", id, driver.name) driver_utils.call_provider( driver.name, driver.listener_update, old_provider_listener, driver_dm.Listener.from_dict(provider_listener_dict)) # Update the database to reflect what the driver just accepted self.repositories.listener.update( lock_session, id, **listener.to_dict(render_unsets=False)) # Force SQL alchemy to query the DB, otherwise we get inconsistent # results context.session.expire_all() db_listener = self._get_db_listener(context.session, id) result = self._convert_db_to_type(db_listener, listener_types.ListenerResponse) return listener_types.ListenerRootResponse(listener=result)
def test_listener_dict_to_provider_dict(self, mock_load_cert, mock_secret): mock_secret.side_effect = [ 'ca cert', 'X509 CRL FILE', 'X509 POOL CA CERT FILE', 'X509 POOL CRL FILE' ] cert1 = data_models.TLSContainer(certificate='cert 1') cert2 = data_models.TLSContainer(certificate='cert 2') cert3 = data_models.TLSContainer(certificate='cert 3') listener_certs = {'tls_cert': cert1, 'sni_certs': [cert2, cert3]} pool_cert = data_models.TLSContainer(certificate='pool cert') pool_certs = {'tls_cert': pool_cert, 'sni_certs': []} mock_load_cert.side_effect = [listener_certs, pool_certs] # The reason to do this, as before the logic arrives the test func, # there are two data sources, one is from db_dict, the other is from # the api layer model_dict, actually, they are different and contain # different fields. That's why the test_listener1_dict from sample data # just contain the client_ca_tls_certificate_id for client certificate, # not any other related fields. So we need to delete them. expect_prov = copy.deepcopy(self.sample_data.provider_listener1_dict) expect_pool_prov = copy.deepcopy(self.sample_data.provider_pool1_dict) expect_prov['default_pool'] = expect_pool_prov provider_listener = utils.listener_dict_to_provider_dict( self.sample_data.test_listener1_dict) # TODO(johnsom) Remove this once the listener ACLs patch merges # https://review.opendev.org/#/c/659626/ del expect_prov['allowed_cidrs'] self.assertEqual(expect_prov, provider_listener)
def put(self, id, listener_): """Updates a listener on a load balancer.""" listener = listener_.listener context = pecan.request.context.get('octavia_context') db_listener = self._get_db_listener(context.session, id, show_deleted=False) load_balancer_id = db_listener.load_balancer_id project_id, provider = self._get_lb_project_id_provider( context.session, load_balancer_id) self._auth_validate_action(context, project_id, constants.RBAC_PUT) self._validate_listener_PUT(listener, db_listener) 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) # Load the driver early as it also provides validation driver = driver_factory.get_driver(provider) with db_api.get_lock_session() as lock_session: self._test_lb_and_listener_statuses(lock_session, load_balancer_id, id=id) # Prepare the data for the driver data model listener_dict = listener.to_dict(render_unsets=False) listener_dict['id'] = id provider_listener_dict = ( driver_utils.listener_dict_to_provider_dict(listener_dict)) # Also prepare the baseline object data old_provider_llistener = ( driver_utils.db_listener_to_provider_listener(db_listener)) # Dispatch to the driver LOG.info("Sending update Listener %s to provider %s", id, driver.name) driver_utils.call_provider( driver.name, driver.listener_update, old_provider_llistener, driver_dm.Listener.from_dict(provider_listener_dict)) # Update the database to reflect what the driver just accepted self.repositories.listener.update( lock_session, id, **listener.to_dict(render_unsets=False)) # Force SQL alchemy to query the DB, otherwise we get inconsistent # results context.session.expire_all() db_listener = self._get_db_listener(context.session, id) result = self._convert_db_to_type(db_listener, listener_types.ListenerResponse) return listener_types.ListenerRootResponse(listener=result)
def test_listener_dict_to_provider_dict(self, mock_load_cert): cert1 = data_models.TLSContainer(certificate='cert 1') cert2 = data_models.TLSContainer(certificate='cert 2') cert3 = data_models.TLSContainer(certificate='cert 3') mock_load_cert.return_value = { 'tls_cert': cert1, 'sni_certs': [cert2, cert3] } provider_listener = utils.listener_dict_to_provider_dict( self.sample_data.test_listener1_dict) self.assertEqual(self.sample_data.provider_listener1_dict, provider_listener)
def test_listener_dict_to_provider_dict_load_cert_error_for_delete( self, mock_load_cert, mock_secret): mock_secret.side_effect = ['ca cert', 'X509 CRL FILE', 'X509 POOL CA CERT FILE', 'X509 POOL CRL FILE'] mock_load_cert.side_effect = [Exception] # Test load_cert exception for_delete == True path expect_prov = copy.deepcopy(self.sample_data.provider_listener1_dict) expect_pool_prov = copy.deepcopy(self.sample_data.provider_pool1_dict) del expect_pool_prov['tls_container_data'] expect_prov['default_pool'] = expect_pool_prov del expect_prov['default_tls_container_data'] del expect_prov['sni_container_data'] provider_listener = utils.listener_dict_to_provider_dict( self.sample_data.test_listener1_dict, for_delete=True) self.assertEqual(expect_prov, provider_listener)
def test_listener_dict_to_provider_dict_load_cert_error_for_delete( self, mock_load_cert, mock_secret): mock_secret.side_effect = [ 'ca cert', 'X509 CRL FILE', 'X509 POOL CA CERT FILE', 'X509 POOL CRL FILE' ] mock_load_cert.side_effect = [Exception] # Test load_cert exception for_delete == True path expect_prov = copy.deepcopy(self.sample_data.provider_listener1_dict) expect_pool_prov = copy.deepcopy(self.sample_data.provider_pool1_dict) del expect_pool_prov['tls_container_data'] # TODO(johnsom) Remove when versions and ciphers are implemented expect_pool_prov.pop(lib_constants.TLS_VERSIONS) expect_prov.pop(lib_constants.TLS_VERSIONS) expect_prov['default_pool'] = expect_pool_prov del expect_prov['default_tls_container_data'] del expect_prov['sni_container_data'] provider_listener = utils.listener_dict_to_provider_dict( self.sample_data.test_listener1_dict, for_delete=True) self.assertEqual(expect_prov, provider_listener)
def test_listener_dict_to_provider_dict(self, mock_load_cert, mock_secret): mock_secret.side_effect = ['ca cert', 'X509 CRL FILE', 'X509 POOL CA CERT FILE', 'X509 POOL CRL FILE'] cert1 = data_models.TLSContainer(certificate='cert 1') cert2 = data_models.TLSContainer(certificate='cert 2') cert3 = data_models.TLSContainer(certificate='cert 3') listener_certs = {'tls_cert': cert1, 'sni_certs': [cert2, cert3]} pool_cert = data_models.TLSContainer(certificate='pool cert') pool_certs = {'tls_cert': pool_cert, 'sni_certs': []} mock_load_cert.side_effect = [listener_certs, pool_certs] # The reason to do this, as before the logic arrives the test func, # there are two data sources, one is from db_dict, the other is from # the api layer model_dict, actually, they are different and contain # different fields. That's why the test_listener1_dict from sample data # just contain the client_ca_tls_certificate_id for client certificate, # not any other related fields. So we need to delete them. expect_prov = copy.deepcopy(self.sample_data.provider_listener1_dict) expect_pool_prov = copy.deepcopy(self.sample_data.provider_pool1_dict) expect_prov['default_pool'] = expect_pool_prov provider_listener = utils.listener_dict_to_provider_dict( self.sample_data.test_listener1_dict) self.assertEqual(expect_prov, provider_listener)
def put(self, id, listener_): """Updates a listener on a load balancer.""" listener = listener_.listener context = pecan.request.context.get('octavia_context') db_listener = self._get_db_listener(context.session, id, show_deleted=False) load_balancer_id = db_listener.load_balancer_id project_id, provider = self._get_lb_project_id_provider( context.session, load_balancer_id) self._auth_validate_action(context, project_id, constants.RBAC_PUT) # TODO(rm_work): Do we need something like this? What do we do on an # empty body for a PUT? if not listener: raise exceptions.ValidationException( detail='No listener object supplied.') if (db_listener.protocol == constants.PROTOCOL_UDP and self._is_tls_or_insert_header(listener)): raise exceptions.ValidationException(detail=_( "%s protocol listener does not support TLS or header " "insertion.") % constants.PROTOCOL_UDP) if listener.default_pool_id: self._validate_pool(context.session, load_balancer_id, listener.default_pool_id, db_listener.protocol) sni_containers = listener.sni_container_refs or [] tls_refs = [sni for sni in sni_containers] if listener.default_tls_container_ref: tls_refs.append(listener.default_tls_container_ref) self._validate_tls_refs(tls_refs) # Load the driver early as it also provides validation driver = driver_factory.get_driver(provider) with db_api.get_lock_session() as lock_session: self._test_lb_and_listener_statuses(lock_session, load_balancer_id, id=id) # Prepare the data for the driver data model listener_dict = listener.to_dict(render_unsets=False) listener_dict['id'] = id provider_listener_dict = ( driver_utils.listener_dict_to_provider_dict(listener_dict)) # Also prepare the baseline object data old_provider_llistener = ( driver_utils.db_listener_to_provider_listener(db_listener)) # Dispatch to the driver LOG.info("Sending update Listener %s to provider %s", id, driver.name) driver_utils.call_provider( driver.name, driver.listener_update, old_provider_llistener, driver_dm.Listener.from_dict(provider_listener_dict)) # Update the database to reflect what the driver just accepted self.repositories.listener.update( lock_session, id, **listener.to_dict(render_unsets=False)) # Force SQL alchemy to query the DB, otherwise we get inconsistent # results context.session.expire_all() db_listener = self._get_db_listener(context.session, id) result = self._convert_db_to_type(db_listener, listener_types.ListenerResponse) return listener_types.ListenerRootResponse(listener=result)