From 6b89e06548c8e1ba6150725fff80df01f62b3458 Mon Sep 17 00:00:00 2001 From: Steven Bal Date: Mon, 11 Nov 2024 16:57:56 +0100 Subject: [PATCH 1/5] :heavy_plus_sign: [#100] Add optional django-setup-configuration dependency --- .readthedocs.yaml | 1 + pyproject.toml | 3 +++ tox.ini | 2 ++ 3 files changed, 6 insertions(+) diff --git a/.readthedocs.yaml b/.readthedocs.yaml index 0bd1e4a..49f79f6 100644 --- a/.readthedocs.yaml +++ b/.readthedocs.yaml @@ -17,6 +17,7 @@ python: - docs - db - drf + - setup-configuration sphinx: configuration: docs/conf.py diff --git a/pyproject.toml b/pyproject.toml index 877a269..9c83875 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,6 +53,9 @@ drf = [ zds-client = [ "gemma-zds-client>=2.0.0", ] +setup-configuration = [ + "django-setup-configuration>=0.4.0", +] # These are not the test requirements! They are extras to be installed when making use of `zgw_consumers.test` testutils = [ "Faker>=0.7.0", diff --git a/tox.ini b/tox.ini index 81bd276..3e799a3 100644 --- a/tox.ini +++ b/tox.ini @@ -32,6 +32,7 @@ extras = testutils tests coverage + setup-configuration deps = django42: Django~=4.2.0 commands = @@ -64,6 +65,7 @@ extras = db drf docs + setup-configuration commands= pytest check_sphinx.py -v \ --tb=auto \ From 130b0d469e256e685d8463ba25e42c145ac6800d Mon Sep 17 00:00:00 2001 From: Steven Bal Date: Tue, 12 Nov 2024 15:10:20 +0100 Subject: [PATCH 2/5] :sparkles: [#100] Add ConfigurationStep for Service model which can load any number of Services, configured in a YAML file --- zgw_consumers/contrib/__init__.py | 0 .../contrib/setup_configuration/__init__.py | 0 .../contrib/setup_configuration/models.py | 38 +++++++++++++++ .../contrib/setup_configuration/steps.py | 48 +++++++++++++++++++ 4 files changed, 86 insertions(+) create mode 100644 zgw_consumers/contrib/__init__.py create mode 100644 zgw_consumers/contrib/setup_configuration/__init__.py create mode 100644 zgw_consumers/contrib/setup_configuration/models.py create mode 100644 zgw_consumers/contrib/setup_configuration/steps.py diff --git a/zgw_consumers/contrib/__init__.py b/zgw_consumers/contrib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/zgw_consumers/contrib/setup_configuration/__init__.py b/zgw_consumers/contrib/setup_configuration/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/zgw_consumers/contrib/setup_configuration/models.py b/zgw_consumers/contrib/setup_configuration/models.py new file mode 100644 index 0000000..a364ab1 --- /dev/null +++ b/zgw_consumers/contrib/setup_configuration/models.py @@ -0,0 +1,38 @@ +from django_setup_configuration.models import ConfigurationModel, DjangoModelRef +from pydantic import Field + +from zgw_consumers.models import Service + + +class SingleServiceConfigurationModel(ConfigurationModel): + # TODO these should probably be defined in simple_certmanager and referred to? + # client_certificate: FilePath = DjangoModelRef(Service, "client_certificate") + # server_certificate: FilePath = DjangoModelRef(Service, "server_certificate") + connection_check_expected_status: int | None = Field( + description="The status code that indicates that the connection check is successful", + default=200, + ) + timeout: int | None = DjangoModelRef(Service, "timeout") + + class Meta: + django_model_refs = { + Service: [ + "slug", + "label", + "api_type", + "api_root", + "api_connection_check_path", + "auth_type", + "client_id", + "secret", + "header_key", + "header_value", + "nlx", + "user_id", + "user_representation", + ] + } + + +class ServicesConfigurationModel(ConfigurationModel): + services: list[SingleServiceConfigurationModel] = Field(default_factory=list) diff --git a/zgw_consumers/contrib/setup_configuration/steps.py b/zgw_consumers/contrib/setup_configuration/steps.py new file mode 100644 index 0000000..2e997fd --- /dev/null +++ b/zgw_consumers/contrib/setup_configuration/steps.py @@ -0,0 +1,48 @@ +from django_setup_configuration.configuration import BaseConfigurationStep +from django_setup_configuration.exceptions import SelfTestFailed + +from zgw_consumers.models import Service + +from .models import ServicesConfigurationModel + + +class ServiceConfigurationStep(BaseConfigurationStep[ServicesConfigurationModel]): + """ + Configure Services to connect with external APIs + """ + + verbose_name = "Configuration to connect with external services" + config_model = ServicesConfigurationModel + namespace = "ZGW_CONSUMERS" + enable_setting = "ZGW_CONSUMERS_CONFIG_ENABLE" + + def is_configured(self, model: ServicesConfigurationModel) -> bool: + slugs = [config.slug for config in model.services] + return Service.objects.filter(slug__in=slugs).count() == len(slugs) + + def execute(self, model: ServicesConfigurationModel): + ignore_fields = ["slug", "connection_check_expected_status"] + for config in model.services: + Service.objects.update_or_create( + slug=config.slug, + defaults={ + k: v + for k, v in config.model_dump().items() + if k not in ignore_fields + }, + ) + + def validate_result(self, model: ServicesConfigurationModel) -> None: + slugs = [config.slug for config in model.services] + failed_checks = [] + ordered_models = sorted(model.services, key=lambda x: x.slug) + for service, model in zip( + Service.objects.filter(slug__in=slugs).order_by("slug"), ordered_models + ): + if service.connection_check != model.connection_check_expected_status: + failed_checks.append(service.slug) + + if failed_checks: + raise SelfTestFailed( + f"non-success response from the following service(s): {failed_checks}" + ) From bf03b04f4ade125c45f8bc8440fea95e5766524f Mon Sep 17 00:00:00 2001 From: Steven Bal Date: Tue, 12 Nov 2024 15:16:45 +0100 Subject: [PATCH 3/5] :white_check_mark: [#100] Add tests for ServiceConfigurationStep --- testapp/settings.py | 1 + tests/files/services.yaml | 19 +++++ tests/test_configuration_steps.py | 124 ++++++++++++++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 tests/files/services.yaml create mode 100644 tests/test_configuration_steps.py diff --git a/testapp/settings.py b/testapp/settings.py index cf5cf2f..0731061 100644 --- a/testapp/settings.py +++ b/testapp/settings.py @@ -48,6 +48,7 @@ "simple_certmanager", "solo", "testapp", + "django_setup_configuration", ] MIDDLEWARE = [ diff --git a/tests/files/services.yaml b/tests/files/services.yaml new file mode 100644 index 0000000..da8ee55 --- /dev/null +++ b/tests/files/services.yaml @@ -0,0 +1,19 @@ +ZGW_CONSUMERS_CONFIG_ENABLE: True +ZGW_CONSUMERS: + services: + - slug: objecten-test + label: Objecten API test + api_root: http://objecten.local/api/v1/ + api_connection_check_path: objects + api_type: orc + auth_type: api_key + header_key: Authorization + header_value: Token foo + - slug: zaken-test + label: Zaken API test + api_root: http://zaken.local/api/v1/ + connection_check_expected_status: 400 + api_type: zrc + auth_type: zgw + client_id: client + secret: super-secret diff --git a/tests/test_configuration_steps.py b/tests/test_configuration_steps.py new file mode 100644 index 0000000..4115b46 --- /dev/null +++ b/tests/test_configuration_steps.py @@ -0,0 +1,124 @@ +import pytest +import requests_mock +from django_setup_configuration.exceptions import SelfTestFailed +from django_setup_configuration.test_utils import load_step_config_from_source + +from zgw_consumers.contrib.setup_configuration.steps import ServiceConfigurationStep +from zgw_consumers.models import Service +from zgw_consumers.test.factories import ServiceFactory + +CONFIG_FILE_PATH = "tests/files/services.yaml" + + +@pytest.fixture() +def step_config_model(): + return load_step_config_from_source(ServiceConfigurationStep, CONFIG_FILE_PATH) + + +@pytest.mark.django_db +def test_execute_configuration_step_success(step_config_model): + step = ServiceConfigurationStep() + + assert not step.is_configured(step_config_model) + + step.execute(step_config_model) + + assert Service.objects.count() == 2 + + objects_service, zaken_service = Service.objects.all() + + assert objects_service.slug == "objecten-test" + assert objects_service.label == "Objecten API test" + assert objects_service.api_root == "http://objecten.local/api/v1/" + assert objects_service.api_type == "orc" + assert objects_service.auth_type == "api_key" + assert objects_service.header_key == "Authorization" + assert objects_service.header_value == "Token foo" + assert objects_service.timeout == 10 + + assert zaken_service.slug == "zaken-test" + assert zaken_service.label == "Zaken API test" + assert zaken_service.api_root == "http://zaken.local/api/v1/" + assert zaken_service.api_type == "zrc" + assert zaken_service.auth_type == "zgw" + assert zaken_service.client_id == "client" + assert zaken_service.secret == "super-secret" + assert zaken_service.timeout == 10 + + +@pytest.mark.django_db +def test_execute_configuration_step_already_configured(step_config_model): + ServiceFactory.create( + slug="objecten-test", + label="Objecten", + api_root="http://some.other.existing.service.local/api/v1/", + ) + ServiceFactory.create( + slug="zaken-test", + label="Zaken", + api_root="http://some.existing.service.local/api/v1/", + ) + + step = ServiceConfigurationStep() + + assert step.is_configured(step_config_model) + + +@pytest.mark.django_db +def test_execute_configuration_step_update_existing(step_config_model): + ServiceFactory.create( + slug="zaken-test", + label="Objecttypen", + api_root="http://some.existing.service.local/api/v1/", + ) + + step = ServiceConfigurationStep() + + assert not step.is_configured(step_config_model) + + step.execute(step_config_model) + + assert Service.objects.count() == 2 + + objects_service, zaken_service = Service.objects.all() + + assert objects_service.slug == "objecten-test" + assert objects_service.label == "Objecten API test" + assert objects_service.api_root == "http://objecten.local/api/v1/" + + assert zaken_service.slug == "zaken-test" + assert zaken_service.label == "Zaken API test" + assert zaken_service.api_root == "http://zaken.local/api/v1/" + + +@pytest.mark.django_db +def test_execute_configuration_step_validate_result_success(step_config_model): + step = ServiceConfigurationStep() + + assert not step.is_configured(step_config_model) + + step.execute(step_config_model) + + with requests_mock.Mocker() as m: + m.get("http://objecten.local/api/v1/objects") + m.get("http://zaken.local/api/v1/", status_code=400) + step.validate_result(step_config_model) + + +@pytest.mark.django_db +def test_execute_configuration_step_validate_result_failure(step_config_model): + step = ServiceConfigurationStep() + + assert not step.is_configured(step_config_model) + + step.execute(step_config_model) + + with requests_mock.Mocker() as m: + m.get("http://objecten.local/api/v1/objects") + m.get("http://zaken.local/api/v1/", status_code=404) + with pytest.raises(SelfTestFailed) as excinfo: + step.validate_result(step_config_model) + assert ( + str(excinfo.value) + == "non-success response from the following service(s): ['zaken-test']" + ) From a707cd794cbdf5f572022a7e64a7e9e50a5e0cd4 Mon Sep 17 00:00:00 2001 From: Steven Bal Date: Mon, 18 Nov 2024 16:48:54 +0100 Subject: [PATCH 4/5] :recycle: [#100] Change several implementation details after discussion * use lowercase for root level keys in YAML files (e.g. `zgw_consumers_config_enable`) * use `identifier` instead of `slug` in config files * add `setup_config_` prefix to test files * remove `is_configured` and `validate_result` --- ...rvices.yaml => setup_config_services.yaml} | 9 ++- tests/test_configuration_steps.py | 55 +------------------ .../contrib/setup_configuration/models.py | 9 +-- .../contrib/setup_configuration/steps.py | 43 ++++++--------- 4 files changed, 24 insertions(+), 92 deletions(-) rename tests/files/{services.yaml => setup_config_services.yaml} (73%) diff --git a/tests/files/services.yaml b/tests/files/setup_config_services.yaml similarity index 73% rename from tests/files/services.yaml rename to tests/files/setup_config_services.yaml index da8ee55..4f7a6aa 100644 --- a/tests/files/services.yaml +++ b/tests/files/setup_config_services.yaml @@ -1,7 +1,7 @@ -ZGW_CONSUMERS_CONFIG_ENABLE: True -ZGW_CONSUMERS: +zgw_consumers_config_enable: True +zgw_consumers: services: - - slug: objecten-test + - identifier: objecten-test label: Objecten API test api_root: http://objecten.local/api/v1/ api_connection_check_path: objects @@ -9,10 +9,9 @@ ZGW_CONSUMERS: auth_type: api_key header_key: Authorization header_value: Token foo - - slug: zaken-test + - identifier: zaken-test label: Zaken API test api_root: http://zaken.local/api/v1/ - connection_check_expected_status: 400 api_type: zrc auth_type: zgw client_id: client diff --git a/tests/test_configuration_steps.py b/tests/test_configuration_steps.py index 4115b46..2f46345 100644 --- a/tests/test_configuration_steps.py +++ b/tests/test_configuration_steps.py @@ -1,13 +1,11 @@ import pytest -import requests_mock -from django_setup_configuration.exceptions import SelfTestFailed from django_setup_configuration.test_utils import load_step_config_from_source from zgw_consumers.contrib.setup_configuration.steps import ServiceConfigurationStep from zgw_consumers.models import Service from zgw_consumers.test.factories import ServiceFactory -CONFIG_FILE_PATH = "tests/files/services.yaml" +CONFIG_FILE_PATH = "tests/files/setup_config_services.yaml" @pytest.fixture() @@ -46,24 +44,6 @@ def test_execute_configuration_step_success(step_config_model): assert zaken_service.timeout == 10 -@pytest.mark.django_db -def test_execute_configuration_step_already_configured(step_config_model): - ServiceFactory.create( - slug="objecten-test", - label="Objecten", - api_root="http://some.other.existing.service.local/api/v1/", - ) - ServiceFactory.create( - slug="zaken-test", - label="Zaken", - api_root="http://some.existing.service.local/api/v1/", - ) - - step = ServiceConfigurationStep() - - assert step.is_configured(step_config_model) - - @pytest.mark.django_db def test_execute_configuration_step_update_existing(step_config_model): ServiceFactory.create( @@ -89,36 +69,3 @@ def test_execute_configuration_step_update_existing(step_config_model): assert zaken_service.slug == "zaken-test" assert zaken_service.label == "Zaken API test" assert zaken_service.api_root == "http://zaken.local/api/v1/" - - -@pytest.mark.django_db -def test_execute_configuration_step_validate_result_success(step_config_model): - step = ServiceConfigurationStep() - - assert not step.is_configured(step_config_model) - - step.execute(step_config_model) - - with requests_mock.Mocker() as m: - m.get("http://objecten.local/api/v1/objects") - m.get("http://zaken.local/api/v1/", status_code=400) - step.validate_result(step_config_model) - - -@pytest.mark.django_db -def test_execute_configuration_step_validate_result_failure(step_config_model): - step = ServiceConfigurationStep() - - assert not step.is_configured(step_config_model) - - step.execute(step_config_model) - - with requests_mock.Mocker() as m: - m.get("http://objecten.local/api/v1/objects") - m.get("http://zaken.local/api/v1/", status_code=404) - with pytest.raises(SelfTestFailed) as excinfo: - step.validate_result(step_config_model) - assert ( - str(excinfo.value) - == "non-success response from the following service(s): ['zaken-test']" - ) diff --git a/zgw_consumers/contrib/setup_configuration/models.py b/zgw_consumers/contrib/setup_configuration/models.py index a364ab1..18dcbbd 100644 --- a/zgw_consumers/contrib/setup_configuration/models.py +++ b/zgw_consumers/contrib/setup_configuration/models.py @@ -8,16 +8,12 @@ class SingleServiceConfigurationModel(ConfigurationModel): # TODO these should probably be defined in simple_certmanager and referred to? # client_certificate: FilePath = DjangoModelRef(Service, "client_certificate") # server_certificate: FilePath = DjangoModelRef(Service, "server_certificate") - connection_check_expected_status: int | None = Field( - description="The status code that indicates that the connection check is successful", - default=200, - ) - timeout: int | None = DjangoModelRef(Service, "timeout") + # Identifier is mapped to slug, because slug isn't a very descriptive name for devops + identifier: str = DjangoModelRef(Service, "slug") class Meta: django_model_refs = { Service: [ - "slug", "label", "api_type", "api_root", @@ -30,6 +26,7 @@ class Meta: "nlx", "user_id", "user_representation", + "timeout", ] } diff --git a/zgw_consumers/contrib/setup_configuration/steps.py b/zgw_consumers/contrib/setup_configuration/steps.py index 2e997fd..3411323 100644 --- a/zgw_consumers/contrib/setup_configuration/steps.py +++ b/zgw_consumers/contrib/setup_configuration/steps.py @@ -1,5 +1,4 @@ from django_setup_configuration.configuration import BaseConfigurationStep -from django_setup_configuration.exceptions import SelfTestFailed from zgw_consumers.models import Service @@ -13,36 +12,26 @@ class ServiceConfigurationStep(BaseConfigurationStep[ServicesConfigurationModel] verbose_name = "Configuration to connect with external services" config_model = ServicesConfigurationModel - namespace = "ZGW_CONSUMERS" - enable_setting = "ZGW_CONSUMERS_CONFIG_ENABLE" - - def is_configured(self, model: ServicesConfigurationModel) -> bool: - slugs = [config.slug for config in model.services] - return Service.objects.filter(slug__in=slugs).count() == len(slugs) + namespace = "zgw_consumers" + enable_setting = "zgw_consumers_config_enable" def execute(self, model: ServicesConfigurationModel): - ignore_fields = ["slug", "connection_check_expected_status"] for config in model.services: Service.objects.update_or_create( - slug=config.slug, + slug=config.identifier, defaults={ - k: v - for k, v in config.model_dump().items() - if k not in ignore_fields + "label": config.label, + "api_type": config.api_type, + "api_root": config.api_root, + "api_connection_check_path": config.api_connection_check_path, + "auth_type": config.auth_type, + "client_id": config.client_id, + "secret": config.secret, + "header_key": config.header_key, + "header_value": config.header_value, + "nlx": config.nlx, + "user_id": config.user_id, + "user_representation": config.user_representation, + "timeout": config.timeout, }, ) - - def validate_result(self, model: ServicesConfigurationModel) -> None: - slugs = [config.slug for config in model.services] - failed_checks = [] - ordered_models = sorted(model.services, key=lambda x: x.slug) - for service, model in zip( - Service.objects.filter(slug__in=slugs).order_by("slug"), ordered_models - ): - if service.connection_check != model.connection_check_expected_status: - failed_checks.append(service.slug) - - if failed_checks: - raise SelfTestFailed( - f"non-success response from the following service(s): {failed_checks}" - ) From 2e4516aee5d856b07561d2a66b9e068068bcbb86 Mon Sep 17 00:00:00 2001 From: Steven Bal Date: Tue, 19 Nov 2024 09:40:34 +0100 Subject: [PATCH 5/5] :white_check_mark: [#100] Tests with required service fields and all service fields and add a test for idempotency --- pyproject.toml | 3 + .../setup_config_services_all_fields.yaml | 20 +++ ...setup_config_services_required_fields.yaml | 8 ++ tests/test_configuration_steps.py | 125 +++++++++++++++--- 4 files changed, 134 insertions(+), 22 deletions(-) create mode 100644 tests/files/setup_config_services_all_fields.yaml create mode 100644 tests/files/setup_config_services_required_fields.yaml diff --git a/pyproject.toml b/pyproject.toml index 9c83875..f968784 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -102,6 +102,9 @@ skip = ["env", ".tox", ".history"] [tool.pytest.ini_options] testpaths = ["tests"] DJANGO_SETTINGS_MODULE = "testapp.settings" +markers = [ + "config_path: the path to the YAML file that is loaded for setup_configuration", +] [tool.bumpversion] current_version = "0.35.1" diff --git a/tests/files/setup_config_services_all_fields.yaml b/tests/files/setup_config_services_all_fields.yaml new file mode 100644 index 0000000..1713be0 --- /dev/null +++ b/tests/files/setup_config_services_all_fields.yaml @@ -0,0 +1,20 @@ +zgw_consumers_config_enable: True +zgw_consumers: + services: + - identifier: objecten-test + label: Objecten API test + api_root: http://objecten.local/api/v1/ + api_connection_check_path: objects + api_type: orc + auth_type: api_key + header_key: Authorization + header_value: Token foo + client_id: client + secret: super-secret + nlx: http://some-outway-adress.local:8080/ + user_id: open-formulieren + user_representation: Open Formulieren + timeout: 5 + # NOT SUPPORTED YET + # client_certificatie: ... + # server_certificatie: ... diff --git a/tests/files/setup_config_services_required_fields.yaml b/tests/files/setup_config_services_required_fields.yaml new file mode 100644 index 0000000..9dcf1db --- /dev/null +++ b/tests/files/setup_config_services_required_fields.yaml @@ -0,0 +1,8 @@ +zgw_consumers_config_enable: True +zgw_consumers: + services: + - identifier: objecten-test + label: Objecten API test + api_root: http://objecten.local/api/v1/ + api_type: orc + auth_type: zgw \ No newline at end of file diff --git a/tests/test_configuration_steps.py b/tests/test_configuration_steps.py index 2f46345..f339a39 100644 --- a/tests/test_configuration_steps.py +++ b/tests/test_configuration_steps.py @@ -1,25 +1,21 @@ import pytest -from django_setup_configuration.test_utils import load_step_config_from_source +from django_setup_configuration.test_utils import execute_single_step +from zgw_consumers.constants import APITypes, AuthTypes from zgw_consumers.contrib.setup_configuration.steps import ServiceConfigurationStep from zgw_consumers.models import Service from zgw_consumers.test.factories import ServiceFactory CONFIG_FILE_PATH = "tests/files/setup_config_services.yaml" - - -@pytest.fixture() -def step_config_model(): - return load_step_config_from_source(ServiceConfigurationStep, CONFIG_FILE_PATH) +CONFIG_FILE_PATH_REQUIRED_FIELDS = ( + "tests/files/setup_config_services_required_fields.yaml" +) +CONFIG_FILE_PATH_ALL_FIELDS = "tests/files/setup_config_services_all_fields.yaml" @pytest.mark.django_db -def test_execute_configuration_step_success(step_config_model): - step = ServiceConfigurationStep() - - assert not step.is_configured(step_config_model) - - step.execute(step_config_model) +def test_execute_configuration_step_success(): + execute_single_step(ServiceConfigurationStep, yaml_source=CONFIG_FILE_PATH) assert Service.objects.count() == 2 @@ -28,8 +24,8 @@ def test_execute_configuration_step_success(step_config_model): assert objects_service.slug == "objecten-test" assert objects_service.label == "Objecten API test" assert objects_service.api_root == "http://objecten.local/api/v1/" - assert objects_service.api_type == "orc" - assert objects_service.auth_type == "api_key" + assert objects_service.api_type == APITypes.orc + assert objects_service.auth_type == AuthTypes.api_key assert objects_service.header_key == "Authorization" assert objects_service.header_value == "Token foo" assert objects_service.timeout == 10 @@ -37,26 +33,22 @@ def test_execute_configuration_step_success(step_config_model): assert zaken_service.slug == "zaken-test" assert zaken_service.label == "Zaken API test" assert zaken_service.api_root == "http://zaken.local/api/v1/" - assert zaken_service.api_type == "zrc" - assert zaken_service.auth_type == "zgw" + assert zaken_service.api_type == APITypes.zrc + assert zaken_service.auth_type == AuthTypes.zgw assert zaken_service.client_id == "client" assert zaken_service.secret == "super-secret" assert zaken_service.timeout == 10 @pytest.mark.django_db -def test_execute_configuration_step_update_existing(step_config_model): +def test_execute_configuration_step_update_existing(): ServiceFactory.create( slug="zaken-test", label="Objecttypen", api_root="http://some.existing.service.local/api/v1/", ) - step = ServiceConfigurationStep() - - assert not step.is_configured(step_config_model) - - step.execute(step_config_model) + execute_single_step(ServiceConfigurationStep, yaml_source=CONFIG_FILE_PATH) assert Service.objects.count() == 2 @@ -69,3 +61,92 @@ def test_execute_configuration_step_update_existing(step_config_model): assert zaken_service.slug == "zaken-test" assert zaken_service.label == "Zaken API test" assert zaken_service.api_root == "http://zaken.local/api/v1/" + + +@pytest.mark.django_db +def test_execute_configuration_step_with_required_fields(): + execute_single_step( + ServiceConfigurationStep, yaml_source=CONFIG_FILE_PATH_REQUIRED_FIELDS + ) + + assert Service.objects.count() == 1 + + objects_service = Service.objects.get() + + assert objects_service.slug == "objecten-test" + assert objects_service.label == "Objecten API test" + assert objects_service.api_root == "http://objecten.local/api/v1/" + assert objects_service.api_type == APITypes.orc + assert objects_service.auth_type == AuthTypes.zgw + assert objects_service.timeout == 10 + + # Not required fields + assert objects_service.api_connection_check_path == "" + assert objects_service.header_key == "" + assert objects_service.header_value == "" + assert objects_service.client_id == "" + assert objects_service.secret == "" + assert objects_service.nlx == "" + assert objects_service.user_id == "" + assert objects_service.user_representation == "" + + +@pytest.mark.django_db +def test_execute_configuration_step_with_all_fields(): + execute_single_step( + ServiceConfigurationStep, yaml_source=CONFIG_FILE_PATH_ALL_FIELDS + ) + + assert Service.objects.count() == 1 + + objects_service = Service.objects.get() + + assert objects_service.slug == "objecten-test" + assert objects_service.label == "Objecten API test" + assert objects_service.api_root == "http://objecten.local/api/v1/" + assert objects_service.api_type == APITypes.orc + assert objects_service.auth_type == AuthTypes.api_key + assert objects_service.api_connection_check_path == "objects" + assert objects_service.header_key == "Authorization" + assert objects_service.header_value == "Token foo" + assert objects_service.client_id == "client" + assert objects_service.secret == "super-secret" + assert objects_service.nlx == "http://some-outway-adress.local:8080/" + assert objects_service.user_id == "open-formulieren" + assert objects_service.user_representation == "Open Formulieren" + assert objects_service.timeout == 5 + + +@pytest.mark.django_db +def test_execute_configuration_step_idempotent(): + def make_assertions(): + assert Service.objects.count() == 1 + + objects_service = Service.objects.get() + + assert objects_service.slug == "objecten-test" + assert objects_service.label == "Objecten API test" + assert objects_service.api_root == "http://objecten.local/api/v1/" + assert objects_service.api_type == APITypes.orc + assert objects_service.auth_type == AuthTypes.api_key + assert objects_service.api_connection_check_path == "objects" + assert objects_service.header_key == "Authorization" + assert objects_service.header_value == "Token foo" + assert objects_service.client_id == "client" + assert objects_service.secret == "super-secret" + assert objects_service.nlx == "http://some-outway-adress.local:8080/" + assert objects_service.user_id == "open-formulieren" + assert objects_service.user_representation == "Open Formulieren" + assert objects_service.timeout == 5 + + execute_single_step( + ServiceConfigurationStep, yaml_source=CONFIG_FILE_PATH_ALL_FIELDS + ) + + make_assertions() + + execute_single_step( + ServiceConfigurationStep, yaml_source=CONFIG_FILE_PATH_ALL_FIELDS + ) + + make_assertions()