Skip to content

Commit

Permalink
Unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
juditnovak committed Feb 16, 2024
1 parent 8dcc32c commit 238018b
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 12 deletions.
47 changes: 37 additions & 10 deletions lib/charms/data_platform_libs/v0/data_interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ def _on_topic_requested(self, event: TopicRequestedEvent):

# Increment this PATCH version before using `charmcraft publish-lib` or reset
# to 0 if you are raising the major API version
LIBPATCH = 27
LIBPATCH = 29

PYDEPS = ["ops>=2.0.0"]

Expand Down Expand Up @@ -558,6 +558,18 @@ def get_info(self) -> Optional[SecretInfo]:
if self.meta:
return self.meta.get_info()

def remove(self) -> None:
"""Remove secret."""
if not self.meta:
raise SecretsUnavailableError("Non-existent secret was attempted to be removed.")
try:
self.meta.remove_all_revisions()
except SecretNotFoundError:
pass
self._secret_content = {}
self._secret_meta = None
self._secret_uri = None


class SecretCache:
"""A data structure storing CachedSecret objects."""
Expand Down Expand Up @@ -1153,6 +1165,8 @@ def _delete_relation_secret(
relation.data[self.component].pop(field)
except KeyError:
pass
label = self._generate_secret_label(self.relation_name, relation.id, group)
self.secrets.remove(label)

# Return the content that was removed
return True
Expand Down Expand Up @@ -1898,6 +1912,17 @@ def database(self) -> Optional[str]:
class DatabaseRequestedEvent(DatabaseProvidesEvent, ExtraRoleEvent):
"""Event emitted when a new database is requested for use on this relation."""

@property
def external_node_connectivity(self) -> bool:
"""Returns the requested external_node_connectivity field."""
if not self.relation.app:
return False

return (
self.relation.data[self.relation.app].get("external-node-connectivity", "false")
== "true"
)


class DatabaseProvidesEvents(CharmEvents):
"""Database events.
Expand Down Expand Up @@ -2116,11 +2141,13 @@ def __init__(
extra_user_roles: Optional[str] = None,
relations_aliases: Optional[List[str]] = None,
additional_secret_fields: Optional[List[str]] = [],
external_node_connectivity: bool = False,
):
"""Manager of database client relations."""
super().__init__(charm, relation_name, extra_user_roles, additional_secret_fields)
self.database = database_name
self.relations_aliases = relations_aliases
self.external_node_connectivity = external_node_connectivity

# Define custom event names for each alias.
if relations_aliases:
Expand Down Expand Up @@ -2271,16 +2298,16 @@ def _on_relation_created_event(self, event: RelationCreatedEvent) -> None:
if not self.local_unit.is_leader():
return

event_data = {"database": self.database}

if self.extra_user_roles:
self.update_relation_data(
event.relation.id,
{
"database": self.database,
"extra-user-roles": self.extra_user_roles,
},
)
else:
self.update_relation_data(event.relation.id, {"database": self.database})
event_data["extra-user-roles"] = self.extra_user_roles

# set external-node-connectivity field
if self.external_node_connectivity:
event_data["external-node-connectivity"] = "true"

self.update_relation_data(event.relation.id, event_data)

def _on_relation_changed_event(self, event: RelationChangedEvent) -> None:
"""Event emitted when the database relation has changed."""
Expand Down
61 changes: 59 additions & 2 deletions tests/unit/test_data_interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,18 @@ class DatabaseCharm(CharmBase):

def __init__(self, *args):
super().__init__(*args)
self.peer_relation_app = DataPeer(self, PEER_RELATION_NAME)
self.peer_relation_app = DataPeerUnit(self, PEER_RELATION_NAME)
self.peer_relation_app = DataPeer(
self,
PEER_RELATION_NAME,
additional_secret_fields=["cfg_file"],
field_translations={"cfg_file": "cfg-file"},
)
self.peer_relation_unit = DataPeerUnit(
self,
PEER_RELATION_NAME,
additional_secret_fields=["ca"],
field_translations={"ca": "ca-auth"},
)
self.provider = DatabaseProvides(
self,
DATABASE_RELATION_NAME,
Expand Down Expand Up @@ -239,6 +249,7 @@ class TestDatabaseProvides(DataProvidesBaseTests, unittest.TestCase):
def get_harness(self) -> Tuple[Harness, int]:
harness = Harness(self.charm, meta=self.metadata)
# Set up the initial relation and hooks.
self.peer_rel_id = harness.add_relation(PEER_RELATION_NAME, self.app_name)
rel_id = harness.add_relation(self.relation_name, "application")

# Juju 3 - specific setup
Expand Down Expand Up @@ -567,6 +578,7 @@ def test_delete_relation_data_and_field_secrets(self):
with pytest.raises(SecretNotFoundError):
self.harness.charm.model.get_secret(id=secret_id)

@pytest.mark.usefixtures("only_with_juju_secrets")
def test_database_requested_event(self):
# Test custom event creation

Expand All @@ -583,6 +595,51 @@ def test_database_requested_event(self):
self.harness.update_relation_data(self.rel_id, "application/0", {"database": DATABASE})
assert captured.event.unit.name == "application/0"

@pytest.mark.usefixtures("only_without_juju_secrets")
@parameterized.expand(
[
("app", "peer_relation_app", "cfg_file", "cfg-file", True),
("unit", "peer_relation_unit", "ca", "ca-auth", True),
]
)
def test_peer_relation(self, scope, endpoint_name, old_field, new_field, is_leader):
"""Check if we're moving on to use secrets when live upgrade from databag to Secrets usage."""
# App has to be leader, unit can be either
with self.harness.hooks_disabled():
self.harness.set_leader(is_leader)

endpoint = getattr(self.harness.charm, endpoint_name)

# Getting current password
entity = getattr(self.harness.charm, scope)
self.harness.update_relation_data(0, entity.name, {old_field: "bla"})
assert endpoint.fetch_my_relation_field(0, old_field) == "bla"

# Set secret via old name resulting in having it moved from databag to Juju Secret
endpoint.update_relation_data(0, {old_field: "blablabla"})
assert endpoint.fetch_my_relation_field(0, old_field) == "blablabla"
assert endpoint.fetch_my_relation_field(0, new_field) == "blablabla"
# A secret was created, while the databag field disappeared
assert self.harness.charm.model.get_secret(label=f"database.{scope}")
assert old_field not in self.harness.get_relation_data(self.rel_id, "database")

# Set secret via new name
endpoint.update_relation_data(0, {new_field: "blablabla-new"})
assert endpoint.fetch_my_relation_field(0, old_field) == "blablabla-new"
assert endpoint.fetch_my_relation_field(0, new_field) == "blablabla-new"

# Delete secret via old name
endpoint.delete_relation_data(0, [old_field])
assert endpoint.fetch_my_relation_field(0, old_field) is None
assert endpoint.fetch_my_relation_field(0, new_field) is None

# Delete secret via new name
endpoint.update_relation_data(0, {new_field: "blablabla-new2"})
assert endpoint.fetch_my_relation_field(0, old_field) == "blablabla-new2"
endpoint.delete_relation_data(0, [new_field])
assert endpoint.fetch_my_relation_field(0, old_field) is None
assert endpoint.fetch_my_relation_field(0, new_field) is None

def test_peer_relation_disabled_functions(self):
"""Verify that fetch_relation_data/field() functions are disabled for Peer Relations."""
with pytest.raises(NotImplementedError):
Expand Down

0 comments on commit 238018b

Please sign in to comment.