From a7c4e628029d9d5762de9e529163887c3cc2af74 Mon Sep 17 00:00:00 2001 From: Sergei Maertens Date: Tue, 2 Jul 2024 17:48:54 +0200 Subject: [PATCH] :card_file_box: [#4267] Make migration more robust --- .../0019_add_default_objects_api_group.py | 33 +++++++++++++----- .../objects_api/tests/test_migrations.py | 34 +++++++++++++++++++ 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/src/openforms/registrations/contrib/objects_api/migrations/0019_add_default_objects_api_group.py b/src/openforms/registrations/contrib/objects_api/migrations/0019_add_default_objects_api_group.py index 86b1e41954..f71dc19784 100644 --- a/src/openforms/registrations/contrib/objects_api/migrations/0019_add_default_objects_api_group.py +++ b/src/openforms/registrations/contrib/objects_api/migrations/0019_add_default_objects_api_group.py @@ -1,9 +1,8 @@ # Generated by Django 4.2.11 on 2024-07-02 15:18 from django.db import migrations - -from django.db.migrations.state import StateApps from django.db.backends.base.schema import BaseDatabaseSchemaEditor +from django.db.migrations.state import StateApps def add_default_objects_api_group( @@ -13,17 +12,33 @@ def add_default_objects_api_group( ObjectsAPIGroupConfig = apps.get_model( "registrations_objects_api", "ObjectsAPIGroupConfig" ) + backends_qs = FormRegistrationBackend.objects.filter(backend="objects_api") + # nothing to do if there are no relevant backends + if not backends_qs.exists(): + return objects_api_group_config = ObjectsAPIGroupConfig.objects.order_by("pk").first() if objects_api_group_config is None: - # Because this migration runs after registrations_objects_api/0017_move_singleton_data, - # Having no Objects API Group means we had no solo config in the first place, thus - # it is safe to assume no Objects API registration backend was set up. - return + # This shouldn't happen because of: + # * upgrade checks + # * operations in registrations_objects_api/0017_move_singleton_data + # + # BUT that doesn't mean it's impossible, like on continuously deployed + # environments... For those cases, we generate a (knowingly broken) + # configuration so that migrations don't crash and options have at least the + # right shape so that we can trust the type annotations. + objects_api_group_config = ObjectsAPIGroupConfig.objects.create( + name="AUTO_GENERATED - FIXME", + # DeprecationWarning + # Open Forms 3.0 will drop the nullable fields, so this data migration needs + # to be gone by then. + objects_service=None, + objecttypes_service=None, + drc_service=None, + catalogi_service=None, + ) - for registration_backend in FormRegistrationBackend.objects.filter( - backend="objects_api" - ): + for registration_backend in backends_qs: registration_backend.options.setdefault( "objects_api_group", objects_api_group_config.pk ) diff --git a/src/openforms/registrations/contrib/objects_api/tests/test_migrations.py b/src/openforms/registrations/contrib/objects_api/tests/test_migrations.py index a87604ea24..be958f5cfd 100644 --- a/src/openforms/registrations/contrib/objects_api/tests/test_migrations.py +++ b/src/openforms/registrations/contrib/objects_api/tests/test_migrations.py @@ -313,6 +313,40 @@ def test_sets_default_objects_api_group(self) -> None: ) +class AddDefaultObjectsAPIGroupWithBrokenStateMigrationTests(TestMigrations): + app = "registrations_objects_api" + migrate_from = "0018_remove_objectsapiconfig_catalogi_service_and_more" + migrate_to = "0019_add_default_objects_api_group" + + def setUpBeforeMigration(self, apps: StateApps) -> None: + Form = apps.get_model("forms", "Form") + FormRegistrationBackend = apps.get_model("forms", "FormRegistrationBackend") + ObjectsAPIGroupConfig = apps.get_model( + "registrations_objects_api", "ObjectsAPIGroupConfig" + ) + + form = Form.objects.create(name="test form") + FormRegistrationBackend.objects.create( + form=form, + name="Objects API backend", + key="backend", + backend="objects_api", + ) + assert not ObjectsAPIGroupConfig.objects.exists() + + def test_sets_default_objects_api_group(self) -> None: + FormRegistrationBackend = self.apps.get_model( + "forms", "FormRegistrationBackend" + ) + ObjectsAPIGroupConfig = self.apps.get_model( + "registrations_objects_api", "ObjectsAPIGroupConfig" + ) + auto_created_config = ObjectsAPIGroupConfig.objects.get() + + backend = FormRegistrationBackend.objects.get() + self.assertEqual(backend.options["objects_api_group"], auto_created_config.pk) + + class ObjecttypeUrltoUuidMigrationTests(TestMigrations): app = "registrations_objects_api" migrate_from = "0019_add_default_objects_api_group"