From de05d8f979ae916b7674d432b2bba4b7337b28bc Mon Sep 17 00:00:00 2001 From: Steven Bal Date: Thu, 5 Dec 2024 15:58:03 +0100 Subject: [PATCH 1/6] :heavy_plus_sign: Add optional setup-configuration dependency --- .readthedocs.yaml | 1 + setup.cfg | 2 ++ tox.ini | 2 ++ 3 files changed, 5 insertions(+) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 3b52192..39115b7 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -14,3 +14,4 @@ python: path: . extra_requirements: - db + - setup-configuration \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 86abbb3..e5d0b9c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -70,6 +70,8 @@ tests = zgw-consumers[testutils]>=0.35.1 pep8 = flake8 coverage = pytest-cov +setup-configuration = + django-setup-configuration>=0.4.0 docs = sphinx sphinx-rtd-theme diff --git a/tox.ini b/tox.ini index d362bb4..2d4faab 100644 --- a/tox.ini +++ b/tox.ini @@ -20,6 +20,7 @@ DJANGO = extras = tests coverage + setup-configuration deps = django42: Django~=4.2.0 passenv = @@ -53,6 +54,7 @@ skipsdist=true extras = docs tests + setup-configuration commands= pytest check_sphinx.py -v \ --junitxml=../reports/junit-{envname}.xml \ From 7d45707b5a82ad6764184b5960fefbb5d9c1da05 Mon Sep 17 00:00:00 2001 From: Steven Bal Date: Thu, 5 Dec 2024 15:58:18 +0100 Subject: [PATCH 2/6] :sparkles: Add ConfigurationStep for NotificationsConfig --- notifications_api_common/contrib/__init__.py | 0 .../contrib/setup_configuration/__init__.py | 0 .../contrib/setup_configuration/models.py | 18 +++++++ .../contrib/setup_configuration/steps.py | 51 +++++++++++++++++++ 4 files changed, 69 insertions(+) create mode 100644 notifications_api_common/contrib/__init__.py create mode 100644 notifications_api_common/contrib/setup_configuration/__init__.py create mode 100644 notifications_api_common/contrib/setup_configuration/models.py create mode 100644 notifications_api_common/contrib/setup_configuration/steps.py diff --git a/notifications_api_common/contrib/__init__.py b/notifications_api_common/contrib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/notifications_api_common/contrib/setup_configuration/__init__.py b/notifications_api_common/contrib/setup_configuration/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/notifications_api_common/contrib/setup_configuration/models.py b/notifications_api_common/contrib/setup_configuration/models.py new file mode 100644 index 0000000..5e7d6ed --- /dev/null +++ b/notifications_api_common/contrib/setup_configuration/models.py @@ -0,0 +1,18 @@ +from django_setup_configuration.models import ConfigurationModel, DjangoModelRef + +from notifications_api_common.models import NotificationsConfig + + +class NotificationConfigurationModel(ConfigurationModel): + notifications_api_service_identifier: str = DjangoModelRef( + NotificationsConfig, "notifications_api_service", default="" + ) + + class Meta: + django_model_refs = { + NotificationsConfig: [ + "notification_delivery_max_retries", + "notification_delivery_retry_backoff", + "notification_delivery_retry_backoff_max", + ] + } diff --git a/notifications_api_common/contrib/setup_configuration/steps.py b/notifications_api_common/contrib/setup_configuration/steps.py new file mode 100644 index 0000000..e2aa88b --- /dev/null +++ b/notifications_api_common/contrib/setup_configuration/steps.py @@ -0,0 +1,51 @@ +from django_setup_configuration.configuration import BaseConfigurationStep +from zgw_consumers.models import Service + +from notifications_api_common.models import NotificationsConfig + +from .models import NotificationConfigurationModel + + +def get_service(slug: str) -> Service: + """ + Try to find a Service and re-raise DoesNotExist with the identifier + to make debugging easier + """ + try: + return Service.objects.get(slug=slug) + except Service.DoesNotExist as e: + raise Service.DoesNotExist(f"{str(e)} (identifier = {slug})") + + +class NotificationConfigurationStep( + BaseConfigurationStep[NotificationConfigurationModel] +): + """ + Configure settings for Notificaties API + """ + + verbose_name = "Configuration for Notificaties API" + config_model = NotificationConfigurationModel + namespace = "notifications_config" + enable_setting = "notifications_config_enable" + + def execute(self, model: NotificationConfigurationModel): + config = NotificationsConfig.get_solo() + + if identifier := model.notifications_api_service_identifier: + config.notifications_api_service = get_service(identifier) + + if model.notification_delivery_max_retries: + config.notification_delivery_max_retries = ( + model.notification_delivery_max_retries + ) + if model.notification_delivery_retry_backoff: + config.notification_delivery_retry_backoff = ( + model.notification_delivery_retry_backoff + ) + if model.notification_delivery_retry_backoff_max: + config.notification_delivery_retry_backoff_max = ( + model.notification_delivery_retry_backoff_max + ) + + config.save() From 11dd31a25e664e532aca7afd5979798c8a91d7e9 Mon Sep 17 00:00:00 2001 From: Steven Bal Date: Thu, 5 Dec 2024 15:58:38 +0100 Subject: [PATCH 3/6] :white_check_mark: Add tests for NotificationConfigurationStep --- testapp/settings.py | 1 + .../setup_config_notifications_config.yaml | 6 ++ ...onfig_notifications_config_no_service.yaml | 5 + tests/test_configuration_steps.py | 92 +++++++++++++++++++ 4 files changed, 104 insertions(+) create mode 100644 tests/files/setup_config_notifications_config.yaml create mode 100644 tests/files/setup_config_notifications_config_no_service.yaml create mode 100644 tests/test_configuration_steps.py diff --git a/testapp/settings.py b/testapp/settings.py index 1daf370..cb3a436 100644 --- a/testapp/settings.py +++ b/testapp/settings.py @@ -33,6 +33,7 @@ "simple_certmanager", "zgw_consumers", "notifications_api_common", + "django_setup_configuration", "testapp", ] diff --git a/tests/files/setup_config_notifications_config.yaml b/tests/files/setup_config_notifications_config.yaml new file mode 100644 index 0000000..cbef426 --- /dev/null +++ b/tests/files/setup_config_notifications_config.yaml @@ -0,0 +1,6 @@ +notifications_config_enable: true +notifications_config: + notifications_api_service_identifier: notifs-api + notification_delivery_max_retries: 1 + notification_delivery_retry_backoff: 2 + notification_delivery_retry_backoff_max: 3 diff --git a/tests/files/setup_config_notifications_config_no_service.yaml b/tests/files/setup_config_notifications_config_no_service.yaml new file mode 100644 index 0000000..877c6db --- /dev/null +++ b/tests/files/setup_config_notifications_config_no_service.yaml @@ -0,0 +1,5 @@ +notifications_config_enable: true +notifications_config: + notification_delivery_max_retries: 1 + notification_delivery_retry_backoff: 2 + notification_delivery_retry_backoff_max: 3 diff --git a/tests/test_configuration_steps.py b/tests/test_configuration_steps.py new file mode 100644 index 0000000..837e31a --- /dev/null +++ b/tests/test_configuration_steps.py @@ -0,0 +1,92 @@ +import pytest +from django_setup_configuration.test_utils import execute_single_step +from zgw_consumers.test.factories import ServiceFactory + +from notifications_api_common.contrib.setup_configuration.steps import ( + NotificationConfigurationStep, +) +from notifications_api_common.models import NotificationsConfig + +CONFIG_FILE_PATH = "tests/files/setup_config_notifications_config.yaml" +CONFIG_FILE_PATH_NO_SERVICE = ( + "tests/files/setup_config_notifications_config_no_service.yaml" +) + + +@pytest.mark.django_db +def test_execute_configuration_step_success(): + service = ServiceFactory.create( + slug="notifs-api", api_root="http://notificaties.local/api/v1/" + ) + + execute_single_step(NotificationConfigurationStep, yaml_source=CONFIG_FILE_PATH) + + config = NotificationsConfig.get_solo() + + assert config.notifications_api_service == service + assert config.notification_delivery_max_retries == 1 + assert config.notification_delivery_retry_backoff == 2 + assert config.notification_delivery_retry_backoff_max == 3 + + +@pytest.mark.django_db +def test_execute_configuration_step_update_existing(): + service1 = ServiceFactory.create( + slug="other-api", api_root="http://other-notificaties.local/api/v1/" + ) + service2 = ServiceFactory.create( + slug="notifs-api", api_root="http://notificaties.local/api/v1/" + ) + + config = NotificationsConfig.get_solo() + config.notifications_api_service = service1 + config.notification_delivery_max_retries = 1 + config.notification_delivery_retry_backoff = 2 + config.notification_delivery_retry_backoff_max = 3 + config.save() + + execute_single_step(NotificationConfigurationStep, yaml_source=CONFIG_FILE_PATH) + + config = NotificationsConfig.get_solo() + + assert config.notifications_api_service == service2 + assert config.notification_delivery_max_retries == 1 + assert config.notification_delivery_retry_backoff == 2 + assert config.notification_delivery_retry_backoff_max == 3 + + +@pytest.mark.django_db +def test_execute_configuration_step_without_service_success(): + execute_single_step( + NotificationConfigurationStep, yaml_source=CONFIG_FILE_PATH_NO_SERVICE + ) + + config = NotificationsConfig.get_solo() + + assert config.notifications_api_service is None + assert config.notification_delivery_max_retries == 1 + assert config.notification_delivery_retry_backoff == 2 + assert config.notification_delivery_retry_backoff_max == 3 + + +@pytest.mark.django_db +def test_execute_configuration_step_idempotent(): + service = ServiceFactory.create( + slug="notifs-api", api_root="http://notificaties.local/api/v1/" + ) + + def make_assertions(): + config = NotificationsConfig.get_solo() + + assert config.notifications_api_service == service + assert config.notification_delivery_max_retries == 1 + assert config.notification_delivery_retry_backoff == 2 + assert config.notification_delivery_retry_backoff_max == 3 + + execute_single_step(NotificationConfigurationStep, yaml_source=CONFIG_FILE_PATH) + + make_assertions() + + execute_single_step(NotificationConfigurationStep, yaml_source=CONFIG_FILE_PATH) + + make_assertions() From d81ca6c5d8e29bb3ca55aa0d31d86fbf12837ad2 Mon Sep 17 00:00:00 2001 From: Steven Bal Date: Fri, 6 Dec 2024 12:21:30 +0100 Subject: [PATCH 4/6] :memo: Add docs for NotificationConfigurationStep --- docs/index.rst | 1 + docs/setup_config.rst | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 docs/setup_config.rst diff --git a/docs/index.rst b/docs/index.rst index 3254567..f995ef3 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -23,6 +23,7 @@ Features :caption: Contents: quickstart + setup_config Indices and tables diff --git a/docs/setup_config.rst b/docs/setup_config.rst new file mode 100644 index 0000000..efe8584 --- /dev/null +++ b/docs/setup_config.rst @@ -0,0 +1,40 @@ +Setup configuration +=================== + +Loading notification configuration from a YAML file +*************************************************** + +This library provides a ``ConfigurationStep`` +(from the library ``django-setup-configuration``, see the +`documentation `_ +for more information on how to run ``setup_configuration``) +to configure the notification configuration. + +To add this step to your configuration steps, add ``django_setup_configuration`` to ``INSTALLED_APPS`` and add the following setting: + + .. code:: python + + SETUP_CONFIGURATION_STEPS = [ + ... + "notifications_api_common.contrib.setup_configuration.steps.NotificationConfigurationStep" + ... + ] + +The YAML file that is passed to ``setup_configuration`` must set the +``notifications_config_enable`` flag to ``true`` to enable the step. All fields under ``notifications_config`` are optional. + +Example file: + + .. code:: yaml + + notifications_config_enable: True + notifications_config: + notifications_api_service_identifier: notifs-api + notification_delivery_max_retries: 1 + notification_delivery_retry_backoff: 2 + notification_delivery_retry_backoff_max: 3 + +If the ``notifications_api_service_identifier`` is specified, it might also be useful +to use the `ServiceConfigurationStep `_ +from ``zgw-consumers``. + From 6687e99737c2e4c66ef62997dda67412beeae85c Mon Sep 17 00:00:00 2001 From: Sidney Richards Date: Mon, 9 Dec 2024 15:10:54 +0100 Subject: [PATCH 5/6] :sparkles: Add ConfigurationStep for Subscriptions --- docs/setup_config.rst | 30 +++- .../contrib/setup_configuration/models.py | 29 +++- .../contrib/setup_configuration/steps.py | 58 ++++++- setup.cfg | 1 + .../setup_config_subscriptions_config.yaml | 19 +++ .../test_subscription_configuration_steps.py | 143 ++++++++++++++++++ 6 files changed, 271 insertions(+), 9 deletions(-) create mode 100644 tests/files/setup_config_subscriptions_config.yaml create mode 100644 tests/test_subscription_configuration_steps.py diff --git a/docs/setup_config.rst b/docs/setup_config.rst index efe8584..9e058a1 100644 --- a/docs/setup_config.rst +++ b/docs/setup_config.rst @@ -4,24 +4,28 @@ Setup configuration Loading notification configuration from a YAML file *************************************************** -This library provides a ``ConfigurationStep`` +This library provides two ``ConfigurationStep`` implementations (from the library ``django-setup-configuration``, see the `documentation `_ -for more information on how to run ``setup_configuration``) -to configure the notification configuration. +for more information on how to run ``setup_configuration``): one to configure the +service and retry settings, another to configure notification endpoint subscriptions. -To add this step to your configuration steps, add ``django_setup_configuration`` to ``INSTALLED_APPS`` and add the following setting: +To add these steps to your configuration steps, add ``django_setup_configuration`` +to ``INSTALLED_APPS`` and add the following settings: .. code:: python SETUP_CONFIGURATION_STEPS = [ ... + # Note the order: NotificationSubscriptionConfigurationStep expects a notification service + # to have been configured by NotificationConfigurationStep "notifications_api_common.contrib.setup_configuration.steps.NotificationConfigurationStep" + "notifications_api_common.contrib.setup_configuration.steps.NotificationSubscriptionConfigurationStep" ... ] -The YAML file that is passed to ``setup_configuration`` must set the -``notifications_config_enable`` flag to ``true`` to enable the step. All fields under ``notifications_config`` are optional. +The YAML file that is passed to ``setup_configuration`` must set the appropriate +flag and fields for both steps: Example file: @@ -34,7 +38,21 @@ Example file: notification_delivery_retry_backoff: 2 notification_delivery_retry_backoff_max: 3 + notifications_subscriptions_config_enable: true + notifications_subscriptions_config: + items: + - identifier: my-subscription + callback_url: http://my/callback + client_id: the-client + secret: supersecret + uuid: 0f616bfd-aacc-4d85-a140-2af17a56217b + channels: + - Foo + - Bar + If the ``notifications_api_service_identifier`` is specified, it might also be useful to use the `ServiceConfigurationStep `_ from ``zgw-consumers``. +Note that the ``uuid`` field in your subscriptions config must point to an existing +``Abonnement`` in the Open Notificaties service configured through ``notifications_config``. diff --git a/notifications_api_common/contrib/setup_configuration/models.py b/notifications_api_common/contrib/setup_configuration/models.py index 5e7d6ed..308e3d5 100644 --- a/notifications_api_common/contrib/setup_configuration/models.py +++ b/notifications_api_common/contrib/setup_configuration/models.py @@ -1,6 +1,7 @@ from django_setup_configuration.models import ConfigurationModel, DjangoModelRef +from pydantic import UUID4, Field -from notifications_api_common.models import NotificationsConfig +from notifications_api_common.models import NotificationsConfig, Subscription class NotificationConfigurationModel(ConfigurationModel): @@ -16,3 +17,29 @@ class Meta: "notification_delivery_retry_backoff_max", ] } + + +class SubscriptionConfigurationItem(ConfigurationModel): + uuid: UUID4 = Field( + description="The UUID for this subscription. Must match the UUID of the corresponding `Abonnement` in Open Notificaties." + ) + + channels: list[str] = DjangoModelRef( + Subscription, + "channels", + default_factory=list, + ) + + class Meta: + django_model_refs = { + Subscription: [ + "identifier", + "callback_url", + "client_id", + "secret", + ] + } + + +class SubscriptionConfigurationModel(ConfigurationModel): + items: list[SubscriptionConfigurationItem] diff --git a/notifications_api_common/contrib/setup_configuration/steps.py b/notifications_api_common/contrib/setup_configuration/steps.py index e2aa88b..8c79564 100644 --- a/notifications_api_common/contrib/setup_configuration/steps.py +++ b/notifications_api_common/contrib/setup_configuration/steps.py @@ -1,9 +1,15 @@ +import logging + from django_setup_configuration.configuration import BaseConfigurationStep +from django_setup_configuration.exceptions import ConfigurationRunFailed +from furl import furl from zgw_consumers.models import Service -from notifications_api_common.models import NotificationsConfig +from notifications_api_common.models import NotificationsConfig, Subscription + +from .models import NotificationConfigurationModel, SubscriptionConfigurationModel -from .models import NotificationConfigurationModel +logger = logging.getLogger(__name__) def get_service(slug: str) -> Service: @@ -49,3 +55,51 @@ def execute(self, model: NotificationConfigurationModel): ) config.save() + + +class NotificationSubscriptionConfigurationStep( + BaseConfigurationStep[SubscriptionConfigurationModel] +): + """ + Configure settings for Notificaties API Subscriptions + """ + + verbose_name = "Configuration for Notificaties API Subscriptions" + config_model = SubscriptionConfigurationModel + namespace = "notifications_subscriptions_config" + enable_setting = "notifications_subscriptions_config_enable" + + def execute(self, model: SubscriptionConfigurationModel): + config = NotificationsConfig.get_solo() + + if not (notifications_api := config.notifications_api_service): + raise ConfigurationRunFailed( + "No Notifications API Service configured. Please ensure you've first " + f"run {NotificationConfigurationStep.__name__}" + ) + + if len(model.items) == 0: + raise ConfigurationRunFailed("You must configure at least one subscription") + + for item in model.items: + detail_url = furl(notifications_api.api_root) + detail_url.path /= f"/abonnement/{item.uuid!s}" + detail_url.path.normalize() + + subscription, created = Subscription.objects.update_or_create( + identifier=item.identifier, + defaults={ + "client_id": item.client_id, + "secret": item.secret, + "channels": item.channels, + "callback_url": item.callback_url, + "_subscription": str(detail_url), + }, + ) + + logger.debug( + "%s subscription with identifier='%s' and pk='%s'", + "Created" if created else "Updated", + subscription.identifier, + subscription.pk, + ) diff --git a/setup.cfg b/setup.cfg index e5d0b9c..8293a4e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -72,6 +72,7 @@ pep8 = flake8 coverage = pytest-cov setup-configuration = django-setup-configuration>=0.4.0 + furl docs = sphinx sphinx-rtd-theme diff --git a/tests/files/setup_config_subscriptions_config.yaml b/tests/files/setup_config_subscriptions_config.yaml new file mode 100644 index 0000000..e8602be --- /dev/null +++ b/tests/files/setup_config_subscriptions_config.yaml @@ -0,0 +1,19 @@ +notifications_subscriptions_config_enable: true +notifications_subscriptions_config: + items: + - identifier: my-subscription + callback_url: http://my/callback + client_id: the-client + secret: supersecret + uuid: 0f616bfd-aacc-4d85-a140-2af17a56217b + channels: + - Foo + - Bar + - identifier: my-other-subscription + callback_url: http://my/other-callback + client_id: the-client + secret: supersecret + uuid: a33cf110-06b6-454e-b7e9-5139c172ca9a + channels: + - Fuh + - Bahr diff --git a/tests/test_subscription_configuration_steps.py b/tests/test_subscription_configuration_steps.py new file mode 100644 index 0000000..d786d48 --- /dev/null +++ b/tests/test_subscription_configuration_steps.py @@ -0,0 +1,143 @@ +import pytest +from django_setup_configuration.exceptions import ConfigurationRunFailed +from django_setup_configuration.test_utils import execute_single_step +from zgw_consumers.test.factories import ServiceFactory + +from notifications_api_common.contrib.setup_configuration.steps import ( + NotificationSubscriptionConfigurationStep, +) +from notifications_api_common.models import NotificationsConfig, Subscription + +CONFIG_FILE_PATH = "tests/files/setup_config_subscriptions_config.yaml" + + +@pytest.mark.django_db +def test_execute_configuration_step_success(): + config = NotificationsConfig.get_solo() + config.notifications_api_service = ServiceFactory.create( + slug="notifs-api", api_root="http://notificaties.local/api/v1/" + ) + config.save() + + execute_single_step( + NotificationSubscriptionConfigurationStep, yaml_source=CONFIG_FILE_PATH + ) + + value = list( + Subscription.objects.values_list( + "identifier", + "client_id", + "secret", + "channels", + "callback_url", + "_subscription", + ) + ) + expected = [ + ( + "my-subscription", + "the-client", + "supersecret", + ["Foo", "Bar"], + "http://my/callback", + "http://notificaties.local/api/v1/abonnement/0f616bfd-aacc-4d85-a140-2af17a56217b", + ), + ( + "my-other-subscription", + "the-client", + "supersecret", + ["Fuh", "Bahr"], + "http://my/other-callback", + "http://notificaties.local/api/v1/abonnement/a33cf110-06b6-454e-b7e9-5139c172ca9a", + ), + ] + + assert value == expected + + +@pytest.mark.django_db +def test_existing_items_are_updated(): + config = NotificationsConfig.get_solo() + config.notifications_api_service = ServiceFactory.create( + slug="notifs-api", api_root="http://notificaties.local/api/v1/" + ) + config.save() + + Subscription.objects.create( + identifier="my-subscription", + callback_url="http://my/initial-callback", + client_id="the-old-client", + secret="secretsuper", + channels=["Fuzz"], + ) + + execute_single_step( + NotificationSubscriptionConfigurationStep, yaml_source=CONFIG_FILE_PATH + ) + + value = list( + Subscription.objects.values_list( + "identifier", + "client_id", + "secret", + "channels", + "callback_url", + "_subscription", + ) + ) + expected = [ + # Updated + ( + "my-subscription", + "the-client", + "supersecret", + ["Foo", "Bar"], + "http://my/callback", + "http://notificaties.local/api/v1/abonnement/0f616bfd-aacc-4d85-a140-2af17a56217b", + ), + # Created + ( + "my-other-subscription", + "the-client", + "supersecret", + ["Fuh", "Bahr"], + "http://my/other-callback", + "http://notificaties.local/api/v1/abonnement/a33cf110-06b6-454e-b7e9-5139c172ca9a", + ), + ] + + assert value == expected + + +@pytest.mark.django_db +def test_missing_notifications_service_raises(): + config = NotificationsConfig.get_solo() + config.notifications_api_service = None + config.save() + + with pytest.raises(ConfigurationRunFailed) as excinfo: + execute_single_step( + NotificationSubscriptionConfigurationStep, yaml_source=CONFIG_FILE_PATH + ) + + assert ( + str(excinfo.value) + == "No Notifications API Service configured. Please ensure you've first run NotificationConfigurationStep" + ) + + +@pytest.mark.django_db +def test_no_items_raises(): + config = NotificationsConfig.get_solo() + config.notifications_api_service = ServiceFactory.create( + slug="notifs-api", api_root="http://notificaties.local/api/v1/" + ) + config.save() + + with pytest.raises(ConfigurationRunFailed) as excinfo: + execute_single_step( + NotificationSubscriptionConfigurationStep, + object_source={"notifications_subscriptions_config": {"items": []}}, + ) + + assert str(excinfo.value) == "You must configure at least one subscription" From 57363d4de3439f4367a0125703605d44b157f641 Mon Sep 17 00:00:00 2001 From: Sidney Richards Date: Thu, 12 Dec 2024 09:20:45 +0100 Subject: [PATCH 6/6] Make notifications_api_service_identifier required on NotificationConfigurationModel --- docs/setup_config.rst | 4 ++-- .../contrib/setup_configuration/models.py | 3 ++- tests/test_configuration_steps.py | 18 +++++++++--------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/docs/setup_config.rst b/docs/setup_config.rst index 9e058a1..fafd3d1 100644 --- a/docs/setup_config.rst +++ b/docs/setup_config.rst @@ -50,9 +50,9 @@ Example file: - Foo - Bar -If the ``notifications_api_service_identifier`` is specified, it might also be useful +Because ``notifications_api_service_identifier`` is required, it might also be useful to use the `ServiceConfigurationStep `_ -from ``zgw-consumers``. +from ``zgw-consumers`` to configure the ``Service`` object for the notifications API. Note that the ``uuid`` field in your subscriptions config must point to an existing ``Abonnement`` in the Open Notificaties service configured through ``notifications_config``. diff --git a/notifications_api_common/contrib/setup_configuration/models.py b/notifications_api_common/contrib/setup_configuration/models.py index 308e3d5..0f4f79e 100644 --- a/notifications_api_common/contrib/setup_configuration/models.py +++ b/notifications_api_common/contrib/setup_configuration/models.py @@ -6,7 +6,8 @@ class NotificationConfigurationModel(ConfigurationModel): notifications_api_service_identifier: str = DjangoModelRef( - NotificationsConfig, "notifications_api_service", default="" + NotificationsConfig, + "notifications_api_service", ) class Meta: diff --git a/tests/test_configuration_steps.py b/tests/test_configuration_steps.py index 837e31a..57968f0 100644 --- a/tests/test_configuration_steps.py +++ b/tests/test_configuration_steps.py @@ -1,4 +1,5 @@ import pytest +from django_setup_configuration.exceptions import PrerequisiteFailed from django_setup_configuration.test_utils import execute_single_step from zgw_consumers.test.factories import ServiceFactory @@ -57,17 +58,16 @@ def test_execute_configuration_step_update_existing(): @pytest.mark.django_db def test_execute_configuration_step_without_service_success(): - execute_single_step( - NotificationConfigurationStep, yaml_source=CONFIG_FILE_PATH_NO_SERVICE + with pytest.raises(PrerequisiteFailed) as excinfo: + execute_single_step( + NotificationConfigurationStep, yaml_source=CONFIG_FILE_PATH_NO_SERVICE + ) + + assert ( + "notifications_config.notifications_api_service_identifier\n Input should be a valid string" + in str(excinfo.value) ) - config = NotificationsConfig.get_solo() - - assert config.notifications_api_service is None - assert config.notification_delivery_max_retries == 1 - assert config.notification_delivery_retry_backoff == 2 - assert config.notification_delivery_retry_backoff_max == 3 - @pytest.mark.django_db def test_execute_configuration_step_idempotent():