diff --git a/tests/composition/cmk/piggyback/piggyback_test_helper.py b/tests/composition/cmk/piggyback/piggyback_test_helper.py index 6f26abda314..b1a1c51b977 100644 --- a/tests/composition/cmk/piggyback/piggyback_test_helper.py +++ b/tests/composition/cmk/piggyback/piggyback_test_helper.py @@ -129,12 +129,12 @@ def disable_piggyback_hub_globally(central_site: Site, remote_site_id: str) -> I ): _write_replication_changes(central_site, central_site.id) _write_replication_changes(central_site, remote_site_id) - central_site.openapi.activate_changes_and_wait_for_completion() + central_site.openapi.changes.activate_and_wait_for_completion() yield finally: _write_replication_changes(central_site, central_site.id) _write_replication_changes(central_site, remote_site_id) - central_site.openapi.activate_changes_and_wait_for_completion() + central_site.openapi.changes.activate_and_wait_for_completion() @contextmanager @@ -143,11 +143,11 @@ def disable_piggyback_hub_remote_site(central_site: Site, remote_site_id: str) - # fake changes to trigger replication with _write_sitespecific_config_file(central_site): _write_replication_changes(central_site, remote_site_id) - central_site.openapi.activate_changes_and_wait_for_completion() + central_site.openapi.changes.activate_and_wait_for_completion() yield finally: _write_replication_changes(central_site, remote_site_id) - central_site.openapi.activate_changes_and_wait_for_completion() + central_site.openapi.changes.activate_and_wait_for_completion() @contextmanager diff --git a/tests/composition/cmk/piggyback/test_piggyback.py b/tests/composition/cmk/piggyback/test_piggyback.py index 3bd3b3a2afd..e6730395ac3 100644 --- a/tests/composition/cmk/piggyback/test_piggyback.py +++ b/tests/composition/cmk/piggyback/test_piggyback.py @@ -59,11 +59,11 @@ def _setup_piggyback_host( "tag_piggyback": "piggyback", }, ) - source_site.openapi.activate_changes_and_wait_for_completion() + source_site.openapi.changes.activate_and_wait_for_completion() yield finally: source_site.openapi.hosts.delete(hostname_piggyback) - source_site.openapi.activate_changes_and_wait_for_completion() + source_site.openapi.changes.activate_and_wait_for_completion() @pytest.fixture(name="prepare_piggyback_environment", scope="module") @@ -83,10 +83,10 @@ def _prepare_piggyback_environment(central_site: Site, remote_site: Site) -> Ite [_HOSTNAME_PIGGYBACKED_B], ), ): - central_site.openapi.activate_changes_and_wait_for_completion() + central_site.openapi.changes.activate_and_wait_for_completion() yield finally: - central_site.openapi.activate_changes_and_wait_for_completion() + central_site.openapi.changes.activate_and_wait_for_completion() def _schedule_check_and_discover(site: Site, hostname_source: str, hostname_piggyback: str) -> None: @@ -146,16 +146,16 @@ def _create_and_rename_host( }, ) - source_site.openapi.activate_changes_and_wait_for_completion() + source_site.openapi.changes.activate_and_wait_for_completion() source_site.openapi.hosts.rename_and_wait_for_completion( hostname_old="other_host", hostname_new=hostname_piggyback, etag="*" ) - source_site.openapi.activate_changes_and_wait_for_completion() + source_site.openapi.changes.activate_and_wait_for_completion() yield finally: source_site.openapi.hosts.delete(hostname_piggyback) - source_site.openapi.activate_changes_and_wait_for_completion() + source_site.openapi.changes.activate_and_wait_for_completion() def test_piggyback_rename_host( @@ -210,7 +210,7 @@ def test_piggyback_hub_disabled_globally( _schedule_check_and_discover( central_site, _HOSTNAME_SOURCE_CENTRAL, _HOSTNAME_PIGGYBACKED_A ) - central_site.openapi.activate_changes_and_wait_for_completion() + central_site.openapi.changes.activate_and_wait_for_completion() assert _piggybacked_service_gets_updated( central_site, remote_site, _HOSTNAME_SOURCE_CENTRAL, _HOSTNAME_PIGGYBACKED_A @@ -245,7 +245,7 @@ def test_piggyback_hub_disabled_remote_site( _schedule_check_and_discover( central_site, _HOSTNAME_SOURCE_CENTRAL, _HOSTNAME_PIGGYBACKED_A ) - central_site.openapi.activate_changes_and_wait_for_completion() + central_site.openapi.changes.activate_and_wait_for_completion() assert _piggybacked_service_gets_updated( central_site, remote_site, _HOSTNAME_SOURCE_CENTRAL, _HOSTNAME_PIGGYBACKED_A @@ -266,7 +266,7 @@ def _move_host(central_site: Site, to_remote_site: str, hostname_piggyback: str) hostname_piggyback, update_attributes={"site": to_remote_site}, ) - central_site.openapi.activate_changes_and_wait_for_completion() + central_site.openapi.changes.activate_and_wait_for_completion() def test_piggyback_services_move_host( diff --git a/tests/composition/conftest.py b/tests/composition/conftest.py index d8d556a29dc..8d2f2001b9f 100644 --- a/tests/composition/conftest.py +++ b/tests/composition/conftest.py @@ -164,7 +164,7 @@ def _connection( } ) central_site.openapi.sites.login(remote_site.id) - central_site.openapi.activate_changes_and_wait_for_completion( + central_site.openapi.changes.activate_and_wait_for_completion( # this seems to be necessary to avoid sporadic CI failures force_foreign_changes=True, ) @@ -173,7 +173,7 @@ def _connection( finally: logger.warning("Hosts left: %s", central_site.openapi.hosts.get_all_names()) central_site.openapi.sites.delete(remote_site.id) - central_site.openapi.activate_changes_and_wait_for_completion( + central_site.openapi.changes.activate_and_wait_for_completion( # this seems to be necessary to avoid sporadic CI failures force_foreign_changes=True, ) diff --git a/tests/composition/controller_site_interactions/test_proxy_register_import_workflow.py b/tests/composition/controller_site_interactions/test_proxy_register_import_workflow.py index 3496dff76ad..8cb62282f3d 100644 --- a/tests/composition/controller_site_interactions/test_proxy_register_import_workflow.py +++ b/tests/composition/controller_site_interactions/test_proxy_register_import_workflow.py @@ -24,7 +24,7 @@ def test_proxy_register_import_workflow( ) -> None: hostname = HostName("proxy-host") central_site.openapi.hosts.create(hostname=hostname, attributes={"ipaddress": "127.0.0.1"}) - central_site.openapi.activate_changes_and_wait_for_completion() + central_site.openapi.changes.activate_and_wait_for_completion() try: proxy_registration_proc = run( @@ -56,7 +56,7 @@ def test_proxy_register_import_workflow( wait_until_host_receives_data(central_site, hostname) central_site.openapi.service_discovery.run_discovery_and_wait_for_completion(hostname) - central_site.openapi.activate_changes_and_wait_for_completion() + central_site.openapi.changes.activate_and_wait_for_completion() wait_until_host_has_services( central_site, @@ -66,4 +66,4 @@ def test_proxy_register_import_workflow( ) finally: central_site.openapi.hosts.delete(hostname=hostname) - central_site.openapi.activate_changes_and_wait_for_completion(force_foreign_changes=True) + central_site.openapi.changes.activate_and_wait_for_completion(force_foreign_changes=True) diff --git a/tests/composition/controller_site_interactions/test_register_workflow.py b/tests/composition/controller_site_interactions/test_register_workflow.py index 83a987462d7..fe03c05b9e9 100644 --- a/tests/composition/controller_site_interactions/test_register_workflow.py +++ b/tests/composition/controller_site_interactions/test_register_workflow.py @@ -30,7 +30,7 @@ def _test_register_workflow( ) -> None: try: site.openapi.hosts.create(hostname=hostname, attributes=dict(host_attributes)) - site.openapi.activate_changes_and_wait_for_completion() + site.openapi.changes.activate_and_wait_for_completion() register_controller(ctl_path, site, hostname) @@ -38,7 +38,7 @@ def _test_register_workflow( wait_until_host_receives_data(site, hostname) site.openapi.service_discovery.run_discovery_and_wait_for_completion(hostname) - site.openapi.activate_changes_and_wait_for_completion() + site.openapi.changes.activate_and_wait_for_completion() wait_until_host_has_services( site, @@ -48,7 +48,7 @@ def _test_register_workflow( ) finally: site.openapi.hosts.delete(hostname=hostname) - site.openapi.activate_changes_and_wait_for_completion(force_foreign_changes=True) + site.openapi.changes.activate_and_wait_for_completion(force_foreign_changes=True) @skip_if_not_containerized diff --git a/tests/composition/controller_site_interactions/test_rename_preserves_registration.py b/tests/composition/controller_site_interactions/test_rename_preserves_registration.py index 94a40b5c475..8caf7cd37ed 100644 --- a/tests/composition/controller_site_interactions/test_rename_preserves_registration.py +++ b/tests/composition/controller_site_interactions/test_rename_preserves_registration.py @@ -32,7 +32,7 @@ def _test_rename_preserves_registration( "site": registration_site.id, }, ) - central_site.openapi.activate_changes_and_wait_for_completion() + central_site.openapi.changes.activate_and_wait_for_completion() register_controller( ctl_path, registration_site, @@ -53,7 +53,7 @@ def _test_rename_preserves_registration( hostnames = set(central_site.openapi.hosts.get_all_names()) for hostname_ in hostnames.intersection({hostname, new_hostname}): central_site.openapi.hosts.delete(hostname_) - central_site.openapi.activate_changes_and_wait_for_completion(force_foreign_changes=True) + central_site.openapi.changes.activate_and_wait_for_completion(force_foreign_changes=True) @skip_if_not_containerized diff --git a/tests/composition/controller_site_interactions/test_status.py b/tests/composition/controller_site_interactions/test_status.py index 501e4e290e9..2b878493b93 100644 --- a/tests/composition/controller_site_interactions/test_status.py +++ b/tests/composition/controller_site_interactions/test_status.py @@ -33,13 +33,13 @@ def _get_status_output_json( ) -> Iterator[Mapping[str, Any]]: try: site.openapi.hosts.create(hostname=hostname, attributes=dict(host_attributes)) - site.openapi.activate_changes_and_wait_for_completion() + site.openapi.changes.activate_and_wait_for_completion() register_controller(ctl_path, site, hostname) yield controller_status_json(ctl_path) finally: site.openapi.hosts.delete(hostname=hostname) - site.openapi.activate_changes_and_wait_for_completion(force_foreign_changes=True) + site.openapi.changes.activate_and_wait_for_completion(force_foreign_changes=True) @skip_if_not_containerized diff --git a/tests/composition/message_broker/utils.py b/tests/composition/message_broker/utils.py index 2b2bef17ef2..a2df3512410 100644 --- a/tests/composition/message_broker/utils.py +++ b/tests/composition/message_broker/utils.py @@ -165,8 +165,8 @@ def p2p_connection(central_site: Site, remote_site: Site, remote_site_2: Site) - central_site.openapi.broker_connections.create( connection_id, connecter=remote_site.id, connectee=remote_site_2.id ) - central_site.openapi.activate_changes_and_wait_for_completion() + central_site.openapi.changes.activate_and_wait_for_completion() yield finally: central_site.openapi.broker_connections.delete(connection_id) - central_site.openapi.activate_changes_and_wait_for_completion() + central_site.openapi.changes.activate_and_wait_for_completion() diff --git a/tests/composition/test_automatic_host_removal.py b/tests/composition/test_automatic_host_removal.py index 9e7fe34bf7d..484d5301e70 100644 --- a/tests/composition/test_automatic_host_removal.py +++ b/tests/composition/test_automatic_host_removal.py @@ -24,7 +24,7 @@ def test_automatic_host_removal( central_site: Site, remote_site: Site, ) -> None: - assert not central_site.openapi.pending_changes() + assert not central_site.openapi.changes.get_pending() unresolvable_host_central = "not-dns-resolvable-central" unresolvable_host_remote = "not-dns-resolvable-remote" @@ -49,7 +49,7 @@ def test_automatic_host_removal( }, ) - central_site.openapi.activate_changes_and_wait_for_completion(force_foreign_changes=True) + central_site.openapi.changes.activate_and_wait_for_completion(force_foreign_changes=True) try: @@ -66,7 +66,7 @@ def _host_removal_done() -> bool: logger.info("Waiting for changes to be activated") wait_until( - lambda: not central_site.openapi.pending_changes(), + lambda: not central_site.openapi.changes.get_pending(), timeout=180, interval=20, ) @@ -81,4 +81,4 @@ def _host_removal_done() -> bool: central_site.openapi.hosts.delete(unresolvable_host_central) if unresolvable_host_remote in central_site.openapi.hosts.get_all_names(): central_site.openapi.hosts.delete(unresolvable_host_remote) - central_site.openapi.activate_changes_and_wait_for_completion(force_foreign_changes=True) + central_site.openapi.changes.activate_and_wait_for_completion(force_foreign_changes=True) diff --git a/tests/gui_e2e/conftest.py b/tests/gui_e2e/conftest.py index ce17b9bd023..18f62cf98fa 100644 --- a/tests/gui_e2e/conftest.py +++ b/tests/gui_e2e/conftest.py @@ -245,7 +245,7 @@ def _create_hosts_using_data_from_agent_dump(test_site: Site) -> Iterator: test_site.openapi.service_discovery.run_bulk_discovery_and_wait_for_completion( created_hosts_list ) - test_site.openapi.activate_changes_and_wait_for_completion() + test_site.openapi.changes.activate_and_wait_for_completion() logger.info("Schedule the 'Check_MK' service") for host_name in created_hosts_list: @@ -258,7 +258,7 @@ def _create_hosts_using_data_from_agent_dump(test_site: Site) -> Iterator: logger.info("Clean up: delete the host(s) and the rule") test_site.openapi.hosts.bulk_delete(created_hosts_list) test_site.openapi.rules.delete(rule_id) - test_site.openapi.activate_changes_and_wait_for_completion() + test_site.openapi.changes.activate_and_wait_for_completion() test_site.delete_dir(test_site_dump_path) diff --git a/tests/integration/checks/test_checks_sanity.py b/tests/integration/checks/test_checks_sanity.py index 3549abead82..a73b9bb599e 100644 --- a/tests/integration/checks/test_checks_sanity.py +++ b/tests/integration/checks/test_checks_sanity.py @@ -62,7 +62,7 @@ def _host_services( wait_until_host_receives_data(site, hostname) wait_for_agent_cache_omd_status(site) site.openapi.service_discovery.run_bulk_discovery_and_wait_for_completion([str(hostname)]) - site.openapi.activate_changes_and_wait_for_completion() + site.openapi.changes.activate_and_wait_for_completion() if active_mode: site.reschedule_services(hostname) else: diff --git a/tests/integration/cmk/ec/test_ec.py b/tests/integration/cmk/ec/test_ec.py index 49b6f17d97b..b203bc1e31d 100644 --- a/tests/integration/cmk/ec/test_ec.py +++ b/tests/integration/cmk/ec/test_ec.py @@ -111,7 +111,7 @@ def _write_ec_rule(site: Site, rule: list | None) -> None: def _activate_ec_changes(site: Site) -> None: replication_changes_path = site.path(f"var/check_mk/wato/replication_changes_{site.id}.mk") site.write_text_file(str(replication_changes_path), str(_get_replication_change())) - site.openapi.activate_changes_and_wait_for_completion(force_foreign_changes=True) + site.openapi.changes.activate_and_wait_for_completion(force_foreign_changes=True) def _generate_message_via_events_pipe(site: Site, message: str, end_of_line: bool = True) -> None: diff --git a/tests/integration/core/test_core_switch.py b/tests/integration/core/test_core_switch.py index 317f82ee23c..a6e11a7be02 100644 --- a/tests/integration/core/test_core_switch.py +++ b/tests/integration/core/test_core_switch.py @@ -51,11 +51,11 @@ def test_core_switch(site: Site, switch_core: Iterator[None]) -> None: site.openapi.hosts.create( "test_host_core_switch", attributes={"ipaddress": site.http_address, "site": site.id} ) - site.openapi.activate_changes_and_wait_for_completion() + site.openapi.changes.activate_and_wait_for_completion() except Exception as e: logger.error(e) raise finally: site.openapi.hosts.delete("test_host_core_switch") - site.openapi.activate_changes_and_wait_for_completion() + site.openapi.changes.activate_and_wait_for_completion() diff --git a/tests/plugins_integration/checks.py b/tests/plugins_integration/checks.py index a1ea75bdd23..3c3b0c6293e 100644 --- a/tests/plugins_integration/checks.py +++ b/tests/plugins_integration/checks.py @@ -635,9 +635,7 @@ def wait_for_dcd_pend_changes(site: Site) -> None: """Wait up to 60 seconds for DCD to activate changes.""" max_count = 60 count = 0 - while ( - n_pending_changes := len(site.openapi.pending_changes([site.id])) - ) > 0 and count < max_count: + while (n_pending_changes := len(site.openapi.changes.get_pending())) > 0 and count < max_count: logger.info( "Waiting for changes to be activated by the DCD connector. Count: %s/%s", count, @@ -668,12 +666,12 @@ def _dcd_connector(test_site_piggyback: Site) -> Iterator[None]: delete_hosts=True, no_deletion_time_after_init=60, ) - test_site_piggyback.openapi.activate_changes_and_wait_for_completion(force_foreign_changes=True) + test_site_piggyback.openapi.changes.activate_and_wait_for_completion(force_foreign_changes=True) try: yield finally: if not config.skip_cleanup: test_site_piggyback.openapi.dcd.delete(dcd_id) - test_site_piggyback.openapi.activate_changes_and_wait_for_completion( + test_site_piggyback.openapi.changes.activate_and_wait_for_completion( force_foreign_changes=True ) diff --git a/tests/plugins_integration/conftest.py b/tests/plugins_integration/conftest.py index d757aedfa1d..bbc3f57d986 100644 --- a/tests/plugins_integration/conftest.py +++ b/tests/plugins_integration/conftest.py @@ -286,11 +286,11 @@ def _create_periodic_service_discovery_rule(test_site_update: Site) -> Iterator[ ruleset_name="periodic_discovery", value=_periodic_service_discovery_rule(), ) - test_site_update.openapi.activate_changes_and_wait_for_completion() + test_site_update.openapi.changes.activate_and_wait_for_completion() yield for rule in test_site_update.openapi.rules.get_all("periodic_discovery"): if rule["id"] not in existing_rules_ids: test_site_update.openapi.rules.delete(rule["id"]) - test_site_update.openapi.activate_changes_and_wait_for_completion() + test_site_update.openapi.changes.activate_and_wait_for_completion() diff --git a/tests/testlib/agent.py b/tests/testlib/agent.py index 441c5ec95ff..79b8981db08 100644 --- a/tests/testlib/agent.py +++ b/tests/testlib/agent.py @@ -381,4 +381,4 @@ def clean_up_host(site: Site, hostname: HostName) -> Iterator[None]: deleted = True if deleted: - site.openapi.activate_changes_and_wait_for_completion(force_foreign_changes=True) + site.openapi.changes.activate_and_wait_for_completion(force_foreign_changes=True) diff --git a/tests/testlib/emails.py b/tests/testlib/emails.py index c18279002e1..31e551d2fbc 100644 --- a/tests/testlib/emails.py +++ b/tests/testlib/emails.py @@ -170,7 +170,7 @@ def create_notification_user(site: Site, admin: bool = False) -> Iterator[tuple[ customer="global" if site.version.is_managed_edition() else None, roles=["admin"] if admin else [], ) - site.openapi.activate_changes_and_wait_for_completion() + site.openapi.changes.activate_and_wait_for_completion() yield user_name, email_address site.openapi.users.delete(user_name) - site.openapi.activate_changes_and_wait_for_completion() + site.openapi.changes.activate_and_wait_for_completion() diff --git a/tests/testlib/openapi_session.py b/tests/testlib/openapi_session.py index 68646c057a7..fade2eeb545 100644 --- a/tests/testlib/openapi_session.py +++ b/tests/testlib/openapi_session.py @@ -108,6 +108,7 @@ def __init__( self.headers["Accept"] = "application/json" self.set_authentication_header(user, password) + self.changes = ChangesAPI(self) self.users = UsersAPI(self) self.folders = FoldersAPI(self) self.hosts = HostsAPI(self) @@ -169,75 +170,6 @@ def request( # type: ignore[no-untyped-def] return response - def activate_changes( - self, - sites: list[str] | None = None, - force_foreign_changes: bool = False, - ) -> None: - response = self.post( - "/domain-types/activation_run/actions/activate-changes/invoke", - json={ - "redirect": True, - "sites": sites or [], - "force_foreign_changes": force_foreign_changes, - }, - headers={"If-Match": "*"}, - # We want to get the redirect response and handle that below. So don't let requests - # handle that for us. - allow_redirects=False, - ) - if response.status_code == 200: - logger.info("Activation id: %s", response.json()["id"]) - return # changes are activated - if response.status_code == 422: - raise NoActiveChanges # there are no changes - if 300 <= response.status_code < 400: - redirect_url = response.headers["Location"] - - # Extract the activation ID from the wait-for-completion URL - # "/{site_id}/check_mk/api/1.0/objects/activation_run/{activation_id}/actions/wait-for-completion/invoke", - assert redirect_url.split("/")[6] == "activation_run" - activation_id = redirect_url.split("/")[7] - logger.info("Activation pending (ID: %s)", activation_id) - - raise Redirect(redirect_url=redirect_url) # activation pending - raise UnexpectedResponse.from_response(response) - - def pending_changes(self, sites: list[str] | None = None) -> list[dict[str, Any]]: - """Returns a list of all changes currently pending.""" - response = self.get("/domain-types/activation_run/collections/pending_changes") - assert response.status_code == 200 - value: list[dict[str, Any]] = response.json()["value"] - return value - - @tracer.start_as_current_span("activate_changes_and_wait_for_completion") - def activate_changes_and_wait_for_completion( - self, - sites: list[str] | None = None, - force_foreign_changes: bool = False, - timeout: int = 300, # TODO: revert to 60 seconds once performance is improved. - ) -> bool: - """Activate changes via REST API and wait for completion. - - Returns: - * True if changes are activated - * False if there are no changes to be activated - """ - logger.info("Activate changes and wait %ds for completion...", timeout) - with self.wait_for_completion(timeout, "get", "activate_changes"): - try: - self.activate_changes(sites, force_foreign_changes) - except NoActiveChanges: - logger.info("There were no changes to activate") - return False - - pending_changes = self.pending_changes() - assert ( - not pending_changes - ), f"There are pending changes that were not activated: {pending_changes}" - - return True - @contextmanager def wait_for_completion( self, @@ -306,6 +238,68 @@ def __init__(self, session: CMKOpenApiSession) -> None: self.session = session +class ChangesAPI(BaseAPI): + def activate( + self, + sites: list[str] | None = None, + force_foreign_changes: bool = False, + ) -> None: + response = self.session.post( + "/domain-types/activation_run/actions/activate-changes/invoke", + json={ + "redirect": True, + "sites": sites or [], + "force_foreign_changes": force_foreign_changes, + }, + headers={"If-Match": "*"}, + # We want to get the redirect response and handle that below. So don't let requests + # handle that for us. + allow_redirects=False, + ) + if response.status_code == 200: + logger.info("Activation id: %s", response.json()["id"]) + return # changes are activated + if response.status_code == 422: + raise NoActiveChanges # there are no changes + if 300 <= response.status_code < 400: + raise Redirect(redirect_url=response.headers["Location"]) # activation pending + raise UnexpectedResponse.from_response(response) + + def get_pending(self) -> list[dict[str, Any]]: + """Returns a list of all changes currently pending.""" + response = self.session.get("/domain-types/activation_run/collections/pending_changes") + assert response.status_code == 200 + value: list[dict[str, Any]] = response.json()["value"] + return value + + @tracer.start_as_current_span("activate_and_wait_for_completion") + def activate_and_wait_for_completion( + self, + sites: list[str] | None = None, + force_foreign_changes: bool = False, + timeout: int = 300, # TODO: revert to 60 seconds once performance is improved. + ) -> bool: + """Activate changes via REST API and wait for completion. + + Returns: + * True if changes are activated + * False if there are no changes to be activated + """ + logger.info("Activate changes and wait %ds for completion...", timeout) + with self.session.wait_for_completion(timeout, "get", "activate_changes"): + try: + self.activate(sites, force_foreign_changes) + except NoActiveChanges: + return False + + pending_changes = self.get_pending() + assert ( + not pending_changes + ), f"There are pending changes that were not activated: {pending_changes}" + + return True + + class UsersAPI(BaseAPI): def create( self, diff --git a/tests/testlib/site.py b/tests/testlib/site.py index 42c0097fd7a..2d233191366 100644 --- a/tests/testlib/site.py +++ b/tests/testlib/site.py @@ -1412,7 +1412,7 @@ def activate_changes_and_wait_for_core_reload( "A previous activation is still running. Does the wait work?" ) - changed = self.openapi.activate_changes_and_wait_for_completion( + changed = self.openapi.changes.activate_and_wait_for_completion( force_foreign_changes=allow_foreign_changes ) if changed: @@ -1777,7 +1777,7 @@ def update_as_site_user( site.version.edition.short == target_version.edition.short ), "Edition mismatch during update!" - site.openapi.activate_changes_and_wait_for_completion() + site.openapi.changes.activate_and_wait_for_completion() return site