From fb3774645543273f3522012d757a6490d1af239e Mon Sep 17 00:00:00 2001 From: Dario Faccin Date: Thu, 16 Nov 2023 16:45:52 +0100 Subject: [PATCH] fix: go into blocked status when database relation is removed --- src/charm.py | 9 +++++ tests/integration/test_integration.py | 26 ++++++++++++++ tests/unit/test_charm.py | 49 ++++++++++++++++++++------- 3 files changed, 71 insertions(+), 13 deletions(-) diff --git a/src/charm.py b/src/charm.py index 5854866..2103dc9 100755 --- a/src/charm.py +++ b/src/charm.py @@ -88,6 +88,7 @@ def __init__(self, *args): self.framework.observe(self.on.install, self._on_install) self.framework.observe(self.on.smf_pebble_ready, self._configure_sdcore_smf) self.framework.observe(self.on.database_relation_joined, self._configure_sdcore_smf) + self.framework.observe(self.on.database_relation_broken, self._on_database_relation_broken) self.framework.observe(self._database.on.database_created, self._configure_sdcore_smf) self.framework.observe(self.on.fiveg_nrf_relation_joined, self._configure_sdcore_smf) self.framework.observe(self._nrf_requires.on.nrf_available, self._configure_sdcore_smf) @@ -187,6 +188,14 @@ def _on_nrf_broken(self, event: EventBase) -> None: """ self.unit.status = BlockedStatus("Waiting for fiveg_nrf relation") + 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 _on_certificates_relation_created(self, event: EventBase) -> None: """Generates Private key.""" if not self._container.can_connect(): diff --git a/tests/integration/test_integration.py b/tests/integration/test_integration.py index 2aeaf13..c4ea1b7 100644 --- a/tests/integration/test_integration.py +++ b/tests/integration/test_integration.py @@ -164,3 +164,29 @@ async def test_when_scale_app_beyond_1_then_only_one_unit_is_active( async def test_remove_app(ops_test: OpsTest, build_and_deploy): assert ops_test.model await ops_test.model.remove_application(APP_NAME, block_until_done=True) + + +@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 ops_test.model.deploy( + DATABASE_APP_NAME, + application_name=DATABASE_APP_NAME, + channel="5/edge", + trust=True, + ) + 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) diff --git a/tests/unit/test_charm.py b/tests/unit/test_charm.py index 407ce3f..a5874e6 100644 --- a/tests/unit/test_charm.py +++ b/tests/unit/test_charm.py @@ -82,7 +82,7 @@ def _create_nrf_relation(self) -> int: self.harness.add_relation_unit(relation_id=relation_id, remote_unit_name="nrf-operator/0") return relation_id - def _database_is_available(self) -> str: + def _create_database_relation_and_populate_data(self) -> int: database_url = "http://6.5.6.5" database_username = "rock" database_password = "paper" @@ -96,7 +96,7 @@ def _database_is_available(self) -> str: "uris": "".join([database_url]), }, ) - return database_url + return database_relation_id def test_given_container_cant_connect_when_on_install_then_status_is_waiting( self, @@ -184,7 +184,7 @@ def test_given_certificates_relation_not_created_when_configure_sdcore_smf_is_ca def test_given_smf_charm_in_active_status_when_nrf_relation_breaks_then_status_is_blocked( self, patch_exists, patch_check_output, patch_nrf_url ): - self._database_is_available() + self._create_database_relation_and_populate_data() nrf_relation_id = self._create_nrf_relation() self.harness.set_can_connect(container=self.container_name, val=True) patch_exists.return_value = True @@ -199,6 +199,29 @@ def test_given_smf_charm_in_active_status_when_nrf_relation_breaks_then_status_i BlockedStatus("Waiting for fiveg_nrf relation"), ) + @patch("ops.model.Container.pull", new=Mock) + @patch("charms.sdcore_nrf.v0.fiveg_nrf.NRFRequires.nrf_url") + @patch("ops.model.Container.push", new=Mock) + @patch("charm.check_output") + @patch("ops.model.Container.exists") + def test_given_smf_charm_in_active_status_when_database_relation_breaks_then_status_is_blocked( + self, patch_exists, patch_check_output, patch_nrf_url + ): + database_relation_id = self._create_database_relation_and_populate_data() + self._create_nrf_relation() + self.harness.set_can_connect(container=self.container_name, val=True) + patch_exists.return_value = True + patch_check_output.return_value = b"1.1.1.1" + patch_nrf_url.return_value = "http://nrf.com:8080" + self.harness.container_pebble_ready("smf") + + self.harness.remove_relation(database_relation_id) + + self.assertEqual( + self.harness.model.unit.status, + BlockedStatus("Waiting for database relation"), + ) + def test_given_container_cant_connect_when_configure_sdcore_smf_is_called_is_called_then_status_is_waiting( # noqa: E501 self, ): @@ -235,7 +258,7 @@ def test_given_database_relation_not_available_when_configure_sdcore_smf_is_call def test_given_nrf_is_not_available_when_configure_sdcore_smf_is_called_then_status_is_waiting( # noqa: E501 self, ): - self._database_is_available() + self._create_database_relation_and_populate_data() self._create_nrf_relation() self.harness.add_relation( relation_name="certificates", remote_app="tls-certificates-operator" @@ -258,7 +281,7 @@ def test_given_ue_config_file_is_not_written_when_configure_sdcore_smf_is_called patch_nrf_url, patch_check_output, ): - self._database_is_available() + self._create_database_relation_and_populate_data() self._create_nrf_relation() self.harness.add_relation( relation_name="certificates", remote_app="tls-certificates-operator" @@ -283,7 +306,7 @@ def test_given_ue_config_file_is_not_written_when_configure_sdcore_smf_is_called def test_given_storage_is_not_attached_when_configure_sdcore_smf_is_called_then_status_is_waiting( # noqa: E501 self, patch_push, patch_exists, patch_nrf_url ): - self._database_is_available() + self._create_database_relation_and_populate_data() self._create_nrf_relation() self.harness.add_relation( relation_name="certificates", remote_app="tls-certificates-operator" @@ -308,7 +331,7 @@ def test_given_ip_not_available_when_configure_then_status_is_waiting( patch_check_output, patch_nrf_url, ): - self._database_is_available() + self._create_database_relation_and_populate_data() self._create_nrf_relation() self.harness.add_relation( relation_name="certificates", remote_app="tls-certificates-operator" @@ -336,7 +359,7 @@ def test_given_certificate_is_not_stored_when_configure_sdcore_smf_then_status_i ): self.harness.set_can_connect(container=self.container_name, val=True) patch_nrf_url.return_value = "http://nrf.com:8080" - self._database_is_available() + self._create_database_relation_and_populate_data() self._create_nrf_relation() self.harness.add_relation( relation_name="certificates", remote_app="tls-certificates-operator" @@ -363,7 +386,7 @@ def test_given_config_files_and_relations_are_created_when_configure_sdcore_smf_ patch_check_output, patch_nrf_url, ): - self._database_is_available() + self._create_database_relation_and_populate_data() self._create_nrf_relation() self.harness.add_relation( relation_name="certificates", remote_app="tls-certificates-operator" @@ -395,7 +418,7 @@ def test_given_nrf_is_available_when_database_is_created_then_config_file_is_wri ): pod_ip = "1.1.1.1" patch_check_output.return_value = pod_ip.encode() - self._database_is_available() + self._create_database_relation_and_populate_data() self._create_nrf_relation() self.harness.add_relation( relation_name="certificates", remote_app="tls-certificates-operator" @@ -431,7 +454,7 @@ def test_given_config_file_exists_and_is_not_changed_when_configure_smf_then_con patch_pull.return_value = StringIO(self._read_file("tests/unit/expected_smfcfg.yaml")) patch_exists.side_effect = [True, False] patch_nrf_url.return_value = "http://nrf.com:8080" - self._database_is_available() + self._create_database_relation_and_populate_data() self._create_nrf_relation() self.harness.add_relation( relation_name="certificates", remote_app="tls-certificates-operator" @@ -459,7 +482,7 @@ def test_given_config_file_exists_and_is_changed_when_configure_smf_then_config_ pod_ip = "1.1.1.1" patch_check_output.return_value = pod_ip.encode() patch_pull.return_value = StringIO("super different config file content") - self._database_is_available() + self._create_database_relation_and_populate_data() self._create_nrf_relation() self.harness.add_relation( relation_name="certificates", remote_app="tls-certificates-operator" @@ -487,7 +510,7 @@ def test_given_config_files_and_relations_are_created_when_configure_sdcore_smf_ ): pod_ip = "1.1.1.1" patch_check_output.return_value = pod_ip.encode() - self._database_is_available() + self._create_database_relation_and_populate_data() self._create_nrf_relation() self.harness.add_relation( relation_name="certificates", remote_app="tls-certificates-operator"