diff --git a/src/charm.py b/src/charm.py index 8d39813..faba7d9 100755 --- a/src/charm.py +++ b/src/charm.py @@ -91,6 +91,7 @@ def __init__(self, *args): self._sdcore_management = SdcoreManagementProvides(self, SDCORE_MANAGEMENT_RELATION_NAME) self.framework.observe(self.on.webui_pebble_ready, self._on_webui_pebble_ready) self.framework.observe(self.on.database_relation_joined, self._on_webui_pebble_ready) + self.framework.observe(self.on.database_relation_broken, self._on_database_relation_broken) self.framework.observe(self._database.on.database_created, self._on_database_created) self.framework.observe(self._database.on.endpoints_changed, self._on_database_created) self.framework.observe( @@ -165,6 +166,14 @@ def _publish_sdcore_management_url(self, event: EventBase): management_url=self._get_webui_endpoint_url(), ) + def _on_database_relation_broken(self, event: EventBase) -> None: + """Event handler for database relation broken. + + Args: + event: Juju event + """ + self.unit.status = BlockedStatus("Waiting for database relation") + def _write_config_file(self, content: str) -> None: """Writes configuration file based on provided content. diff --git a/tests/integration/test_integration.py b/tests/integration/test_integration.py index 0b261ab..1562cca 100644 --- a/tests/integration/test_integration.py +++ b/tests/integration/test_integration.py @@ -73,6 +73,27 @@ async def test_relate_and_wait_for_active_status( ) +@pytest.mark.skip( + reason="Bug in MongoDB: https://github.com/canonical/mongodb-k8s-operator/issues/218" +) +@pytest.mark.abort_on_fail +async def test_remove_database_and_wait_for_blocked_status(ops_test: OpsTest, build_and_deploy): + assert ops_test.model + await ops_test.model.remove_application(DATABASE_APP_NAME, block_until_done=True) + await ops_test.model.wait_for_idle(apps=[APP_NAME], status="blocked", timeout=60) + + +@pytest.mark.skip( + reason="Bug in MongoDB: https://github.com/canonical/mongodb-k8s-operator/issues/218" +) +@pytest.mark.abort_on_fail +async def test_restore_database_and_wait_for_active_status(ops_test: OpsTest, build_and_deploy): + assert ops_test.model + await _deploy_database(ops_test) + await ops_test.model.integrate(relation1=APP_NAME, relation2=DATABASE_APP_NAME) + await ops_test.model.wait_for_idle(apps=[APP_NAME], status="active", timeout=1000) + + @pytest.mark.abort_on_fail async def test_when_scale_app_beyond_1_then_only_one_unit_is_active( ops_test: OpsTest, build_and_deploy diff --git a/tests/unit/test_charm.py b/tests/unit/test_charm.py index 178fc21..361601f 100644 --- a/tests/unit/test_charm.py +++ b/tests/unit/test_charm.py @@ -6,7 +6,7 @@ from unittest.mock import Mock, patch from ops import testing -from ops.model import ActiveStatus, WaitingStatus +from ops.model import ActiveStatus, BlockedStatus, WaitingStatus from charm import WebuiOperatorCharm @@ -38,7 +38,7 @@ def setUp(self): self.addCleanup(self.harness.cleanup) self.harness.begin() - def _database_is_available(self) -> str: + def _create_database_relation_and_populate_data(self) -> int: database_url = "http://6.6.6.6" database_username = "banana" database_password = "pizza" @@ -55,7 +55,17 @@ def _database_is_available(self) -> str: "uris": database_url, }, ) - return database_url + return database_relation_id + + def test_given_database_relation_not_created_when_pebble_ready_then_status_is_blocked( + self, + ): + self.harness.set_can_connect(container="webui", val=True) + self.harness.container_pebble_ready("webui") + self.assertEqual( + self.harness.model.unit.status, + BlockedStatus("Waiting for database relation to be created"), + ) @patch("ops.model.Container.push") @patch("ops.model.Container.exists") @@ -105,7 +115,7 @@ def test_given_config_file_is_written_when_pebble_ready_then_pebble_plan_is_appl ): patch_exists.return_value = True - self._database_is_available() + self._create_database_relation_and_populate_data() self.harness.container_pebble_ready(container_name="webui") @@ -136,19 +146,33 @@ def test_given_config_file_is_written_when_pebble_ready_then_status_is_active( ): patch_exists.return_value = True - self._database_is_available() + self._create_database_relation_and_populate_data() self.harness.container_pebble_ready("webui") self.assertEqual(self.harness.model.unit.status, ActiveStatus()) + @patch("ops.model.Container.exists") + def test_given_webui_charm_in_active_state_when_database_relation_breaks_then_status_is_blocked( # noqa: E501 + self, patch_exists + ): + patch_exists.return_value = True + database_relation_id = self._create_database_relation_and_populate_data() + self.harness.container_pebble_ready("webui") + + self.harness.remove_relation(database_relation_id) + + self.assertEqual( + self.harness.model.unit.status, BlockedStatus("Waiting for database relation") + ) + @patch("ops.model.Container.exists") def test_given_config_file_is_not_written_when_pebble_ready_then_status_is_waiting( self, patch_exists ): patch_exists.return_value = False - self._database_is_available() + self._create_database_relation_and_populate_data() self.harness.container_pebble_ready("webui")