From 9109ef47a30fd18c16b21abb9adb14b0fd159321 Mon Sep 17 00:00:00 2001 From: Paulo Machado Date: Fri, 17 Apr 2026 22:35:58 +0200 Subject: [PATCH 1/9] testing fix --- machines/tests/integration/helpers_ha.py | 4 +-- .../test_async_replication_upgrade.py | 30 ++++++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/machines/tests/integration/helpers_ha.py b/machines/tests/integration/helpers_ha.py index 4c6d3d92e..d35d4eedd 100644 --- a/machines/tests/integration/helpers_ha.py +++ b/machines/tests/integration/helpers_ha.py @@ -78,7 +78,7 @@ def check_mysql_units_writes_increment( for unit_name in app_units: for attempt in Retrying( reraise=True, - stop=stop_after_delay(5 * MINUTE_SECS), + stop=stop_after_delay(2 * MINUTE_SECS), wait=wait_fixed(10), ): with attempt: @@ -587,7 +587,7 @@ def verify_mysql_test_data(juju: Juju, app_name: str, table_name: str, value: st for unit_name in mysql_app_units: for attempt in Retrying( reraise=True, - stop=stop_after_delay(5 * MINUTE_SECS), + stop=stop_after_delay(2 * MINUTE_SECS), wait=wait_fixed(10), ): with attempt: diff --git a/machines/tests/integration/integration/high_availability/test_async_replication_upgrade.py b/machines/tests/integration/integration/high_availability/test_async_replication_upgrade.py index a1f5e12c0..0d8d5e7d6 100644 --- a/machines/tests/integration/integration/high_availability/test_async_replication_upgrade.py +++ b/machines/tests/integration/integration/high_availability/test_async_replication_upgrade.py @@ -6,6 +6,7 @@ import os import time from collections.abc import Generator +from concurrent.futures import ThreadPoolExecutor import jubilant_backports import pytest @@ -95,14 +96,23 @@ def test_build_and_deploy(first_model: str, second_model: str, charm: str) -> No ) logging.info("Waiting for the applications to settle") - model_1.wait( - ready=wait_for_apps_status(jubilant_backports.all_active, MYSQL_APP_1), - timeout=10 * MINUTE_SECS, - ) - model_2.wait( - ready=wait_for_apps_status(jubilant_backports.all_active, MYSQL_APP_2), - timeout=10 * MINUTE_SECS, - ) + + def wait_model_1(): + model_1.wait( + ready=wait_for_apps_status(jubilant_backports.all_active, MYSQL_APP_1), + timeout=20 * MINUTE_SECS, + ) + + def wait_model_2(): + model_2.wait( + ready=wait_for_apps_status(jubilant_backports.all_active, MYSQL_APP_2), + timeout=20 * MINUTE_SECS, + ) + + with ThreadPoolExecutor(max_workers=2) as executor: + futures = [executor.submit(wait_model_1), executor.submit(wait_model_2)] + for future in futures: + future.result() if path := os.getenv("DATA_SOURCE_PATH"): logging.info("Loading test database") @@ -259,7 +269,7 @@ def run_pre_upgrade_checks(juju: Juju, app_name: str) -> None: def run_upgrade_from_edge(juju: Juju, app_name: str, charm: str) -> None: - """Update the second cluster.""" + """Upgrade a cluster and wait for completion.""" logging.info("Ensure continuous writes are incrementing") check_mysql_units_writes_increment(juju, app_name) @@ -274,7 +284,7 @@ def run_upgrade_from_edge(juju: Juju, app_name: str, charm: str) -> None: logging.info("Wait for upgrade to complete") juju.wait( - ready=lambda status: jubilant_backports.all_active(status, app_name), + ready=wait_for_apps_status(jubilant_backports.all_active, app_name), timeout=20 * MINUTE_SECS, ) From 9889ef9911bf58e5fe4622d5660679f7fc03a57e Mon Sep 17 00:00:00 2001 From: Paulo Machado Date: Fri, 17 Apr 2026 22:55:32 +0200 Subject: [PATCH 2/9] concurrent wait --- .../test_async_replication.py | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/machines/tests/integration/integration/high_availability/test_async_replication.py b/machines/tests/integration/integration/high_availability/test_async_replication.py index 62b99c79e..74166ecd8 100644 --- a/machines/tests/integration/integration/high_availability/test_async_replication.py +++ b/machines/tests/integration/integration/high_availability/test_async_replication.py @@ -6,6 +6,7 @@ import os import time from collections.abc import Generator +from concurrent.futures import ThreadPoolExecutor import jubilant_backports import pytest @@ -94,14 +95,19 @@ def test_build_and_deploy(first_model: str, second_model: str, charm: str) -> No ) logging.info("Waiting for the applications to settle") - model_1.wait( - ready=wait_for_apps_status(jubilant_backports.all_active, MYSQL_APP_1), - timeout=10 * MINUTE_SECS, - ) - model_2.wait( - ready=wait_for_apps_status(jubilant_backports.all_active, MYSQL_APP_2), - timeout=10 * MINUTE_SECS, - ) + with ThreadPoolExecutor(max_workers=2) as executor: + future_1 = executor.submit( + model_1.wait, + ready=wait_for_apps_status(jubilant_backports.all_active, MYSQL_APP_1), + timeout=20 * MINUTE_SECS, + ) + future_2 = executor.submit( + model_2.wait, + ready=wait_for_apps_status(jubilant_backports.all_active, MYSQL_APP_2), + timeout=20 * MINUTE_SECS, + ) + future_1.result() + future_2.result() if path := os.getenv("DATA_SOURCE_PATH"): logging.info("Loading test database") From aaff69d6dbbacc048503975c6cc8a58b0147eb40 Mon Sep 17 00:00:00 2001 From: Paulo Machado Date: Sun, 19 Apr 2026 22:20:47 +0200 Subject: [PATCH 3/9] other fixes --- machines/tests/integration/helpers_ha.py | 5 ++++- .../high_availability/test_async_replication.py | 2 -- .../test_async_replication_upgrade.py | 13 ++++++++++++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/machines/tests/integration/helpers_ha.py b/machines/tests/integration/helpers_ha.py index d35d4eedd..eeac046c0 100644 --- a/machines/tests/integration/helpers_ha.py +++ b/machines/tests/integration/helpers_ha.py @@ -75,6 +75,8 @@ def check_mysql_units_writes_increment( app_primary = get_mysql_primary_unit(juju, app_name, app_units[0]) app_max_value = get_mysql_max_written_value(juju, app_name, app_primary) + juju.model_config({"update-status-hook-interval": "10s"}) + for unit_name in app_units: for attempt in Retrying( reraise=True, @@ -85,6 +87,7 @@ def check_mysql_units_writes_increment( unit_max_value = get_mysql_max_written_value(juju, app_name, unit_name) assert unit_max_value > app_max_value, "Writes not incrementing" app_max_value = unit_max_value + juju.model_config(reset="update-status-hook-interval") def get_app_leader(juju: Juju, app_name: str) -> str: @@ -618,7 +621,7 @@ def wait_for_apps_status(jubilant_status_func: JujuAppsStatusFn, *apps: str) -> def wait_for_app_status(app_name: str, app_status: str) -> JujuModelStatusFn: """Returns whether a Juju app has a specific status.""" - return lambda status: (status.apps[app_name].app_status.current == app_status) + return lambda status: status.apps[app_name].app_status.current == app_status def wait_for_unit_status(app_name: str, unit_name: str, unit_status: str) -> JujuModelStatusFn: diff --git a/machines/tests/integration/integration/high_availability/test_async_replication.py b/machines/tests/integration/integration/high_availability/test_async_replication.py index 74166ecd8..dd54c7323 100644 --- a/machines/tests/integration/integration/high_availability/test_async_replication.py +++ b/machines/tests/integration/integration/high_availability/test_async_replication.py @@ -153,7 +153,6 @@ def test_deploy_router_and_app(first_model: str) -> None: base="ubuntu@22.04", channel="dpe/edge", num_units=1, - trust=True, ) model_1.deploy( charm=MYSQL_TEST_APP_NAME, @@ -161,7 +160,6 @@ def test_deploy_router_and_app(first_model: str) -> None: base="ubuntu@22.04", channel="latest/edge", num_units=1, - trust=False, ) logging.info("Relating the router and test application") diff --git a/machines/tests/integration/integration/high_availability/test_async_replication_upgrade.py b/machines/tests/integration/integration/high_availability/test_async_replication_upgrade.py index 0d8d5e7d6..0da703f33 100644 --- a/machines/tests/integration/integration/high_availability/test_async_replication_upgrade.py +++ b/machines/tests/integration/integration/high_availability/test_async_replication_upgrade.py @@ -28,6 +28,7 @@ MYSQL_APP_1 = "db1" MYSQL_APP_2 = "db2" MYSQL_TEST_APP_NAME = "mysql-test-app" +MYSQL_ROUTER = "mysql-router" MINUTE_SECS = 60 @@ -159,12 +160,22 @@ def test_deploy_test_app(first_model: str) -> None: channel="latest/edge", num_units=1, ) + model_1.deploy( + charm=MYSQL_ROUTER, + app=MYSQL_ROUTER, + base="ubuntu@22.04", + channel="dpe/edge", + ) logging.info("Relating the test application") model_1.integrate( - f"{MYSQL_APP_1}:database", + f"{MYSQL_ROUTER}:database", f"{MYSQL_TEST_APP_NAME}:database", ) + model_1.integrate( + f"{MYSQL_ROUTER}:backend-database", + f"{MYSQL_APP_1}:database", + ) model_1.wait( ready=wait_for_apps_status(jubilant_backports.all_active, MYSQL_TEST_APP_NAME), From 4e078df5ed38becc364688fd29e59b4095828ac2 Mon Sep 17 00:00:00 2001 From: Paulo Machado Date: Mon, 20 Apr 2026 11:05:31 +0200 Subject: [PATCH 4/9] replicate machine improv to k8s --- kubernetes/tests/integration/helpers_ha.py | 21 +++++----- .../test_async_replication_upgrade.py | 42 +++++++++++++++---- .../test_primary_switchover.py | 10 ++--- machines/tests/integration/helpers_ha.py | 24 +++++------ 4 files changed, 60 insertions(+), 37 deletions(-) diff --git a/kubernetes/tests/integration/helpers_ha.py b/kubernetes/tests/integration/helpers_ha.py index 0157e05bf..fd29e8f09 100644 --- a/kubernetes/tests/integration/helpers_ha.py +++ b/kubernetes/tests/integration/helpers_ha.py @@ -83,16 +83,17 @@ def check_mysql_units_writes_increment( app_primary = get_mysql_primary_unit(juju, app_name, app_units[0]) app_max_value = get_mysql_max_written_value(juju, app_name, app_primary) - for unit_name in app_units: - for attempt in Retrying( - reraise=True, - stop=stop_after_delay(5 * MINUTE_SECS), - wait=wait_fixed(10), - ): - with attempt: - unit_max_value = get_mysql_max_written_value(juju, app_name, unit_name) - assert unit_max_value > app_max_value, "Writes not incrementing" - app_max_value = unit_max_value + with update_interval(juju, "10s"): + for unit_name in app_units: + for attempt in Retrying( + reraise=True, + stop=stop_after_delay(5 * MINUTE_SECS), + wait=wait_fixed(10), + ): + with attempt: + unit_max_value = get_mysql_max_written_value(juju, app_name, unit_name) + assert unit_max_value > app_max_value, "Writes not incrementing" + app_max_value = unit_max_value def delete_k8s_pod(juju: Juju, unit_name: str) -> None: diff --git a/kubernetes/tests/integration/integration/high_availability/test_async_replication_upgrade.py b/kubernetes/tests/integration/integration/high_availability/test_async_replication_upgrade.py index 227e85435..ce7f482ed 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_async_replication_upgrade.py +++ b/kubernetes/tests/integration/integration/high_availability/test_async_replication_upgrade.py @@ -6,6 +6,7 @@ import os import time from collections.abc import Generator +from concurrent.futures import ThreadPoolExecutor from contextlib import suppress import jubilant_backports @@ -32,6 +33,7 @@ MYSQL_APP_1 = "db1" MYSQL_APP_2 = "db2" MYSQL_TEST_APP_NAME = "mysql-test-app" +MYSQL_ROUTER = "mysql-router" MINUTE_SECS = 60 @@ -105,14 +107,23 @@ def test_build_and_deploy(first_model: str, second_model: str, charm: str) -> No ) logging.info("Waiting for the applications to settle") - model_1.wait( - ready=wait_for_apps_status(jubilant_backports.all_active, MYSQL_APP_1), - timeout=10 * MINUTE_SECS, - ) - model_2.wait( - ready=wait_for_apps_status(jubilant_backports.all_active, MYSQL_APP_2), - timeout=10 * MINUTE_SECS, - ) + + def wait_model_1(): + model_1.wait( + ready=wait_for_apps_status(jubilant_backports.all_active, MYSQL_APP_1), + timeout=10 * MINUTE_SECS, + ) + + def wait_model_2(): + model_2.wait( + ready=wait_for_apps_status(jubilant_backports.all_active, MYSQL_APP_2), + timeout=10 * MINUTE_SECS, + ) + + with ThreadPoolExecutor() as executor: + futures = [executor.submit(wait_model_1), executor.submit(wait_model_2)] + for future in futures: + future.result() if path := os.getenv("DATA_SOURCE_PATH"): logging.info("Loading test database") @@ -162,11 +173,24 @@ def test_deploy_test_app(first_model: str) -> None: constraints=constraints, ) + model_1.deploy( + charm=MYSQL_ROUTER, + app=MYSQL_ROUTER, + base="ubuntu@22.04", + channel="8.0/edge", + num_units=1, + trust=True, + ) + logging.info("Relating the test application") model_1.integrate( - f"{MYSQL_APP_1}:database", + f"{MYSQL_ROUTER}:database", f"{MYSQL_TEST_APP_NAME}:database", ) + model_1.integrate( + f"{MYSQL_ROUTER}:backend-database", + f"{MYSQL_APP_1}:database", + ) model_1.wait( ready=wait_for_apps_status(jubilant_backports.all_active, MYSQL_TEST_APP_NAME), diff --git a/kubernetes/tests/integration/integration/high_availability/test_primary_switchover.py b/kubernetes/tests/integration/integration/high_availability/test_primary_switchover.py index 8063dd9a7..0d1df95f6 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_primary_switchover.py +++ b/kubernetes/tests/integration/integration/high_availability/test_primary_switchover.py @@ -111,9 +111,9 @@ def test_cluster_failover_after_majority_loss(juju: Juju) -> None: non_primary_units = app_units - {primary_unit} - unit_to_promote = non_primary_units.pop() + unit_to_survive = non_primary_units.pop() - logging.info(f"Unit selected for promotion: {unit_to_promote}") + logging.info(f"Unit selected for promotion: {unit_to_survive}") logging.info("Simulate quorum loss") units_to_kill = [non_primary_units.pop(), primary_unit] @@ -123,7 +123,7 @@ def test_cluster_failover_after_majority_loss(juju: Juju) -> None: logging.info("Waiting to settle in error state") juju.wait( ready=lambda status: all(( - wait_for_unit_status(app_name, unit_to_promote, "active")(status), + wait_for_unit_status(app_name, unit_to_survive, "active")(status), wait_for_unit_message(app_name, units_to_kill[0], "OFFLINE")(status), wait_for_unit_message(app_name, units_to_kill[1], "OFFLINE")(status), )), @@ -133,7 +133,7 @@ def test_cluster_failover_after_majority_loss(juju: Juju) -> None: logging.info("Attempting to promote a unit to primary after quorum loss...") juju.run( - unit=unit_to_promote, + unit=primary_unit, action="promote-to-primary", params={"scope": "unit", "force": True}, wait=600, @@ -147,7 +147,7 @@ def test_cluster_failover_after_majority_loss(juju: Juju) -> None: delay=5, ) - assert get_mysql_primary_unit(juju, app_name) == unit_to_promote, "Failover failed" + assert get_mysql_primary_unit(juju, app_name) == primary_unit, "Failover failed" def kill_pods(juju: Juju, unit_names: list[str]) -> None: diff --git a/machines/tests/integration/helpers_ha.py b/machines/tests/integration/helpers_ha.py index eeac046c0..a9aa8d997 100644 --- a/machines/tests/integration/helpers_ha.py +++ b/machines/tests/integration/helpers_ha.py @@ -75,19 +75,17 @@ def check_mysql_units_writes_increment( app_primary = get_mysql_primary_unit(juju, app_name, app_units[0]) app_max_value = get_mysql_max_written_value(juju, app_name, app_primary) - juju.model_config({"update-status-hook-interval": "10s"}) - - for unit_name in app_units: - for attempt in Retrying( - reraise=True, - stop=stop_after_delay(2 * MINUTE_SECS), - wait=wait_fixed(10), - ): - with attempt: - unit_max_value = get_mysql_max_written_value(juju, app_name, unit_name) - assert unit_max_value > app_max_value, "Writes not incrementing" - app_max_value = unit_max_value - juju.model_config(reset="update-status-hook-interval") + with update_interval(juju, "10s"): + for unit_name in app_units: + for attempt in Retrying( + reraise=True, + stop=stop_after_delay(2 * MINUTE_SECS), + wait=wait_fixed(10), + ): + with attempt: + unit_max_value = get_mysql_max_written_value(juju, app_name, unit_name) + assert unit_max_value > app_max_value, "Writes not incrementing" + app_max_value = unit_max_value def get_app_leader(juju: Juju, app_name: str) -> str: From 8ba74907f9ca9ebda22905ac59de1672c41dad98 Mon Sep 17 00:00:00 2001 From: Paulo Machado Date: Mon, 20 Apr 2026 11:12:56 +0200 Subject: [PATCH 5/9] test revision for test-app --- .../integration/high_availability/test_async_replication.py | 2 +- .../high_availability/test_async_replication_upgrade.py | 2 +- .../high_availability/test_primary_switchover.py | 2 +- .../high_availability/test_replication_data_consistency.py | 2 +- .../high_availability/test_replication_data_isolation.py | 2 +- .../high_availability/test_replication_logs_rotation.py | 2 +- .../high_availability/test_replication_reelection.py | 2 +- .../high_availability/test_replication_scaling.py | 2 +- .../high_availability/test_replication_unit_endpoints.py | 4 ++-- .../high_availability/test_self_healing_network_cut.py | 2 +- .../high_availability/test_self_healing_node_drain.py | 2 +- .../integration/high_availability/test_self_healing_pod.py | 2 +- .../high_availability/test_self_healing_process_frozen.py | 2 +- .../high_availability/test_self_healing_process_killed.py | 2 +- .../high_availability/test_self_healing_restart_graceful.py | 2 +- .../high_availability/test_self_healing_stop_all.py | 2 +- .../high_availability/test_self_healing_stop_primary.py | 2 +- .../integration/high_availability/test_upgrade.py | 2 +- .../high_availability/test_upgrade_from_stable.py | 2 +- .../integration/integration/relations/test_database.py | 6 +++--- .../integration/integration/relations/test_mysql_root.py | 2 +- .../integration/roles/test_predefined_roles_refresh.py | 2 +- .../tests/integration/integration/test_multi_relations.py | 2 +- .../integration/test_saturate_max_connections.py | 2 +- .../release/high_availability/test_upgrade_from_stable.py | 2 +- .../integration/high_availability/test_async_replication.py | 2 +- .../high_availability/test_async_replication_upgrade.py | 2 +- .../high_availability/test_primary_switchover.py | 2 +- .../high_availability/test_replication_data_consistency.py | 2 +- .../high_availability/test_replication_data_isolation.py | 2 +- .../high_availability/test_replication_logs_rotation.py | 2 +- .../high_availability/test_replication_reelection.py | 2 +- .../high_availability/test_replication_scaling.py | 2 +- .../high_availability/test_replication_unit_endpoints.py | 2 +- .../high_availability/test_replication_variables.py | 2 +- .../high_availability/test_self_healing_network_cut.py | 2 +- .../high_availability/test_self_healing_process_frozen.py | 2 +- .../high_availability/test_self_healing_process_killed.py | 2 +- .../high_availability/test_self_healing_restart_forceful.py | 2 +- .../high_availability/test_self_healing_restart_graceful.py | 2 +- .../high_availability/test_self_healing_stop_all.py | 2 +- .../high_availability/test_self_healing_stop_primary.py | 2 +- .../integration/high_availability/test_upgrade.py | 2 +- .../integration/integration/relations/test_database.py | 2 +- .../integration/relations/test_relation_mysql_legacy.py | 2 +- .../integration/roles/test_predefined_roles_refresh.py | 2 +- .../tests/integration/integration/spaces/test_spaced_db.py | 4 ++-- .../integration/test_saturate_max_connections.py | 2 +- .../integration/integration/test_subordinate_charms.py | 2 +- .../release/high_availability/test_upgrade_from_stable.py | 2 +- 50 files changed, 54 insertions(+), 54 deletions(-) diff --git a/kubernetes/tests/integration/integration/high_availability/test_async_replication.py b/kubernetes/tests/integration/integration/high_availability/test_async_replication.py index f14763859..ccea5df6a 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_async_replication.py +++ b/kubernetes/tests/integration/integration/high_availability/test_async_replication.py @@ -164,7 +164,7 @@ def test_deploy_router_and_app(first_model: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", num_units=1, trust=False, constraints=constraints, diff --git a/kubernetes/tests/integration/integration/high_availability/test_async_replication_upgrade.py b/kubernetes/tests/integration/integration/high_availability/test_async_replication_upgrade.py index ce7f482ed..f39195b16 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_async_replication_upgrade.py +++ b/kubernetes/tests/integration/integration/high_availability/test_async_replication_upgrade.py @@ -168,7 +168,7 @@ def test_deploy_test_app(first_model: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", num_units=1, constraints=constraints, ) diff --git a/kubernetes/tests/integration/integration/high_availability/test_primary_switchover.py b/kubernetes/tests/integration/integration/high_availability/test_primary_switchover.py index 0d1df95f6..013259212 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_primary_switchover.py +++ b/kubernetes/tests/integration/integration/high_availability/test_primary_switchover.py @@ -45,7 +45,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 300}, num_units=1, constraints=constraints, diff --git a/kubernetes/tests/integration/integration/high_availability/test_replication_data_consistency.py b/kubernetes/tests/integration/integration/high_availability/test_replication_data_consistency.py index 21915087d..8132fb474 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_replication_data_consistency.py +++ b/kubernetes/tests/integration/integration/high_availability/test_replication_data_consistency.py @@ -42,7 +42,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 300}, num_units=1, constraints=constraints, diff --git a/kubernetes/tests/integration/integration/high_availability/test_replication_data_isolation.py b/kubernetes/tests/integration/integration/high_availability/test_replication_data_isolation.py index 6b0fd2eab..819622dea 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_replication_data_isolation.py +++ b/kubernetes/tests/integration/integration/high_availability/test_replication_data_isolation.py @@ -40,7 +40,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 300}, num_units=1, constraints=constraints, diff --git a/kubernetes/tests/integration/integration/high_availability/test_replication_logs_rotation.py b/kubernetes/tests/integration/integration/high_availability/test_replication_logs_rotation.py index 635d42c90..8ac2ccc36 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_replication_logs_rotation.py +++ b/kubernetes/tests/integration/integration/high_availability/test_replication_logs_rotation.py @@ -51,7 +51,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 300}, num_units=1, constraints=constraints, diff --git a/kubernetes/tests/integration/integration/high_availability/test_replication_reelection.py b/kubernetes/tests/integration/integration/high_availability/test_replication_reelection.py index 0462c51d2..1ad0d0926 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_replication_reelection.py +++ b/kubernetes/tests/integration/integration/high_availability/test_replication_reelection.py @@ -44,7 +44,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 300}, num_units=1, constraints=constraints, diff --git a/kubernetes/tests/integration/integration/high_availability/test_replication_scaling.py b/kubernetes/tests/integration/integration/high_availability/test_replication_scaling.py index fff1210e9..6ef4fb6bd 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_replication_scaling.py +++ b/kubernetes/tests/integration/integration/high_availability/test_replication_scaling.py @@ -42,7 +42,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 300}, num_units=1, constraints=constraints, diff --git a/kubernetes/tests/integration/integration/high_availability/test_replication_unit_endpoints.py b/kubernetes/tests/integration/integration/high_availability/test_replication_unit_endpoints.py index 5737475ef..5d7a989c8 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_replication_unit_endpoints.py +++ b/kubernetes/tests/integration/integration/high_availability/test_replication_unit_endpoints.py @@ -45,7 +45,7 @@ def test_deploy_highly_available_cluster_1(juju: Juju, charm: str) -> None: charm="mysql-test-app", app=MYSQL_TEST_APP_NAME_1, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 300}, num_units=1, constraints=constraints, @@ -89,7 +89,7 @@ def test_deploy_highly_available_cluster_2(juju: Juju, charm: str) -> None: charm="mysql-test-app", app=MYSQL_TEST_APP_NAME_2, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 300}, num_units=1, ) diff --git a/kubernetes/tests/integration/integration/high_availability/test_self_healing_network_cut.py b/kubernetes/tests/integration/integration/high_availability/test_self_healing_network_cut.py index 39f63d591..4efd25636 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_self_healing_network_cut.py +++ b/kubernetes/tests/integration/integration/high_availability/test_self_healing_network_cut.py @@ -48,7 +48,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 300}, num_units=1, constraints=constraints, diff --git a/kubernetes/tests/integration/integration/high_availability/test_self_healing_node_drain.py b/kubernetes/tests/integration/integration/high_availability/test_self_healing_node_drain.py index 3f1005250..61b26a22a 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_self_healing_node_drain.py +++ b/kubernetes/tests/integration/integration/high_availability/test_self_healing_node_drain.py @@ -46,7 +46,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 300}, num_units=1, constraints=constraints, diff --git a/kubernetes/tests/integration/integration/high_availability/test_self_healing_pod.py b/kubernetes/tests/integration/integration/high_availability/test_self_healing_pod.py index bffebb5a7..7afcc72ed 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_self_healing_pod.py +++ b/kubernetes/tests/integration/integration/high_availability/test_self_healing_pod.py @@ -44,7 +44,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 300}, num_units=1, constraints=constraints, diff --git a/kubernetes/tests/integration/integration/high_availability/test_self_healing_process_frozen.py b/kubernetes/tests/integration/integration/high_availability/test_self_healing_process_frozen.py index 41b527eea..18b728d3d 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_self_healing_process_frozen.py +++ b/kubernetes/tests/integration/integration/high_availability/test_self_healing_process_frozen.py @@ -51,7 +51,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 300}, num_units=1, constraints=constraints, diff --git a/kubernetes/tests/integration/integration/high_availability/test_self_healing_process_killed.py b/kubernetes/tests/integration/integration/high_availability/test_self_healing_process_killed.py index b406fcad6..4d3aeec47 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_self_healing_process_killed.py +++ b/kubernetes/tests/integration/integration/high_availability/test_self_healing_process_killed.py @@ -50,7 +50,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 300}, num_units=1, constraints=constraints, diff --git a/kubernetes/tests/integration/integration/high_availability/test_self_healing_restart_graceful.py b/kubernetes/tests/integration/integration/high_availability/test_self_healing_restart_graceful.py index 08eaff387..7de0327f8 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_self_healing_restart_graceful.py +++ b/kubernetes/tests/integration/integration/high_availability/test_self_healing_restart_graceful.py @@ -46,7 +46,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 300}, num_units=1, constraints=constraints, diff --git a/kubernetes/tests/integration/integration/high_availability/test_self_healing_stop_all.py b/kubernetes/tests/integration/integration/high_availability/test_self_healing_stop_all.py index a8075d2a2..755a260df 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_self_healing_stop_all.py +++ b/kubernetes/tests/integration/integration/high_availability/test_self_healing_stop_all.py @@ -44,7 +44,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 300}, num_units=1, constraints=constraints, diff --git a/kubernetes/tests/integration/integration/high_availability/test_self_healing_stop_primary.py b/kubernetes/tests/integration/integration/high_availability/test_self_healing_stop_primary.py index e90a58d97..286d9ec7c 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_self_healing_stop_primary.py +++ b/kubernetes/tests/integration/integration/high_availability/test_self_healing_stop_primary.py @@ -44,7 +44,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 300}, num_units=1, constraints=constraints, diff --git a/kubernetes/tests/integration/integration/high_availability/test_upgrade.py b/kubernetes/tests/integration/integration/high_availability/test_upgrade.py index df3a12d85..7bc2fddae 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_upgrade.py +++ b/kubernetes/tests/integration/integration/high_availability/test_upgrade.py @@ -52,7 +52,7 @@ def test_deploy_latest(juju: Juju) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", num_units=1, trust=False, constraints=constraints, diff --git a/kubernetes/tests/integration/integration/high_availability/test_upgrade_from_stable.py b/kubernetes/tests/integration/integration/high_availability/test_upgrade_from_stable.py index 6c37f6bd3..62d9b3240 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_upgrade_from_stable.py +++ b/kubernetes/tests/integration/integration/high_availability/test_upgrade_from_stable.py @@ -45,7 +45,7 @@ def test_deploy_stable(juju: Juju) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", num_units=1, constraints=constraints, ) diff --git a/kubernetes/tests/integration/integration/relations/test_database.py b/kubernetes/tests/integration/integration/relations/test_database.py index 612353806..10c7f916e 100644 --- a/kubernetes/tests/integration/integration/relations/test_database.py +++ b/kubernetes/tests/integration/integration/relations/test_database.py @@ -40,7 +40,7 @@ def test_build_and_deploy(juju: Juju, charm): juju.deploy( APPLICATION_APP_NAME, num_units=2, - channel="latest/edge", + channel="latest/edge/racing", base="ubuntu@22.04", constraints=constraints, ) @@ -127,7 +127,7 @@ def test_relation_broken_connectivity(juju: Juju): APPLICATION_APP_NAME, test_app_1, num_units=1, - channel="latest/edge", + channel="latest/edge/racing", config={"database_name": "test_database_1"}, base="ubuntu@22.04", ) @@ -136,7 +136,7 @@ def test_relation_broken_connectivity(juju: Juju): APPLICATION_APP_NAME, test_app_2, num_units=1, - channel="latest/edge", + channel="latest/edge/racing", config={"database_name": "test_database_2"}, base="ubuntu@22.04", ) diff --git a/kubernetes/tests/integration/integration/relations/test_mysql_root.py b/kubernetes/tests/integration/integration/relations/test_mysql_root.py index 2b4ee7a21..032f2829c 100644 --- a/kubernetes/tests/integration/integration/relations/test_mysql_root.py +++ b/kubernetes/tests/integration/integration/relations/test_mysql_root.py @@ -39,7 +39,7 @@ def test_build_and_deploy(juju: Juju, charm): juju.deploy( APPLICATION_APP_NAME, num_units=2, - channel="latest/edge", + channel="latest/edge/racing", base="ubuntu@22.04", constraints=constraints, ) diff --git a/kubernetes/tests/integration/integration/roles/test_predefined_roles_refresh.py b/kubernetes/tests/integration/integration/roles/test_predefined_roles_refresh.py index 9e514dd5a..23347d2a1 100644 --- a/kubernetes/tests/integration/integration/roles/test_predefined_roles_refresh.py +++ b/kubernetes/tests/integration/integration/roles/test_predefined_roles_refresh.py @@ -179,7 +179,7 @@ def test_integrate_mysql_router_and_test_app(juju: Juju): charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", num_units=1, config={"database_name": "test"}, ) diff --git a/kubernetes/tests/integration/integration/test_multi_relations.py b/kubernetes/tests/integration/integration/test_multi_relations.py index c3a313333..f88223108 100644 --- a/kubernetes/tests/integration/integration/test_multi_relations.py +++ b/kubernetes/tests/integration/integration/test_multi_relations.py @@ -33,7 +33,7 @@ def test_build_and_deploy(juju: Juju, charm): "mysql-test-app", f"app{idx}", num_units=1, - channel="latest/edge", + channel="latest/edge/racing", config={"database_name": f"database{idx}", "sleep_interval": "2000"}, base="ubuntu@22.04", constraints=constraints, diff --git a/kubernetes/tests/integration/integration/test_saturate_max_connections.py b/kubernetes/tests/integration/integration/test_saturate_max_connections.py index 950ab0253..342e741c5 100644 --- a/kubernetes/tests/integration/integration/test_saturate_max_connections.py +++ b/kubernetes/tests/integration/integration/test_saturate_max_connections.py @@ -42,7 +42,7 @@ def test_deploy_and_relate_test_app(juju: Juju) -> None: num_units=1, base="ubuntu@22.04", config=config, - channel="latest/edge", + channel="latest/edge/racing", constraints=constraints, ) diff --git a/kubernetes/tests/integration/release/high_availability/test_upgrade_from_stable.py b/kubernetes/tests/integration/release/high_availability/test_upgrade_from_stable.py index 39c83514a..738f804bf 100644 --- a/kubernetes/tests/integration/release/high_availability/test_upgrade_from_stable.py +++ b/kubernetes/tests/integration/release/high_availability/test_upgrade_from_stable.py @@ -96,7 +96,7 @@ def deploy_stable(juju: Juju, revision: int, image: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", num_units=1, trust=False, ) diff --git a/machines/tests/integration/integration/high_availability/test_async_replication.py b/machines/tests/integration/integration/high_availability/test_async_replication.py index dd54c7323..2ce937be1 100644 --- a/machines/tests/integration/integration/high_availability/test_async_replication.py +++ b/machines/tests/integration/integration/high_availability/test_async_replication.py @@ -158,7 +158,7 @@ def test_deploy_router_and_app(first_model: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", num_units=1, ) diff --git a/machines/tests/integration/integration/high_availability/test_async_replication_upgrade.py b/machines/tests/integration/integration/high_availability/test_async_replication_upgrade.py index 0da703f33..29dc685ee 100644 --- a/machines/tests/integration/integration/high_availability/test_async_replication_upgrade.py +++ b/machines/tests/integration/integration/high_availability/test_async_replication_upgrade.py @@ -157,7 +157,7 @@ def test_deploy_test_app(first_model: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", num_units=1, ) model_1.deploy( diff --git a/machines/tests/integration/integration/high_availability/test_primary_switchover.py b/machines/tests/integration/integration/high_availability/test_primary_switchover.py index 56a16a9e4..124fc70cc 100644 --- a/machines/tests/integration/integration/high_availability/test_primary_switchover.py +++ b/machines/tests/integration/integration/high_availability/test_primary_switchover.py @@ -40,7 +40,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 500}, num_units=1, ) diff --git a/machines/tests/integration/integration/high_availability/test_replication_data_consistency.py b/machines/tests/integration/integration/high_availability/test_replication_data_consistency.py index 5c59a17b1..dcdfff407 100644 --- a/machines/tests/integration/integration/high_availability/test_replication_data_consistency.py +++ b/machines/tests/integration/integration/high_availability/test_replication_data_consistency.py @@ -37,7 +37,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 500}, num_units=1, ) diff --git a/machines/tests/integration/integration/high_availability/test_replication_data_isolation.py b/machines/tests/integration/integration/high_availability/test_replication_data_isolation.py index f65033be8..5fd194dca 100644 --- a/machines/tests/integration/integration/high_availability/test_replication_data_isolation.py +++ b/machines/tests/integration/integration/high_availability/test_replication_data_isolation.py @@ -36,7 +36,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 500}, num_units=1, ) diff --git a/machines/tests/integration/integration/high_availability/test_replication_logs_rotation.py b/machines/tests/integration/integration/high_availability/test_replication_logs_rotation.py index 574a3221a..5e22bb274 100644 --- a/machines/tests/integration/integration/high_availability/test_replication_logs_rotation.py +++ b/machines/tests/integration/integration/high_availability/test_replication_logs_rotation.py @@ -43,7 +43,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 500}, num_units=1, ) diff --git a/machines/tests/integration/integration/high_availability/test_replication_reelection.py b/machines/tests/integration/integration/high_availability/test_replication_reelection.py index 6009ff367..e3417a924 100644 --- a/machines/tests/integration/integration/high_availability/test_replication_reelection.py +++ b/machines/tests/integration/integration/high_availability/test_replication_reelection.py @@ -39,7 +39,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 500}, num_units=1, ) diff --git a/machines/tests/integration/integration/high_availability/test_replication_scaling.py b/machines/tests/integration/integration/high_availability/test_replication_scaling.py index e347707ae..da7a319c5 100644 --- a/machines/tests/integration/integration/high_availability/test_replication_scaling.py +++ b/machines/tests/integration/integration/high_availability/test_replication_scaling.py @@ -38,7 +38,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 500}, num_units=1, ) diff --git a/machines/tests/integration/integration/high_availability/test_replication_unit_endpoints.py b/machines/tests/integration/integration/high_availability/test_replication_unit_endpoints.py index 421e97781..94c5d53e1 100644 --- a/machines/tests/integration/integration/high_availability/test_replication_unit_endpoints.py +++ b/machines/tests/integration/integration/high_availability/test_replication_unit_endpoints.py @@ -48,7 +48,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 500}, num_units=1, ) diff --git a/machines/tests/integration/integration/high_availability/test_replication_variables.py b/machines/tests/integration/integration/high_availability/test_replication_variables.py index 44a62d256..c25ef0680 100644 --- a/machines/tests/integration/integration/high_availability/test_replication_variables.py +++ b/machines/tests/integration/integration/high_availability/test_replication_variables.py @@ -34,7 +34,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 500}, num_units=1, ) diff --git a/machines/tests/integration/integration/high_availability/test_self_healing_network_cut.py b/machines/tests/integration/integration/high_availability/test_self_healing_network_cut.py index e186d0c2c..2cf24ed72 100644 --- a/machines/tests/integration/integration/high_availability/test_self_healing_network_cut.py +++ b/machines/tests/integration/integration/high_availability/test_self_healing_network_cut.py @@ -54,7 +54,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 500}, num_units=1, ) diff --git a/machines/tests/integration/integration/high_availability/test_self_healing_process_frozen.py b/machines/tests/integration/integration/high_availability/test_self_healing_process_frozen.py index b2d0dc9c2..d0b1fdc4f 100644 --- a/machines/tests/integration/integration/high_availability/test_self_healing_process_frozen.py +++ b/machines/tests/integration/integration/high_availability/test_self_healing_process_frozen.py @@ -47,7 +47,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 500}, num_units=1, ) diff --git a/machines/tests/integration/integration/high_availability/test_self_healing_process_killed.py b/machines/tests/integration/integration/high_availability/test_self_healing_process_killed.py index c82ff6d93..577f5a7e5 100644 --- a/machines/tests/integration/integration/high_availability/test_self_healing_process_killed.py +++ b/machines/tests/integration/integration/high_availability/test_self_healing_process_killed.py @@ -41,7 +41,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 500}, num_units=1, ) diff --git a/machines/tests/integration/integration/high_availability/test_self_healing_restart_forceful.py b/machines/tests/integration/integration/high_availability/test_self_healing_restart_forceful.py index 50b075fca..c5f17d7fe 100644 --- a/machines/tests/integration/integration/high_availability/test_self_healing_restart_forceful.py +++ b/machines/tests/integration/integration/high_availability/test_self_healing_restart_forceful.py @@ -48,7 +48,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 500}, num_units=1, ) diff --git a/machines/tests/integration/integration/high_availability/test_self_healing_restart_graceful.py b/machines/tests/integration/integration/high_availability/test_self_healing_restart_graceful.py index 2bc2da702..1c1729fde 100644 --- a/machines/tests/integration/integration/high_availability/test_self_healing_restart_graceful.py +++ b/machines/tests/integration/integration/high_availability/test_self_healing_restart_graceful.py @@ -42,7 +42,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 500}, num_units=1, ) diff --git a/machines/tests/integration/integration/high_availability/test_self_healing_stop_all.py b/machines/tests/integration/integration/high_availability/test_self_healing_stop_all.py index 8e254192c..922ee7400 100644 --- a/machines/tests/integration/integration/high_availability/test_self_healing_stop_all.py +++ b/machines/tests/integration/integration/high_availability/test_self_healing_stop_all.py @@ -48,7 +48,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 500}, num_units=1, ) diff --git a/machines/tests/integration/integration/high_availability/test_self_healing_stop_primary.py b/machines/tests/integration/integration/high_availability/test_self_healing_stop_primary.py index 37f6d1c01..499bf11c0 100644 --- a/machines/tests/integration/integration/high_availability/test_self_healing_stop_primary.py +++ b/machines/tests/integration/integration/high_availability/test_self_healing_stop_primary.py @@ -50,7 +50,7 @@ def test_deploy_highly_available_cluster(juju: Juju, charm: str) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", config={"sleep_interval": 500}, num_units=1, ) diff --git a/machines/tests/integration/integration/high_availability/test_upgrade.py b/machines/tests/integration/integration/high_availability/test_upgrade.py index 9acd277ca..a138a8f69 100644 --- a/machines/tests/integration/integration/high_availability/test_upgrade.py +++ b/machines/tests/integration/integration/high_availability/test_upgrade.py @@ -43,7 +43,7 @@ def test_deploy_latest(juju: Juju) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", num_units=1, ) diff --git a/machines/tests/integration/integration/relations/test_database.py b/machines/tests/integration/integration/relations/test_database.py index ef44967da..ab688cc9d 100644 --- a/machines/tests/integration/integration/relations/test_database.py +++ b/machines/tests/integration/integration/relations/test_database.py @@ -50,7 +50,7 @@ def test_build_and_deploy(juju: Juju, charm): juju.deploy( APPLICATION_APP_NAME, num_units=2, - channel="latest/edge", + channel="latest/edge/racing", base="ubuntu@22.04", ) diff --git a/machines/tests/integration/integration/relations/test_relation_mysql_legacy.py b/machines/tests/integration/integration/relations/test_relation_mysql_legacy.py index 32e0c3d57..81fb2b2eb 100644 --- a/machines/tests/integration/integration/relations/test_relation_mysql_legacy.py +++ b/machines/tests/integration/integration/relations/test_relation_mysql_legacy.py @@ -46,7 +46,7 @@ def test_build_and_deploy(juju: Juju, charm) -> None: juju.deploy( APPLICATION_APP_NAME, num_units=1, - channel="latest/edge", + channel="latest/edge/racing", base="ubuntu@22.04", ) diff --git a/machines/tests/integration/integration/roles/test_predefined_roles_refresh.py b/machines/tests/integration/integration/roles/test_predefined_roles_refresh.py index bcfe6717a..0ee57f59c 100644 --- a/machines/tests/integration/integration/roles/test_predefined_roles_refresh.py +++ b/machines/tests/integration/integration/roles/test_predefined_roles_refresh.py @@ -161,7 +161,7 @@ def test_integrate_mysql_router_and_test_app(juju: Juju): charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", num_units=1, config={"database_name": "test"}, ) diff --git a/machines/tests/integration/integration/spaces/test_spaced_db.py b/machines/tests/integration/integration/spaces/test_spaced_db.py index 5c0d4226e..1050f2e2c 100644 --- a/machines/tests/integration/integration/spaces/test_spaced_db.py +++ b/machines/tests/integration/integration/spaces/test_spaced_db.py @@ -42,7 +42,7 @@ def test_build_and_deploy(juju: Juju, lxd_spaces, charm) -> None: bind={"database": "client"}, num_units=1, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", ) juju.wait( @@ -96,7 +96,7 @@ def test_integrate_with_isolated_space(juju: Juju): bind={"database": "isolated"}, num_units=1, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", ) juju.wait( ready=wait_for_apps_status(jubilant_backports.all_waiting, isolated_app_name), diff --git a/machines/tests/integration/integration/test_saturate_max_connections.py b/machines/tests/integration/integration/test_saturate_max_connections.py index 50f1afea4..86fb274e8 100644 --- a/machines/tests/integration/integration/test_saturate_max_connections.py +++ b/machines/tests/integration/integration/test_saturate_max_connections.py @@ -39,7 +39,7 @@ def test_deploy_and_relate_test_app(juju: Juju) -> None: num_units=1, base="ubuntu@22.04", config=config, - channel="latest/edge", + channel="latest/edge/racing", ) logger.info("Relating test app to mysql") diff --git a/machines/tests/integration/integration/test_subordinate_charms.py b/machines/tests/integration/integration/test_subordinate_charms.py index e5599c375..a0fbc70d3 100644 --- a/machines/tests/integration/integration/test_subordinate_charms.py +++ b/machines/tests/integration/integration/test_subordinate_charms.py @@ -28,7 +28,7 @@ def test_ubuntu_pro(juju: Juju, charm): juju.deploy( APPLICATION_APP_NAME, APPLICATION_APP_NAME, - channel="latest/edge", + channel="latest/edge/racing", base="ubuntu@22.04", ) juju.deploy( diff --git a/machines/tests/integration/release/high_availability/test_upgrade_from_stable.py b/machines/tests/integration/release/high_availability/test_upgrade_from_stable.py index 91e1bc1f0..bc16ceb8f 100644 --- a/machines/tests/integration/release/high_availability/test_upgrade_from_stable.py +++ b/machines/tests/integration/release/high_availability/test_upgrade_from_stable.py @@ -88,7 +88,7 @@ def deploy_stable(juju: Juju, revision: int) -> None: charm=MYSQL_TEST_APP_NAME, app=MYSQL_TEST_APP_NAME, base="ubuntu@22.04", - channel="latest/edge", + channel="latest/edge/racing", num_units=1, ) From 0318b5ff89e8623225a252cb4c37543bad526f2a Mon Sep 17 00:00:00 2001 From: Paulo Machado Date: Mon, 20 Apr 2026 11:35:43 +0200 Subject: [PATCH 6/9] fix app --- .../high_availability/test_async_replication_upgrade.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes/tests/integration/integration/high_availability/test_async_replication_upgrade.py b/kubernetes/tests/integration/integration/high_availability/test_async_replication_upgrade.py index f39195b16..75f1ac76b 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_async_replication_upgrade.py +++ b/kubernetes/tests/integration/integration/high_availability/test_async_replication_upgrade.py @@ -33,7 +33,7 @@ MYSQL_APP_1 = "db1" MYSQL_APP_2 = "db2" MYSQL_TEST_APP_NAME = "mysql-test-app" -MYSQL_ROUTER = "mysql-router" +MYSQL_ROUTER = "mysql-router-k8s" MINUTE_SECS = 60 From b93b7de913e398263b5f1c110a08405bfc174a6d Mon Sep 17 00:00:00 2001 From: Paulo Machado Date: Wed, 22 Apr 2026 15:45:03 +0200 Subject: [PATCH 7/9] freeze mysqld instead of kill pod The force_quorum method check for other instances connectivity, so it will fail. Keep then frozen --- .../test_primary_switchover.py | 88 ++++++++++++------- 1 file changed, 57 insertions(+), 31 deletions(-) diff --git a/kubernetes/tests/integration/integration/high_availability/test_primary_switchover.py b/kubernetes/tests/integration/integration/high_availability/test_primary_switchover.py index 013259212..5c7df06f2 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_primary_switchover.py +++ b/kubernetes/tests/integration/integration/high_availability/test_primary_switchover.py @@ -18,7 +18,6 @@ load_mysql_test_data, update_interval, wait_for_apps_status, - wait_for_unit_message, wait_for_unit_status, ) @@ -112,33 +111,32 @@ def test_cluster_failover_after_majority_loss(juju: Juju) -> None: non_primary_units = app_units - {primary_unit} unit_to_survive = non_primary_units.pop() + units_to_freeze = [non_primary_units.pop(), primary_unit] logging.info(f"Unit selected for promotion: {unit_to_survive}") - logging.info("Simulate quorum loss") - units_to_kill = [non_primary_units.pop(), primary_unit] - kill_pods(juju, units_to_kill) + logging.info("Simulating quorum loss via SIGSTOP on mysqld") + freeze_mysql(juju, units_to_freeze) with update_interval(juju, "45s"): - logging.info("Waiting to settle in error state") + logging.info("Waiting for surviving unit to detect quorum loss") juju.wait( - ready=lambda status: all(( - wait_for_unit_status(app_name, unit_to_survive, "active")(status), - wait_for_unit_message(app_name, units_to_kill[0], "OFFLINE")(status), - wait_for_unit_message(app_name, units_to_kill[1], "OFFLINE")(status), - )), - timeout=15 * MINUTE_SECS, - delay=15, + ready=lambda status: wait_for_unit_status(app_name, unit_to_survive, "active")(status), + timeout=5 * MINUTE_SECS, + delay=10, ) - logging.info("Attempting to promote a unit to primary after quorum loss...") + logging.info("Attempting to promote surviving unit to primary after quorum loss...") juju.run( - unit=primary_unit, + unit=unit_to_survive, action="promote-to-primary", params={"scope": "unit", "force": True}, wait=600, ) + logging.info("Resuming frozen units so they can rejoin the cluster") + unfreeze_mysql(juju, units_to_freeze) + with update_interval(juju, "15s"): logging.info("Waiting for all units to become active after switchover...") juju.wait( @@ -147,20 +145,48 @@ def test_cluster_failover_after_majority_loss(juju: Juju) -> None: delay=5, ) - assert get_mysql_primary_unit(juju, app_name) == primary_unit, "Failover failed" - - -def kill_pods(juju: Juju, unit_names: list[str]) -> None: - """Kill the unit pods simultaneously using kubectl.""" - pod_names = [get_mysql_instance_label(unit) for unit in unit_names] - cmd = [ - "kubectl", - "delete", - "pod", - *pod_names, - "-n", - juju.model, - "--grace-period=0", - "--force", - ] - subprocess.run(cmd, check=True) + assert get_mysql_primary_unit(juju, app_name) == unit_to_survive, "Failover failed" + + +def freeze_mysql(juju: Juju, unit_names: list[str]) -> None: + """Freeze mysqld in the mysql container via SIGSTOP to simulate unreachable members.""" + for unit in unit_names: + pod = get_mysql_instance_label(unit) + subprocess.run( + [ + "kubectl", + "exec", + pod, + "-n", + juju.model, + "-c", + "mysql", + "--", + "bash", + "-c", + "kill -STOP $(pgrep -x mysqld)", + ], + check=True, + ) + + +def unfreeze_mysql(juju: Juju, unit_names: list[str]) -> None: + """Resume frozen mysqld in the mysql container via SIGCONT.""" + for unit in unit_names: + pod = get_mysql_instance_label(unit) + subprocess.run( + [ + "kubectl", + "exec", + pod, + "-n", + juju.model, + "-c", + "mysql", + "--", + "bash", + "-c", + "kill -CONT $(pgrep -x mysqld)", + ], + check=True, + ) From ce99abedef844463dd3adf4e85c9380f60aca972 Mon Sep 17 00:00:00 2001 From: Paulo Machado Date: Wed, 22 Apr 2026 16:00:06 +0200 Subject: [PATCH 8/9] 10x default timeout (30s) --- kubernetes/lib/charms/mysql/v0/mysql.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/kubernetes/lib/charms/mysql/v0/mysql.py b/kubernetes/lib/charms/mysql/v0/mysql.py index edaeb1075..d3d976bf3 100644 --- a/kubernetes/lib/charms/mysql/v0/mysql.py +++ b/kubernetes/lib/charms/mysql/v0/mysql.py @@ -152,6 +152,7 @@ def __init__( MAX_CONNECTIONS_FLOOR = 10 MIM_MEM_BUFFERS = 200 * BYTES_1MiB ADMIN_PORT = 33062 +FORCE_QUORUM_TIMEOUT = 300 # seconds # Labels are not confidential SECRET_INTERNAL_LABEL = "secret-id" # noqa: S105 @@ -2370,13 +2371,16 @@ def force_quorum_from_instance(self) -> None: instance_def = ( f"{self.cluster_admin_user}:{self.cluster_admin_password}@{self.instance_address}" ) + # TODO: modify/expose timeout in the mysql-shell-client library + address = f"{instance_def}:3306" + command = "\n".join(( + f"cluster = dba.get_cluster('{self.cluster_name}')", + f"cluster.force_quorum_using_partition_of('{address}')", + )) + executor = self._build_cluster_tcp_executor(self.instance_address) try: - self._cluster_client_tcp.force_instance_quorum_into_cluster( - cluster_name=self.cluster_name, - instance_host=instance_def, - instance_port=str(3306), - ) + executor.execute_py(command, timeout=FORCE_QUORUM_TIMEOUT) except ExecutionError as e: raise MySQLForceQuorumFromInstanceError() from e From 5bf3ae9276b1c9fa5ef717f28e88506cac3636cf Mon Sep 17 00:00:00 2001 From: Paulo Machado Date: Wed, 22 Apr 2026 19:01:34 +0200 Subject: [PATCH 9/9] fix calls --- .../high_availability/test_primary_switchover.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/kubernetes/tests/integration/integration/high_availability/test_primary_switchover.py b/kubernetes/tests/integration/integration/high_availability/test_primary_switchover.py index 5c7df06f2..4d9615533 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_primary_switchover.py +++ b/kubernetes/tests/integration/integration/high_availability/test_primary_switchover.py @@ -152,13 +152,13 @@ def freeze_mysql(juju: Juju, unit_names: list[str]) -> None: """Freeze mysqld in the mysql container via SIGSTOP to simulate unreachable members.""" for unit in unit_names: pod = get_mysql_instance_label(unit) - subprocess.run( + subprocess.check_call( [ "kubectl", "exec", pod, "-n", - juju.model, + juju.model or "testing", "-c", "mysql", "--", @@ -166,7 +166,6 @@ def freeze_mysql(juju: Juju, unit_names: list[str]) -> None: "-c", "kill -STOP $(pgrep -x mysqld)", ], - check=True, ) @@ -174,13 +173,13 @@ def unfreeze_mysql(juju: Juju, unit_names: list[str]) -> None: """Resume frozen mysqld in the mysql container via SIGCONT.""" for unit in unit_names: pod = get_mysql_instance_label(unit) - subprocess.run( + subprocess.check_call( [ "kubectl", "exec", pod, "-n", - juju.model, + juju.model or "testing", "-c", "mysql", "--", @@ -188,5 +187,4 @@ def unfreeze_mysql(juju: Juju, unit_names: list[str]) -> None: "-c", "kill -CONT $(pgrep -x mysqld)", ], - check=True, )