diff --git a/src/charm.py b/src/charm.py index b331f499..be1fc9fb 100755 --- a/src/charm.py +++ b/src/charm.py @@ -621,6 +621,12 @@ def _current_effective_db_info(self) -> Optional[types_.DatabaseConfig]: host, port = self._parse_database_endpoints( self.database.fetch_relation_field(relation.id, "endpoints") ) + if host is None: + logger.warning( + "`endpoints` is missing in database relation data: %s", + dict(relation.data[relation.app]), + ) + return None return types_.DatabaseConfig( hostname=host, port=port, diff --git a/tests/unit/test_charm.py b/tests/unit/test_charm.py index dda3607d..fd625da4 100644 --- a/tests/unit/test_charm.py +++ b/tests/unit/test_charm.py @@ -6,6 +6,7 @@ # pylint:disable=protected-access import json +import secrets import typing import unittest.mock @@ -36,14 +37,14 @@ def test_generate_wp_secret_keys(harness: ops.testing.Harness): """ harness.begin() charm: WordpressCharm = typing.cast(WordpressCharm, harness.charm) - secrets = charm._generate_wp_secret_keys() + wordpress_secrets = charm._generate_wp_secret_keys() assert ( - "default_admin_password" in secrets + "default_admin_password" in wordpress_secrets ), "WordPress should generate a default admin password" - del secrets["default_admin_password"] - key_values = list(secrets.values()) - assert set(secrets.keys()) == set( + del wordpress_secrets["default_admin_password"] + key_values = list(wordpress_secrets.values()) + assert set(wordpress_secrets.keys()) == set( charm._wordpress_secret_key_fields() ), "generated WordPress secrets should contain all required fields" assert len(key_values) == len(set(key_values)), "no two secret values should be the same" @@ -883,6 +884,46 @@ def test_wordpress_version_set(harness: ops.testing.Harness): assert harness.get_workload_version() == WordpressContainerMock._WORDPRESS_VERSION +@pytest.mark.usefixtures("attach_storage") +def test_waiting_for_leader_installation_timeout( + patch: WordpressPatch, harness: ops.testing.Harness, app_name +): + """ + arrange: charm peer and database relation is ready, the storage is attached. + act: start the charm as a follower unit. + assert: charm unit should enter blocked state, and the installation error should be seen + in the status. + """ + replica_relation_id = harness.add_relation("wordpress-replica", app_name) + harness.update_relation_data( + relation_id=replica_relation_id, + app_or_unit=app_name, + key_values={k: "test" for k in WordpressCharm._wordpress_secret_key_fields()}, + ) + db_relation_id = harness.add_relation("database", "mysql") + harness.add_relation_unit(db_relation_id, "mysql/0") + test_database_password = secrets.token_urlsafe(8) + harness.update_relation_data( + relation_id=db_relation_id, + app_or_unit="mysql", + key_values={ + "endpoints": "test", + "database": "test", + "username": "test", + "password": test_database_password, + }, + ) + patch.database.prepare_database( + host="test", database="test", user="test", password=test_database_password + ) + harness.begin_with_initial_hooks() + assert harness.charm.unit.status.name == "blocked" + assert ( + harness.charm.unit.status.message + == "leader unit failed to initialize WordPress database in given time." + ) + + def test_valid_proxy_config( harness: ops.testing.Harness, setup_replica_consensus: typing.Callable[[], dict],