From 407406712540a3b9da7b61a778136d61ffc0d351 Mon Sep 17 00:00:00 2001 From: gatici Date: Thu, 15 Feb 2024 15:38:18 +0300 Subject: [PATCH] Store authentication keys in a separate database Signed-off-by: gatici --- README.md | 3 +- metadata.yaml | 4 +- src/charm.py | 175 ++++++++++++----- src/templates/udrcfg.yaml.j2 | 6 +- terraform/README.md | 4 +- terraform/outputs.tf | 11 +- tests/integration/test_integration.py | 42 ++-- tests/unit/resources/expected_udrcfg.yaml | 4 +- tests/unit/test_charm.py | 228 +++++++++++++++------- 9 files changed, 336 insertions(+), 141 deletions(-) diff --git a/README.md b/README.md index 3a5c834..5fca47a 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,8 @@ juju deploy sdcore-nrf-k8s --channel=edge juju deploy sdcore-udr-k8s --channel=edge juju deploy self-signed-certificates --channel=beta juju integrate mongodb-k8s sdcore-nrf-k8s -juju integrate mongodb-k8s sdcore-udr-k8s:database +juju integrate mongodb-k8s sdcore-udr-k8s:common_database +juju integrate mongodb-k8s sdcore-udr-k8s:auth_database juju integrate sdcore-nrf-k8s:certificates self-signed-certificates:certificates juju integrate sdcore-nrf-k8s:fiveg_nrf sdcore-udr-k8s:fiveg_nrf juju integrate sdcore-udr-k8s:certificates self-signed-certificates:certificates diff --git a/metadata.yaml b/metadata.yaml index c499af2..525a177 100644 --- a/metadata.yaml +++ b/metadata.yaml @@ -18,7 +18,9 @@ containers: location: /support/TLS requires: - database: + common_database: + interface: mongodb_client + auth_database: interface: mongodb_client fiveg_nrf: interface: fiveg_nrf diff --git a/src/charm.py b/src/charm.py index 3120b17..9c67859 100755 --- a/src/charm.py +++ b/src/charm.py @@ -19,15 +19,20 @@ generate_private_key, ) from jinja2 import Environment, FileSystemLoader +from ops import ActiveStatus, BlockedStatus, RelationBrokenEvent, WaitingStatus from ops.charm import CharmBase, EventBase from ops.main import main -from ops.model import ActiveStatus, BlockedStatus, WaitingStatus from ops.pebble import Layer, PathError logger = logging.getLogger(__name__) BASE_CONFIG_PATH = "/free5gc/config" -DEFAULT_DATABASE_NAME = "free5gc" +COMMON_DATABASE_NAME = "free5gc" +AUTH_DATABASE_NAME = "authentication" +COMMON_DATABASE_RELATION_NAME = "common_database" +AUTH_DATABASE_RELATION_NAME = "auth_database" +NRF_RELATION_NAME = "fiveg_nrf" +TLS_RELATION_NAME = "certificates" UDR_CONFIG_FILE_NAME = "udrcfg.yaml" UDR_SBI_PORT = 29504 CERTS_DIR_PATH = "/support/TLS" # Certificate paths are hardcoded in UDR code @@ -44,17 +49,27 @@ def __init__(self, *args): super().__init__(*args) self._container_name = self._service_name = "udr" self._container = self.unit.get_container(self._container_name) - self._nrf = NRFRequires(charm=self, relation_name="fiveg_nrf") - self._database = DatabaseRequires( - self, relation_name="database", database_name=DEFAULT_DATABASE_NAME + self._nrf = NRFRequires(charm=self, relation_name=NRF_RELATION_NAME) + self._common_database = DatabaseRequires( + self, relation_name=COMMON_DATABASE_RELATION_NAME, database_name=COMMON_DATABASE_NAME + ) + self._auth_database = DatabaseRequires( + self, relation_name=AUTH_DATABASE_RELATION_NAME, database_name=AUTH_DATABASE_NAME ) self.unit.set_ports(UDR_SBI_PORT) - self._certificates = TLSCertificatesRequiresV3(self, "certificates") + self._certificates = TLSCertificatesRequiresV3(self, TLS_RELATION_NAME) self.framework.observe(self.on.udr_pebble_ready, self._configure_udr) - self.framework.observe(self.on.database_relation_joined, self._configure_udr) - self.framework.observe(self.on.database_relation_broken, self._on_database_relation_broken) - self.framework.observe(self._database.on.database_created, self._configure_udr) + self.framework.observe(self.on.common_database_relation_joined, self._configure_udr) + self.framework.observe(self.on.auth_database_relation_joined, self._configure_udr) + self.framework.observe( + self.on.common_database_relation_broken, self._on_common_database_relation_broken + ) + self.framework.observe( + self.on.auth_database_relation_broken, self._on_auth_database_relation_broken + ) + self.framework.observe(self._common_database.on.database_created, self._configure_udr) + self.framework.observe(self._auth_database.on.database_created, self._configure_udr) self.framework.observe(self.on.fiveg_nrf_relation_joined, self._configure_udr) self.framework.observe(self._nrf.on.nrf_available, self._configure_udr) self.framework.observe(self._nrf.on.nrf_broken, self._on_nrf_broken) @@ -74,6 +89,38 @@ def __init__(self, *args): self._certificates.on.certificate_expiring, self._on_certificate_expiring ) + def ready_to_configure(self) -> bool: + """Returns whether the preconditions are met to proceed with configuration.""" + for relation in [ + COMMON_DATABASE_RELATION_NAME, + AUTH_DATABASE_RELATION_NAME, + NRF_RELATION_NAME, + TLS_RELATION_NAME, + ]: + if not self._relation_created(relation): + self.unit.status = BlockedStatus( + f"Waiting for the {relation} relation to be created" + ) + return False + if not self._common_database_is_available(): + self.unit.status = WaitingStatus("Waiting for the common database to be available") + return False + if not self._auth_database_is_available(): + self.unit.status = WaitingStatus( + "Waiting for the authentication database to be available" + ) + return False + if not self._get_common_database_url(): + self.unit.status = WaitingStatus("Waiting for the common database url to be available") + return False + if not self._get_auth_database_url(): + self.unit.status = WaitingStatus("Waiting for the auth database url to be available") + return False + if not self._nrf_is_available(): + self.unit.status = WaitingStatus("Waiting for the NRF to be available") + return False + return True + def _configure_udr(self, event: EventBase) -> None: """Main callback function of the UDR operator. @@ -83,21 +130,7 @@ def _configure_udr(self, event: EventBase) -> None: Args: event: Juju event """ - for relation in ["database", "fiveg_nrf", "certificates"]: - if not self._relation_created(relation): - self.unit.status = BlockedStatus( - f"Waiting for the `{relation}` relation to be created" - ) - return - if not self._database_is_available(): - self.unit.status = WaitingStatus("Waiting for the database to be available") - return - if not self._get_database_data(): - self.unit.status = WaitingStatus("Waiting for the database data to be available") - event.defer() - return - if not self._nrf_is_available(): - self.unit.status = WaitingStatus("Waiting for the NRF to be available") + if not self.ready_to_configure(): return if not self._container.can_connect(): self.unit.status = WaitingStatus("Waiting for the container to be ready") @@ -118,7 +151,7 @@ def _configure_udr(self, event: EventBase) -> None: self._configure_udr_service() self.unit.status = ActiveStatus() - def _on_nrf_broken(self, event: EventBase) -> None: + def _on_nrf_broken(self, event: RelationBrokenEvent) -> None: """Event handler for NRF relation broken. Args: @@ -126,13 +159,25 @@ 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. + def _on_common_database_relation_broken(self, event: RelationBrokenEvent) -> None: + """Event handler for common database relation broken. + + Args: + event: Juju event + """ + if not self.model.relations[COMMON_DATABASE_RELATION_NAME]: + self.unit.status = BlockedStatus( + f"Waiting for {COMMON_DATABASE_RELATION_NAME} relation" + ) + + def _on_auth_database_relation_broken(self, event: RelationBrokenEvent) -> None: + """Event handler for auth database relation broken. Args: event: Juju event """ - self.unit.status = BlockedStatus("Waiting for database relation") + if not self.model.relations[AUTH_DATABASE_RELATION_NAME]: + self.unit.status = BlockedStatus(f"Waiting for {AUTH_DATABASE_RELATION_NAME} relation") def _on_certificates_relation_created(self, event: EventBase) -> None: """Generates Private key.""" @@ -141,7 +186,7 @@ def _on_certificates_relation_created(self, event: EventBase) -> None: return self._generate_private_key() - def _on_certificates_relation_broken(self, event: EventBase) -> None: + def _on_certificates_relation_broken(self, event: RelationBrokenEvent) -> None: """Deletes TLS related artifacts and reconfigures workload.""" if not self._container.can_connect(): event.defer() @@ -280,8 +325,10 @@ def _generate_udr_config_file(self) -> None: content = self._render_config_file( udr_ip_address=_get_pod_ip(), # type: ignore[arg-type] udr_sbi_port=UDR_SBI_PORT, - default_database_name=DEFAULT_DATABASE_NAME, - default_database_url=self._get_database_data()["uris"].split(",")[0], + common_database_name=COMMON_DATABASE_NAME, + common_database_url=self._get_common_database_url(), + auth_database_name=AUTH_DATABASE_NAME, + auth_database_url=self._get_auth_database_url(), nrf_url=self._nrf.nrf_url, scheme="https", ) @@ -311,8 +358,10 @@ def _render_config_file( *, udr_ip_address: str, udr_sbi_port: int, - default_database_name: str, - default_database_url: str, + common_database_name: str, + auth_database_name: str, + common_database_url: str, + auth_database_url: str, nrf_url: str, scheme: str, ) -> str: @@ -321,8 +370,10 @@ def _render_config_file( Args: udr_ip_address (str): UDR IP address. udr_sbi_port (str): UDR SBI port. - default_database_name (str): Database name. - default_database_url (str): Database URL. + common_database_name (str): Commmon Database name. + auth_database_name (str): Database name to store authentication keys. + common_database_url (str): Common Database URL. + auth_database_url (str): Authentication Database URL. nrf_url (str): NRF URL. scheme (str): SBI interface scheme ("http" or "https") @@ -334,8 +385,10 @@ def _render_config_file( return template.render( udr_ip_address=udr_ip_address, udr_sbi_port=udr_sbi_port, - default_database_name=default_database_name, - default_database_url=default_database_url, + common_database_name=common_database_name, + common_database_url=common_database_url, + auth_database_name=auth_database_name, + auth_database_url=auth_database_url, nrf_url=nrf_url, scheme=scheme, ) @@ -364,15 +417,35 @@ def _push_udr_config_file_to_workload(self, content: str) -> None: ) logger.info(f"Config file {UDR_CONFIG_FILE_NAME} pushed to workload.") - def _get_database_data(self) -> dict: - """Returns the database data. + def _get_common_database_url(self) -> str: + """Returns the common database URL. Returns: - dict: The database data. + str: The common database URL. """ - if not self._database_is_available(): - raise RuntimeError(f"Database `{DEFAULT_DATABASE_NAME}` is not available") - return self._database.fetch_relation_data()[self._database.relations[0].id] + if not self._common_database_is_available(): + raise RuntimeError(f"Database `{COMMON_DATABASE_NAME}` is not available") + uris = self._common_database.fetch_relation_data()[ + self._common_database.relations[0].id + ].get("uris") + if uris: + return uris.split(",")[0] + return "" + + def _get_auth_database_url(self) -> str: + """Returns the authentication database URL. + + Returns: + str: The authentication database URL. + """ + if not self._auth_database_is_available(): + raise RuntimeError(f"Database `{AUTH_DATABASE_NAME}` is not available") + uris = self._auth_database.fetch_relation_data()[self._auth_database.relations[0].id].get( + "uris" + ) + if uris: + return uris.split(",")[0] + return "" def _nrf_is_available(self) -> bool: """Returns whether the NRF endpoint is available. @@ -382,13 +455,21 @@ def _nrf_is_available(self) -> bool: """ return bool(self._nrf.nrf_url) - def _database_is_available(self) -> bool: - """Returns whether database relation is available. + def _common_database_is_available(self) -> bool: + """Returns whether common database relation is available. + + Returns: + bool: Whether common database relation is available. + """ + return bool(self._common_database.is_resource_created()) + + def _auth_database_is_available(self) -> bool: + """Returns whether authentication database relation is available. Returns: - bool: Whether database relation is available. + bool: Whether authentication database relation is available. """ - return bool(self._database.is_resource_created()) + return bool(self._auth_database.is_resource_created()) @property def _pebble_layer(self) -> Layer: diff --git a/src/templates/udrcfg.yaml.j2 b/src/templates/udrcfg.yaml.j2 index 0e7ebe5..0f839b6 100644 --- a/src/templates/udrcfg.yaml.j2 +++ b/src/templates/udrcfg.yaml.j2 @@ -9,8 +9,10 @@ configuration: bindingIPv4: 0.0.0.0 port: {{ udr_sbi_port }} mongodb: - name: {{ default_database_name }} - url: {{ default_database_url }} + name: {{ common_database_name }} + url: {{ common_database_url }} + authKeysDbName: {{ auth_database_name }} + authUrl: {{ auth_database_url }} nrfUri: {{ nrf_url }} # the kind of log output diff --git a/terraform/README.md b/terraform/README.md index ff16a2c..c0e7a95 100644 --- a/terraform/README.md +++ b/terraform/README.md @@ -30,12 +30,12 @@ module "sdcore-udr-k8s" { Create the integrations, for instance: ```text -resource "juju_integration" "udr-db" { +resource "juju_integration" "udr-common-db" { model = var.model_name application { name = module.udr.app_name - endpoint = module.udr.database_endpoint + endpoint = module.udr.commmon_database_endpoint } application { diff --git a/terraform/outputs.tf b/terraform/outputs.tf index 88daa91..1538c26 100644 --- a/terraform/outputs.tf +++ b/terraform/outputs.tf @@ -6,9 +6,14 @@ output "app_name" { value = juju_application.sdcore-udr-k8s.name } -output "database_endpoint" { - description = "Name of the endpoint to integrate with MongoDB using mongodb_client interface." - value = "database" +output "common_database_endpoint" { + description = "Name of the endpoint to integrate with MongoDB for common_database using mongodb_client interface." + value = "common_database" +} + +output "auth_database_endpoint" { + description = "Name of the endpoint to integrate with MongoDB for auth_database using mongodb_client interface." + value = "auth_database" } output "fiveg_nrf_endpoint" { diff --git a/tests/integration/test_integration.py b/tests/integration/test_integration.py index 4520499..fbd06fc 100644 --- a/tests/integration/test_integration.py +++ b/tests/integration/test_integration.py @@ -17,6 +17,10 @@ DB_APPLICATION_NAME = "mongodb-k8s" NRF_APPLICATION_NAME = "sdcore-nrf-k8s" TLS_PROVIDER_CHARM_NAME = "self-signed-certificates" +COMMON_DATABASE_RELATION_NAME = "common_database" +AUTH_DATABASE_RELATION_NAME = "auth_database" +NRF_RELATION_NAME = "fiveg_nrf" +TLS_RELATION_NAME = "certificates" class TestUDROperatorCharm: @@ -65,10 +69,10 @@ async def _deploy_sdcore_nrf_operator(ops_test: OpsTest): channel="edge", trust=True, ) - await ops_test.model.add_relation( # type: ignore[union-attr] + await ops_test.model.integrate( # type: ignore[union-attr] relation1=DB_APPLICATION_NAME, relation2=NRF_APPLICATION_NAME ) - await ops_test.model.add_relation( # type: ignore[union-attr] + await ops_test.model.integrate( # type: ignore[union-attr] relation1=TLS_PROVIDER_CHARM_NAME, relation2=NRF_APPLICATION_NAME ) @@ -80,14 +84,19 @@ async def test_wait_for_blocked_status(self, ops_test: OpsTest, setup, build_and async def test_relate_and_wait_for_idle( self, ops_test: OpsTest, setup, build_and_deploy_charm ): - await ops_test.model.add_relation( # type: ignore[union-attr] - relation1=f"{APPLICATION_NAME}:database", relation2=DB_APPLICATION_NAME + await ops_test.model.integrate( # type: ignore[union-attr] + relation1=f"{APPLICATION_NAME}:{COMMON_DATABASE_RELATION_NAME}", + relation2=DB_APPLICATION_NAME, ) - await ops_test.model.add_relation( # type: ignore[union-attr] - relation1=f"{APPLICATION_NAME}:fiveg_nrf", relation2=NRF_APPLICATION_NAME + await ops_test.model.integrate( # type: ignore[union-attr] + relation1=f"{APPLICATION_NAME}:{AUTH_DATABASE_RELATION_NAME}", + relation2=DB_APPLICATION_NAME, ) - await ops_test.model.add_relation( # type: ignore[union-attr] - relation1=f"{APPLICATION_NAME}:certificates", + await ops_test.model.integrate( # type: ignore[union-attr] + relation1=f"{APPLICATION_NAME}:{NRF_RELATION_NAME}", relation2=NRF_APPLICATION_NAME + ) + await ops_test.model.integrate( # type: ignore[union-attr] + relation1=f"{APPLICATION_NAME}:{TLS_RELATION_NAME}", relation2=f"{TLS_PROVIDER_CHARM_NAME}:certificates", ) await ops_test.model.wait_for_idle(apps=[APPLICATION_NAME], status="active", timeout=1000) # type: ignore[union-attr] # noqa: E501 @@ -109,11 +118,11 @@ async def test_restore_nrf_and_wait_for_active_status( channel="edge", trust=True, ) - await ops_test.model.add_relation( # type: ignore[union-attr] + await ops_test.model.integrate( # type: ignore[union-attr] relation1=f"{NRF_APPLICATION_NAME}:database", relation2=DB_APPLICATION_NAME ) - await ops_test.model.add_relation(relation1=APPLICATION_NAME, relation2=NRF_APPLICATION_NAME) # type: ignore[union-attr] # noqa: E501 - await ops_test.model.add_relation(relation1=TLS_PROVIDER_CHARM_NAME, relation2=NRF_APPLICATION_NAME) # type: ignore[union-attr] # noqa: E501 + await ops_test.model.integrate(relation1=APPLICATION_NAME, relation2=NRF_APPLICATION_NAME) # type: ignore[union-attr] # noqa: E501 + await ops_test.model.integrate(relation1=TLS_PROVIDER_CHARM_NAME, relation2=NRF_APPLICATION_NAME) # type: ignore[union-attr] # noqa: E501 await ops_test.model.wait_for_idle(apps=[APPLICATION_NAME], status="active", timeout=300) # type: ignore[union-attr] # noqa: E501 @pytest.mark.abort_on_fail @@ -133,7 +142,7 @@ async def test_restore_tls_and_wait_for_active_status( channel="beta", trust=True, ) - await ops_test.model.add_relation( # type: ignore[union-attr] + await ops_test.model.integrate( # type: ignore[union-attr] relation1=APPLICATION_NAME, relation2=TLS_PROVIDER_CHARM_NAME ) await ops_test.model.wait_for_idle(apps=[APPLICATION_NAME], status="active", timeout=1000) # type: ignore[union-attr] # noqa: E501 @@ -161,5 +170,12 @@ async def test_restore_database_and_wait_for_active_status(ops_test: OpsTest, bu channel="5/edge", trust=True, ) - await ops_test.model.integrate(relation1=APPLICATION_NAME, relation2=DB_APPLICATION_NAME) + await ops_test.model.integrate( + relation1=f"{NRF_APPLICATION_NAME}:{COMMON_DATABASE_RELATION_NAME}", + relation2=DB_APPLICATION_NAME, + ) + await ops_test.model.integrate( + relation1=f"{NRF_APPLICATION_NAME}:{AUTH_DATABASE_RELATION_NAME}", + relation2=DB_APPLICATION_NAME, + ) await ops_test.model.wait_for_idle(apps=[APPLICATION_NAME], status="active", timeout=1000) diff --git a/tests/unit/resources/expected_udrcfg.yaml b/tests/unit/resources/expected_udrcfg.yaml index 5582862..e1a85ea 100644 --- a/tests/unit/resources/expected_udrcfg.yaml +++ b/tests/unit/resources/expected_udrcfg.yaml @@ -10,7 +10,9 @@ configuration: port: 29504 mongodb: name: free5gc - url: http://dummy + url: 1.9.11.4:1234 + authKeysDbName: authentication + authUrl: 1.9.11.4:1234 nrfUri: http://nrf:8081 # the kind of log output diff --git a/tests/unit/test_charm.py b/tests/unit/test_charm.py index 3d76fbb..c24f885 100644 --- a/tests/unit/test_charm.py +++ b/tests/unit/test_charm.py @@ -10,6 +10,11 @@ from charm import UDROperatorCharm +COMMON_DATABASE_RELATION_NAME = "common_database" +AUTH_DATABASE_RELATION_NAME = "auth_database" +NRF_RELATION_NAME = "fiveg_nrf" +TLS_RELATION_NAME = "certificates" + TEST_PEBBLE_LAYER = { "services": { "udr": { @@ -53,47 +58,101 @@ def _read_file(path: str) -> str: content = f.read() return content - def _database_is_available(self) -> int: - database_relation_id = self.harness.add_relation("database", "mongodb") + def _create_common_database_relation_and_populate_data(self) -> int: + common_database_url = "1.9.11.4:1234" + common_database_username = "banana" + common_database_password = "pizza" + common_database_relation_id = self.harness.add_relation( + COMMON_DATABASE_RELATION_NAME, "mongodb" + ) self.harness.add_relation_unit( - relation_id=database_relation_id, remote_unit_name="mongodb/0" + relation_id=common_database_relation_id, remote_unit_name="mongodb/0" ) self.harness.update_relation_data( - relation_id=database_relation_id, + relation_id=common_database_relation_id, app_or_unit="mongodb", key_values={ - "username": "dummy", - "password": "dummy", - "uris": "http://dummy", + "username": common_database_username, + "password": common_database_password, + "uris": common_database_url, }, ) - return database_relation_id + return common_database_relation_id - def test_given_database_relation_not_created_when_pebble_ready_then_status_is_blocked(self): - self.harness.add_relation(relation_name="fiveg_nrf", remote_app="some_nrf_app") + def _create_auth_database_relation_and_populate_data(self) -> int: + auth_database_url = "1.9.11.4:1234" + auth_database_username = "apple" + auth_database_password = "hamburger" + auth_database_relation_id = self.harness.add_relation( + AUTH_DATABASE_RELATION_NAME, "mongodb" + ) + self.harness.add_relation_unit( + relation_id=auth_database_relation_id, remote_unit_name="mongodb/0" + ) + self.harness.update_relation_data( + relation_id=auth_database_relation_id, + app_or_unit="mongodb", + key_values={ + "username": auth_database_username, + "password": auth_database_password, + "uris": auth_database_url, + }, + ) + return auth_database_relation_id + + def test_given_commmon_database_relation_not_created_when_pebble_ready_then_status_is_blocked( + self, + ): + self.harness.add_relation(relation_name=NRF_RELATION_NAME, remote_app="some_nrf_app") self.harness.container_pebble_ready("udr") self.assertEqual( self.harness.model.unit.status, - BlockedStatus("Waiting for the `database` relation to be created"), + BlockedStatus("Waiting for the common_database relation to be created"), + ) + + def test_given_auth_database_relation_not_created_when_pebble_ready_then_status_is_blocked( + self, + ): + self.harness.add_relation(relation_name=NRF_RELATION_NAME, remote_app="some_nrf_app") + self.harness.add_relation( + relation_name=COMMON_DATABASE_RELATION_NAME, remote_app="mongodb" + ) + self.harness.add_relation( + relation_name="certificates", remote_app="ls-certificates-operator" + ) + self.harness.container_pebble_ready("udr") + self.assertEqual( + self.harness.model.unit.status, + BlockedStatus("Waiting for the auth_database relation to be created"), ) def test_given_fiveg_nrf_relation_not_created_when_pebble_ready_then_status_is_blocked(self): - self.harness.add_relation(relation_name="database", remote_app="some_db_app") + self.harness.add_relation( + relation_name=COMMON_DATABASE_RELATION_NAME, remote_app="some_db_app" + ) + self.harness.add_relation( + relation_name=AUTH_DATABASE_RELATION_NAME, remote_app="some_db_app" + ) self.harness.container_pebble_ready("udr") self.assertEqual( self.harness.model.unit.status, - BlockedStatus("Waiting for the `fiveg_nrf` relation to be created"), + BlockedStatus("Waiting for the fiveg_nrf relation to be created"), ) def test_given_certificates_relation_not_created_when_pebble_ready_then_status_is_blocked( self, ): - self.harness.add_relation(relation_name="database", remote_app="some_db_app") - self.harness.add_relation(relation_name="fiveg_nrf", remote_app="some_nrf_app") + self.harness.add_relation( + relation_name=COMMON_DATABASE_RELATION_NAME, remote_app="some_db_app" + ) + self.harness.add_relation( + relation_name=AUTH_DATABASE_RELATION_NAME, remote_app="some_db_app" + ) + self.harness.add_relation(relation_name=NRF_RELATION_NAME, remote_app="some_nrf_app") self.harness.container_pebble_ready("udr") self.assertEqual( self.harness.model.unit.status, - BlockedStatus("Waiting for the `certificates` relation to be created"), + BlockedStatus("Waiting for the certificates relation to be created"), ) @patch("charm.check_output") @@ -111,12 +170,15 @@ def test_given_udr_charm_in_active_status_when_nrf_relation_breaks_then_status_i patched_is_resource_created.return_value = True patched_nrf_url.return_value = "http://nrf:8081" nrf_relation_id = self.harness.add_relation( - relation_name="fiveg_nrf", remote_app="some_nrf_app" + relation_name=NRF_RELATION_NAME, remote_app="some_nrf_app" ) self.harness.add_relation( - relation_name="certificates", remote_app="tls-certificates-operator" + relation_name=TLS_RELATION_NAME, remote_app="tls-certificates-operator" + ) + self.harness.add_relation(relation_name=AUTH_DATABASE_RELATION_NAME, remote_app="mongodb") + self.harness.add_relation( + relation_name=COMMON_DATABASE_RELATION_NAME, remote_app="mongodb" ) - self._database_is_available() self.harness.container_pebble_ready("udr") self.harness.remove_relation(nrf_relation_id) @@ -140,48 +202,59 @@ def test_given_udr_charm_in_active_status_when_database_relation_breaks_then_sta patched_check_output.return_value = "1.2.3.4".encode() patched_is_resource_created.return_value = True patched_nrf_url.return_value = "http://nrf:8081" - self.harness.add_relation(relation_name="fiveg_nrf", remote_app="some_nrf_app") + self.harness.add_relation(relation_name=NRF_RELATION_NAME, remote_app="some_nrf_app") self.harness.add_relation( - relation_name="certificates", remote_app="tls-certificates-operator" + relation_name=TLS_RELATION_NAME, remote_app="tls-certificates-operator" ) - database_relation_id = self._database_is_available() + self._create_auth_database_relation_and_populate_data() + database_relation_id = self._create_common_database_relation_and_populate_data() self.harness.container_pebble_ready("udr") self.harness.remove_relation(database_relation_id) self.assertEqual( self.harness.model.unit.status, - BlockedStatus("Waiting for database relation"), + BlockedStatus("Waiting for common_database relation"), ) - def test_given_relations_created_but_database_not_available_when_pebble_ready_then_status_is_waiting( # noqa: E501 + def test_given_relations_created_but_common_database_not_available_when_pebble_ready_then_status_is_waiting( # noqa: E501 self, ): - self.harness.add_relation(relation_name="database", remote_app="some_db_app") - self.harness.add_relation(relation_name="fiveg_nrf", remote_app="some_nrf_app") self.harness.add_relation( - relation_name="certificates", remote_app="tls-certificates-operator" + relation_name=COMMON_DATABASE_RELATION_NAME, remote_app="some_db_app" + ) + self.harness.add_relation( + relation_name=AUTH_DATABASE_RELATION_NAME, remote_app="some_db_app" + ) + self.harness.add_relation(relation_name=NRF_RELATION_NAME, remote_app="some_nrf_app") + self.harness.add_relation( + relation_name=TLS_RELATION_NAME, remote_app="tls-certificates-operator" ) self.harness.container_pebble_ready("udr") self.assertEqual( self.harness.model.unit.status, - WaitingStatus("Waiting for the database to be available"), + WaitingStatus("Waiting for the common database to be available"), ) @patch("charms.data_platform_libs.v0.data_interfaces.DatabaseRequires.is_resource_created") - def test_give_database_info_not_available_when_pebble_ready_then_status_is_waiting( + def test_given_common_database_url_not_available_when_pebble_ready_then_status_is_waiting( self, patched_is_resource_created ): patched_is_resource_created.return_value = True - self.harness.add_relation(relation_name="database", remote_app="some_db_app") - self.harness.add_relation(relation_name="fiveg_nrf", remote_app="some_nrf_app") self.harness.add_relation( - relation_name="certificates", remote_app="tls-certificates-operator" + relation_name=COMMON_DATABASE_RELATION_NAME, remote_app="some_db_app" + ) + self.harness.add_relation( + relation_name=AUTH_DATABASE_RELATION_NAME, remote_app="some_db_app" + ) + self.harness.add_relation(relation_name=NRF_RELATION_NAME, remote_app="some_nrf_app") + self.harness.add_relation( + relation_name=TLS_RELATION_NAME, remote_app="tls-certificates-operator" ) self.harness.container_pebble_ready("udr") self.assertEqual( self.harness.model.unit.status, - WaitingStatus("Waiting for the database data to be available"), + WaitingStatus("Waiting for the common database url to be available"), ) @patch("charms.data_platform_libs.v0.data_interfaces.DatabaseRequires.is_resource_created") @@ -189,10 +262,11 @@ def test_given_nrf_data_not_available_when_pebble_ready_then_status_is_waiting( self, patched_is_resource_created ): patched_is_resource_created.return_value = True - self.harness.add_relation(relation_name="fiveg_nrf", remote_app="some_nrf_app") - self._database_is_available() + self.harness.add_relation(relation_name=NRF_RELATION_NAME, remote_app="some_nrf_app") + self._create_common_database_relation_and_populate_data() + self._create_auth_database_relation_and_populate_data() self.harness.add_relation( - relation_name="certificates", remote_app="tls-certificates-operator" + relation_name=TLS_RELATION_NAME, remote_app="tls-certificates-operator" ) self.harness.container_pebble_ready("udr") self.assertEqual( @@ -206,10 +280,11 @@ def test_given_relations_created_and_database_available_and_nrf_available_but_st ): patched_is_resource_created.return_value = True patched_nrf_url.return_value = "http://nrf:8081" - self.harness.add_relation(relation_name="fiveg_nrf", remote_app="some_nrf_app") - self._database_is_available() + self.harness.add_relation(relation_name=NRF_RELATION_NAME, remote_app="some_nrf_app") + self._create_common_database_relation_and_populate_data() + self._create_auth_database_relation_and_populate_data() self.harness.add_relation( - relation_name="certificates", remote_app="tls-certificates-operator" + relation_name=TLS_RELATION_NAME, remote_app="tls-certificates-operator" ) self.harness.container_pebble_ready("udr") self.assertEqual( @@ -229,10 +304,11 @@ def test_given_relations_created_and_database_available_and_nrf_available_but_ce patched_check_output.return_value = "1.2.3.4".encode() patched_is_resource_created.return_value = True patched_nrf_url.return_value = "http://nrf:8081" - self.harness.add_relation(relation_name="fiveg_nrf", remote_app="some_nrf_app") - self._database_is_available() + self.harness.add_relation(relation_name=NRF_RELATION_NAME, remote_app="some_nrf_app") + self._create_common_database_relation_and_populate_data() + self._create_auth_database_relation_and_populate_data() self.harness.add_relation( - relation_name="certificates", remote_app="tls-certificates-operator" + relation_name=TLS_RELATION_NAME, remote_app="tls-certificates-operator" ) self.harness.container_pebble_ready("udr") self.assertEqual( @@ -256,8 +332,9 @@ def test_given_udr_operator_ready_to_be_configured_when_pebble_ready_then_config patched_check_output.return_value = "1.2.3.4".encode() patched_is_resource_created.return_value = True patched_nrf_url.return_value = "http://nrf:8081" - self.harness.add_relation(relation_name="fiveg_nrf", remote_app="some_nrf_app") - self._database_is_available() + self.harness.add_relation(relation_name=NRF_RELATION_NAME, remote_app="some_nrf_app") + self._create_common_database_relation_and_populate_data() + self._create_auth_database_relation_and_populate_data() self.harness.add_relation( relation_name="certificates", remote_app="tls-certificates-operator" ) @@ -286,10 +363,11 @@ def test_given_udr_config_is_different_from_the_newly_generated_config_when_pebb patched_check_output.return_value = "1.2.3.4".encode() patched_is_resource_created.return_value = True patched_nrf_url.return_value = "http://nrf:8081" - self.harness.add_relation(relation_name="fiveg_nrf", remote_app="some_nrf_app") - self._database_is_available() + self.harness.add_relation(relation_name=NRF_RELATION_NAME, remote_app="some_nrf_app") + self._create_common_database_relation_and_populate_data() + self._create_auth_database_relation_and_populate_data() self.harness.add_relation( - relation_name="certificates", remote_app="tls-certificates-operator" + relation_name=TLS_RELATION_NAME, remote_app="tls-certificates-operator" ) self.harness.container_pebble_ready("udr") @@ -320,11 +398,12 @@ def test_given_udr_config_is_the_same_as_the_newly_generated_config_when_pebble_ patched_check_output.return_value = "1.2.3.4".encode() patched_is_resource_created.return_value = True patched_nrf_url.return_value = "http://nrf:8081" - self.harness.add_relation(relation_name="fiveg_nrf", remote_app="some_nrf_app") + self.harness.add_relation(relation_name=NRF_RELATION_NAME, remote_app="some_nrf_app") self.harness.add_relation( - relation_name="certificates", remote_app="tls-certificates-operator" + relation_name=TLS_RELATION_NAME, remote_app="tls-certificates-operator" ) - self._database_is_available() + self._create_common_database_relation_and_populate_data() + self._create_auth_database_relation_and_populate_data() self.harness.container_pebble_ready("udr") @@ -352,10 +431,11 @@ def test_given_udr_service_already_configured_and_udr_config_is_different_from_t patched_check_output.return_value = "1.2.3.4".encode() patched_is_resource_created.return_value = True patched_nrf_url.return_value = "http://nrf:8081" - self.harness.add_relation(relation_name="fiveg_nrf", remote_app="some_nrf_app") - self._database_is_available() + self.harness.add_relation(relation_name=NRF_RELATION_NAME, remote_app="some_nrf_app") + self._create_common_database_relation_and_populate_data() + self._create_auth_database_relation_and_populate_data() self.harness.add_relation( - relation_name="certificates", remote_app="tls-certificates-operator" + relation_name=TLS_RELATION_NAME, remote_app="tls-certificates-operator" ) self.harness.set_can_connect(container="udr", val=True) self._container.add_layer("udr", TEST_PEBBLE_LAYER, combine=True) @@ -386,10 +466,11 @@ def test_given_udr_service_already_configured_and_udr_config_is_the_same_as_the_ patched_check_output.return_value = "1.2.3.4".encode() patched_is_resource_created.return_value = True patched_nrf_url.return_value = "http://nrf:8081" - self.harness.add_relation(relation_name="fiveg_nrf", remote_app="some_nrf_app") - self._database_is_available() + self.harness.add_relation(relation_name=NRF_RELATION_NAME, remote_app="some_nrf_app") + self._create_common_database_relation_and_populate_data() + self._create_auth_database_relation_and_populate_data() self.harness.add_relation( - relation_name="certificates", remote_app="tls-certificates-operator" + relation_name=TLS_RELATION_NAME, remote_app="tls-certificates-operator" ) self.harness.set_can_connect(container="udr", val=True) @@ -418,10 +499,11 @@ def test_given_udr_config_is_pushed_when_pebble_ready_then_udr_service_is_config patched_check_output.return_value = "1.2.3.4".encode() patched_is_resource_created.return_value = True patched_nrf_url.return_value = "http://nrf:8081" - self.harness.add_relation(relation_name="fiveg_nrf", remote_app="some_nrf_app") - self._database_is_available() + self.harness.add_relation(relation_name=NRF_RELATION_NAME, remote_app="some_nrf_app") + self._create_common_database_relation_and_populate_data() + self._create_auth_database_relation_and_populate_data() self.harness.add_relation( - relation_name="certificates", remote_app="tls-certificates-operator" + relation_name=TLS_RELATION_NAME, remote_app="tls-certificates-operator" ) self.harness.container_pebble_ready("udr") @@ -451,10 +533,11 @@ def test_given_udr_config_is_pushed_when_pebble_ready_then_udr_service_is_restar patched_check_output.return_value = "1.2.3.4".encode() patched_is_resource_created.return_value = True patched_nrf_url.return_value = "http://nrf:8081" - self.harness.add_relation(relation_name="fiveg_nrf", remote_app="some_nrf_app") - self._database_is_available() + self.harness.add_relation(relation_name=NRF_RELATION_NAME, remote_app="some_nrf_app") + self._create_common_database_relation_and_populate_data() + self._create_auth_database_relation_and_populate_data() self.harness.add_relation( - relation_name="certificates", remote_app="tls-certificates-operator" + relation_name=TLS_RELATION_NAME, remote_app="tls-certificates-operator" ) self.harness.container_pebble_ready("udr") patched_restart.assert_called_once_with("udr") @@ -479,10 +562,11 @@ def test_given_udr_config_is_pushed_when_pebble_ready_then_status_is_active( patched_check_output.return_value = "1.2.3.4".encode() patched_is_resource_created.return_value = True patched_nrf_url.return_value = "http://nrf:8081" - self.harness.add_relation(relation_name="fiveg_nrf", remote_app="some_nrf_app") - self._database_is_available() + self.harness.add_relation(relation_name=NRF_RELATION_NAME, remote_app="some_nrf_app") + self._create_common_database_relation_and_populate_data() + self._create_auth_database_relation_and_populate_data() self.harness.add_relation( - relation_name="certificates", remote_app="tls-certificates-operator" + relation_name=TLS_RELATION_NAME, remote_app="tls-certificates-operator" ) self.harness.container_pebble_ready("udr") self.assertEqual( @@ -503,10 +587,11 @@ def test_given_ip_not_available_when_pebble_ready_then_status_is_waiting( patched_check_output.return_value = "".encode() patched_is_resource_created.return_value = True patched_nrf_url.return_value = "http://nrf:8081" - self.harness.add_relation(relation_name="fiveg_nrf", remote_app="some_nrf_app") - self._database_is_available() + self.harness.add_relation(relation_name=NRF_RELATION_NAME, remote_app="some_nrf_app") + self._create_common_database_relation_and_populate_data() + self._create_auth_database_relation_and_populate_data() self.harness.add_relation( - relation_name="certificates", remote_app="tls-certificates-operator" + relation_name=TLS_RELATION_NAME, remote_app="tls-certificates-operator" ) self.harness.container_pebble_ready("udr") @@ -526,10 +611,11 @@ def test_given_called_process_error_thrown_while_fetching_pod_ip_when_pebble_rea patched_check_output.side_effect = CalledProcessError(cmd="", returncode=123) patched_is_resource_created.return_value = True patched_nrf_url.return_value = "http://nrf:8081" - self.harness.add_relation(relation_name="fiveg_nrf", remote_app="some_nrf_app") - self._database_is_available() + self.harness.add_relation(relation_name=NRF_RELATION_NAME, remote_app="some_nrf_app") + self._create_common_database_relation_and_populate_data() + self._create_auth_database_relation_and_populate_data() self.harness.add_relation( - relation_name="certificates", remote_app="tls-certificates-operator" + relation_name=TLS_RELATION_NAME, remote_app="tls-certificates-operator" ) self.harness.container_pebble_ready("udr")