From 8703f6fa4e963095967b837a25203611ae2f7570 Mon Sep 17 00:00:00 2001 From: gatici Date: Mon, 18 Sep 2023 11:30:39 +0300 Subject: [PATCH] Updating tls-certificates libraary Signed-off-by: gatici --- .../v2/tls_certificates.py | 28 +++++++++---------- tests/integration/test_integration.py | 14 ++++++++-- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/lib/charms/tls_certificates_interface/v2/tls_certificates.py b/lib/charms/tls_certificates_interface/v2/tls_certificates.py index c55f501..14f94d7 100644 --- a/lib/charms/tls_certificates_interface/v2/tls_certificates.py +++ b/lib/charms/tls_certificates_interface/v2/tls_certificates.py @@ -298,7 +298,7 @@ def _on_all_certificates_invalidated(self, event: AllCertificatesInvalidatedEven ) from ops.framework import EventBase, EventSource, Handle, Object from ops.jujuversion import JujuVersion -from ops.model import SecretNotFoundError +from ops.model import Relation, SecretNotFoundError # The unique Charmhub library identifier, never change it LIBID = "afd8c2bccf834997afce12c2706d2ede" @@ -897,21 +897,21 @@ def __init__(self, charm: CharmBase, relationship_name: str): self.charm = charm self.relationship_name = relationship_name - def _load_relation_data(self, raw_relation_data: dict) -> dict: - """Loads relation data from the relation data bag. + def _load_app_relation_data(self, relation: Relation) -> dict: + """Loads relation data from the application relation data bag. Json loads all data. Args: - raw_relation_data (dict): Relation data from the databag + relation_object: Relation data from the application databag Returns: - dict: Relation data in dict + dict: Relation data in dict format. """ # If unit is not leader, it does not try to reach relation data. if not self.model.unit.is_leader(): return {} - return _load_relation_data(raw_relation_data) + return _load_relation_data(relation.data[self.charm.app]) def _add_certificate( self, @@ -947,7 +947,7 @@ def _add_certificate( "ca": ca, "chain": chain, } - provider_relation_data = self._load_relation_data(relation.data[self.charm.app]) + provider_relation_data = self._load_app_relation_data(relation) provider_certificates = provider_relation_data.get("certificates", []) certificates = copy.deepcopy(provider_certificates) if new_certificate in certificates: @@ -980,7 +980,7 @@ def _remove_certificate( raise RuntimeError( f"Relation {self.relationship_name} with relation id {relation_id} does not exist" ) - provider_relation_data = self._load_relation_data(relation.data[self.charm.app]) + provider_relation_data = self._load_app_relation_data(relation) provider_certificates = provider_relation_data.get("certificates", []) certificates = copy.deepcopy(provider_certificates) for certificate_dict in certificates: @@ -1015,7 +1015,7 @@ def revoke_all_certificates(self) -> None: This method is meant to be used when the Root CA has changed. """ for relation in self.model.relations[self.relationship_name]: - provider_relation_data = self._load_relation_data(relation.data[self.charm.app]) + provider_relation_data = self._load_app_relation_data(relation) provider_certificates = copy.deepcopy(provider_relation_data.get("certificates", [])) for certificate in provider_certificates: certificate["revoked"] = True @@ -1097,7 +1097,7 @@ def get_issued_certificates( else self.model.relations.get(self.relationship_name, []) ) for relation in relations: - provider_relation_data = self._load_relation_data(relation.data[self.charm.app]) + provider_relation_data = self._load_app_relation_data(relation) provider_certificates = provider_relation_data.get("certificates", []) certificates[relation.app.name] = [] # type: ignore[union-attr] @@ -1129,8 +1129,10 @@ def _on_relation_changed(self, event: RelationChangedEvent) -> None: """ if event.unit is None: return + if not self.model.unit.is_leader(): + return requirer_relation_data = _load_relation_data(event.relation.data[event.unit]) - provider_relation_data = self._load_relation_data(event.relation.data[self.charm.app]) + provider_relation_data = self._load_app_relation_data(event.relation) if not self._relation_data_is_valid(requirer_relation_data): logger.debug("Relation data did not pass JSON Schema validation") return @@ -1169,9 +1171,7 @@ def _revoke_certificates_for_which_no_csr_exists(self, relation_id: int) -> None ) if not certificates_relation: raise RuntimeError(f"Relation {self.relationship_name} does not exist") - provider_relation_data = self._load_relation_data( - certificates_relation.data[self.charm.app] - ) + provider_relation_data = self._load_app_relation_data(certificates_relation) list_of_csrs: List[str] = [] for unit in certificates_relation.units: requirer_relation_data = _load_relation_data(certificates_relation.data[unit]) diff --git a/tests/integration/test_integration.py b/tests/integration/test_integration.py index c4e78bb..f2083c4 100644 --- a/tests/integration/test_integration.py +++ b/tests/integration/test_integration.py @@ -48,12 +48,10 @@ async def test_given_charm_is_built_when_deployed_then_status_is_active( ) -async def test_given_charm_is_scaled_when_tls_requirer_is_related_then_certificate_is_created_and_passed_correctly( # noqa: E501 +async def test_given_tls_requirer_is_deployed_and_related_then_certificate_is_created_and_passed_correctly( # noqa: E501 ops_test: OpsTest, build_and_deploy, ): - await ops_test.model.applications[APP_NAME].scale(2) - await ops_test.model.wait_for_idle(apps=[APP_NAME], timeout=1000, wait_for_exact_units=2) await ops_test.model.add_relation( relation1=f"{APP_NAME}:certificates", relation2=f"{TLS_REQUIRER_CHARM_NAME}" ) @@ -69,6 +67,16 @@ async def test_given_charm_is_scaled_when_tls_requirer_is_related_then_certifica assert action_output["csr"] is not None +async def test_given_charm_scaled_then_charm_does_not_crash( + ops_test: OpsTest, + build_and_deploy, +): + await ops_test.model.applications[APP_NAME].scale(2) + await ops_test.model.wait_for_idle(apps=[APP_NAME], timeout=1000, wait_for_exact_units=2) + await ops_test.model.applications[APP_NAME].scale(1) + await ops_test.model.wait_for_idle(apps=[APP_NAME], timeout=1000, wait_for_exact_units=1) + + async def run_get_certificate_action(ops_test) -> dict: """Runs `get-certificate` on the `tls-requirer-requirer/0` unit.