From 33d0f4d6273b540b1257eb4fdf238cf870b70d1b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 23 Apr 2026 11:50:18 +0000 Subject: [PATCH 1/2] Backport PR #264: fix self-healing test waiting logic and wait_for_unit_status misuses Agent-Logs-Url: https://github.com/canonical/mysql-operators/sessions/9dc045f5-e998-405f-918e-299a250ed5ef Co-authored-by: astrojuanlu <316517+astrojuanlu@users.noreply.github.com> --- .../test_self_healing_setup_crash.py | 13 ++++++++++++- .../integration/roles/test_database_dba_role.py | 4 ++-- .../integration/roles/test_instance_dba_role.py | 2 +- .../integration/roles/test_instance_roles.py | 10 +++++----- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/kubernetes/tests/integration/integration/high_availability/test_self_healing_setup_crash.py b/kubernetes/tests/integration/integration/high_availability/test_self_healing_setup_crash.py index 0a8c94b07..bf60b0490 100644 --- a/kubernetes/tests/integration/integration/high_availability/test_self_healing_setup_crash.py +++ b/kubernetes/tests/integration/integration/high_availability/test_self_healing_setup_crash.py @@ -14,6 +14,7 @@ load_mysql_test_data, update_interval, wait_for_apps_status, + wait_for_unit_status, ) MYSQL_APP_NAME = "mysql-k8s" @@ -30,6 +31,7 @@ def test_deploy_single_unit_cluster(juju: Juju, charm: str) -> None: config={"profile": "testing"}, resources={"mysql-image": CHARM_METADATA["resources"]["mysql-image"]["upstream-source"]}, num_units=1, + trust=True, ) logging.info("Wait for applications to become active") @@ -53,10 +55,19 @@ def test_crash_during_cluster_setup(juju: Juju, charm: str) -> None: logging.info("Scaling to 3 units") juju.add_unit(MYSQL_APP_NAME, num_units=2) + # NOTE: This is prone to race conditions: + # if the units clear the "waiting" phase too quickly, + # this status function will never activate juju.wait( - ready=wait_for_apps_status(jubilant_backports.any_waiting, MYSQL_APP_NAME), + ready=lambda status: any(( + *( + wait_for_unit_status(MYSQL_APP_NAME, unit_name, "waiting")(status) + for unit_name in status.get_units(MYSQL_APP_NAME) + ), + )), error=jubilant_backports.any_blocked, timeout=20 * MINUTE_SECS, + successes=1, ) logging.info("Deleting pod") diff --git a/kubernetes/tests/integration/integration/roles/test_database_dba_role.py b/kubernetes/tests/integration/integration/roles/test_database_dba_role.py index 2ff5deb95..3731a6c36 100644 --- a/kubernetes/tests/integration/integration/roles/test_database_dba_role.py +++ b/kubernetes/tests/integration/integration/roles/test_database_dba_role.py @@ -54,11 +54,11 @@ def test_build_and_deploy(juju: Juju, charm) -> None: juju.wait( ready=lambda status: all(( *( - wait_for_unit_status(f"{INTEGRATOR_APP_NAME}1", unit_name, "blocked") + wait_for_unit_status(f"{INTEGRATOR_APP_NAME}1", unit_name, "blocked")(status) for unit_name in status.get_units(f"{INTEGRATOR_APP_NAME}1") ), *( - wait_for_unit_status(f"{INTEGRATOR_APP_NAME}2", unit_name, "blocked") + wait_for_unit_status(f"{INTEGRATOR_APP_NAME}2", unit_name, "blocked")(status) for unit_name in status.get_units(f"{INTEGRATOR_APP_NAME}2") ), )), diff --git a/kubernetes/tests/integration/integration/roles/test_instance_dba_role.py b/kubernetes/tests/integration/integration/roles/test_instance_dba_role.py index bf00e02a6..54e04e13f 100644 --- a/kubernetes/tests/integration/integration/roles/test_instance_dba_role.py +++ b/kubernetes/tests/integration/integration/roles/test_instance_dba_role.py @@ -44,7 +44,7 @@ def test_build_and_deploy(juju: Juju, charm) -> None: juju.wait( ready=lambda status: all(( *( - wait_for_unit_status(INTEGRATOR_APP_NAME, unit_name, "blocked") + wait_for_unit_status(INTEGRATOR_APP_NAME, unit_name, "blocked")(status) for unit_name in status.get_units(INTEGRATOR_APP_NAME) ), )), diff --git a/kubernetes/tests/integration/integration/roles/test_instance_roles.py b/kubernetes/tests/integration/integration/roles/test_instance_roles.py index 2088fc2de..e0eb058a8 100644 --- a/kubernetes/tests/integration/integration/roles/test_instance_roles.py +++ b/kubernetes/tests/integration/integration/roles/test_instance_roles.py @@ -55,11 +55,11 @@ def test_build_and_deploy(juju: Juju, charm) -> None: juju.wait( ready=lambda status: all(( *( - wait_for_unit_status(f"{INTEGRATOR_APP_NAME}1", unit_name, "blocked") + wait_for_unit_status(f"{INTEGRATOR_APP_NAME}1", unit_name, "blocked")(status) for unit_name in status.get_units(f"{INTEGRATOR_APP_NAME}1") ), *( - wait_for_unit_status(f"{INTEGRATOR_APP_NAME}2", unit_name, "blocked") + wait_for_unit_status(f"{INTEGRATOR_APP_NAME}2", unit_name, "blocked")(status) for unit_name in status.get_units(f"{INTEGRATOR_APP_NAME}2") ), )), @@ -144,7 +144,7 @@ def test_charmed_read_role(juju: Juju): # wait for relation to be fully removed before adding it again in the following test jubilant_backports.all_agents_idle(status, f"{INTEGRATOR_APP_NAME}1"), *( - wait_for_unit_status(f"{INTEGRATOR_APP_NAME}1", unit_name, "blocked") + wait_for_unit_status(f"{INTEGRATOR_APP_NAME}1", unit_name, "blocked")(status) for unit_name in status.get_units(f"{INTEGRATOR_APP_NAME}1") ), )), @@ -251,11 +251,11 @@ def test_charmed_dml_role(juju: Juju): juju.wait( ready=lambda status: all(( *( - wait_for_unit_status(f"{INTEGRATOR_APP_NAME}1", unit_name, "blocked") + wait_for_unit_status(f"{INTEGRATOR_APP_NAME}1", unit_name, "blocked")(status) for unit_name in status.get_units(f"{INTEGRATOR_APP_NAME}1") ), *( - wait_for_unit_status(f"{INTEGRATOR_APP_NAME}2", unit_name, "blocked") + wait_for_unit_status(f"{INTEGRATOR_APP_NAME}2", unit_name, "blocked")(status) for unit_name in status.get_units(f"{INTEGRATOR_APP_NAME}2") ), )), From b1c033ecf2086c34a75c80d3fbdaadb9403beff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Luis=20Cano=20Rodr=C3=ADguez?= Date: Thu, 23 Apr 2026 15:48:16 +0200 Subject: [PATCH 2/2] Empty commit