From 229d7fb3d952a2706f7a658f7a6bc261d6e1b182 Mon Sep 17 00:00:00 2001 From: Aleksandr Komissarov Date: Tue, 21 Nov 2023 15:48:24 +0100 Subject: [PATCH] LITE-28135 added coverage --- connect/eaas/runner/helpers.py | 40 +++++++++++++++++++++------------- tests/test_helpers.py | 37 +++++++++++++++++++++++++++++++ tests/workers/test_events.py | 34 +++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 15 deletions(-) diff --git a/connect/eaas/runner/helpers.py b/connect/eaas/runner/helpers.py index dc97108..24558c8 100644 --- a/connect/eaas/runner/helpers.py +++ b/connect/eaas/runner/helpers.py @@ -60,6 +60,7 @@ TRANSFORMATION_TASK_MAX_EXECUTION_TIME, TRANSFORMATION_WRITE_QUEUE_TIMEOUT, ) +from django.core.exceptions import ImproperlyConfigured # noqa: I001 logger = logging.getLogger('connect.eaas') @@ -626,13 +627,18 @@ def get_features_table(features): return table -def enforce_and_override_django_settings( - config, - django_secret_key_variable, - overridden_settings, -): +def enforce_and_override_django_settings(config, django_secret_key_variable, overridden_settings): from django.conf import settings # noqa: I001 - from django.core.exceptions import ImproperlyConfigured # noqa: I001 + _validate_django_secret_key(config, django_secret_key_variable) + _set_django_secret_key(config, django_secret_key_variable, settings) + overrides = copy.copy(overridden_settings) + _override_and_validate_settings(config, overrides) + _override_database_settings(overrides, settings) + _apply_enforced_settings(settings) + _configure_host_and_debug(config, settings) + + +def _validate_django_secret_key(config, django_secret_key_variable): if not django_secret_key_variable: raise ImproperlyConfigured( 'Your extension class must be decorated with the ' @@ -645,41 +651,45 @@ def enforce_and_override_django_settings( 'not been found and it is mandatory to setup django.', ) + +def _set_django_secret_key(config, django_secret_key_variable, settings): settings.SECRET_KEY = config.variables[django_secret_key_variable] - overrides = copy.copy(overridden_settings) +def _override_and_validate_settings(config, overrides): required_overrides = list(DJANGO_REQUIRED_OVERRIDE_SETTINGS) if config.environment_runtime == 'cloud': required_overrides.append('DATABASES') for required_setting in required_overrides: - if required_setting not in overrides.keys(): + if required_setting not in overrides: raise ImproperlyConfigured( f'The settings `{",".join(required_overrides)}` must be overridden.', ) for non_overrideable_setting in DJANGO_NON_OVERRIDEABLE_SETTINGS: - if non_overrideable_setting in overrides.keys(): + if non_overrideable_setting in overrides: raise ImproperlyConfigured( 'The settings ' f'`{",".join(DJANGO_NON_OVERRIDEABLE_SETTINGS)}` cannot be overridden.', ) - databases_override = overrides.pop('DATABASES', None) - for setting, setting_value in overrides.items(): - setattr(settings, setting, setting_value) +def _override_database_settings(overrides, settings): + databases_override = overrides.pop('DATABASES', None) if databases_override: for db, db_config in databases_override.items(): - for prop, propvalue in db_config.items(): - settings.DATABASES[db][prop] = propvalue + for prop, prop_value in db_config.items(): + settings.DATABASES[db][prop] = prop_value + +def _apply_enforced_settings(settings): for setting, setting_value in DJANGO_ENFORCED_SETTINGS.items(): setattr(settings, setting, setting_value) + +def _configure_host_and_debug(config, settings): if config.environment_hostname and config.environment_domain: settings.ALLOWED_HOSTS = [ f'{config.environment_hostname}.{config.environment_domain}', ] - if config.environment_runtime == 'cloud': settings.DEBUG = False diff --git a/tests/test_helpers.py b/tests/test_helpers.py index a0281b0..d098a50 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -945,3 +945,40 @@ def test_enforce_and_override_django_settings_enforced(mocker): for setting, setting_value in DJANGO_ENFORCED_SETTINGS.items(): assert getattr(settings_mock, setting) == setting_value + + +def test_missing_django_secret(mocker): + mocker.patch.object(django.conf, 'settings', mocker.MagicMock()) + config_mock = mocker.MagicMock( + environment_runtime='cloud', + environment_hostname='srvc-1234-dev', + environment_domain='extensions.io', + variables={'DJ_SECRET': 'my-secret'}, + ) + overrides = {} + + with pytest.raises(ImproperlyConfigured) as cv: + enforce_and_override_django_settings(config_mock, False, overrides) + + assert str(cv.value) == ( + "Your extension class must be decorated with the `@django_secret_key_variable` " + "to specify the name of the environment variable that store the django `SECRET_KEY`." + ) + + +def test_improperly_configured_django_secret_settings(mocker): + mocker.patch.object(django.conf, 'settings', mocker.MagicMock()) + config_mock = mocker.MagicMock( + environment_runtime='cloud', + environment_hostname='srvc-1234-dev', + environment_domain='extensions.io', + variables={'DJ_SECRET': 'my-secret'}, + ) + overrides = {} + + with pytest.raises(ImproperlyConfigured) as cv: + enforce_and_override_django_settings(config_mock, 'False', overrides) + + assert str(cv.value) == ( + "The environment variable False has not been found and it is mandatory to setup django." + ) diff --git a/tests/workers/test_events.py b/tests/workers/test_events.py index ff06963..7c78a3d 100644 --- a/tests/workers/test_events.py +++ b/tests/workers/test_events.py @@ -1840,6 +1840,40 @@ async def test_ensure_connection_exit_max_attemps(mocker, caplog): assert 'max connection attemps reached, exit!' in caplog.text +@pytest.mark.asyncio +async def test_connection_refused(mocker, caplog): + mocker.patch.object( + EventsApp, + 'load_application', + ) + mocker.patch('connect.eaas.runner.workers.base.MAX_RETRY_TIME_GENERIC_SECONDS', 1) + mocker.patch('connect.eaas.runner.workers.base.MAX_RETRY_DELAY_TIME_SECONDS', .01) + mocker.patch('connect.eaas.runner.workers.base.MAX_RETRY_TIME_MAINTENANCE_SECONDS', .1) + mocker.patch( + 'connect.eaas.runner.workers.base.websockets.connect', + side_effect=ConnectionClosedError(1006, 'disconnected'), + ) + + config = ConfigHelper(secure=False) + ext_handler = EventsApp(config) + + worker = EventsWorker( + ext_handler, + mocker.MagicMock(), + mocker.MagicMock(), + mocker.MagicMock(), + ) + worker.run_event.set() + worker.get_url = lambda: 'ws://test' + + with pytest.raises(CommunicationError): + with caplog.at_level(logging.INFO): + await worker.ensure_connection() + + assert 'connection closed by the host...' in caplog.text + assert '1st communication attempt failed, backing off waiting' in caplog.text + + @pytest.mark.asyncio async def test_shutdown_pending_task_timeout( mocker, ws_server, unused_port, settings_payload, caplog,