diff --git a/lib/charms/certificate_transfer_interface/v0/certificate_transfer.py b/lib/charms/certificate_transfer_interface/v0/certificate_transfer.py index caa6e228..72cc9a26 100644 --- a/lib/charms/certificate_transfer_interface/v0/certificate_transfer.py +++ b/lib/charms/certificate_transfer_interface/v0/certificate_transfer.py @@ -101,6 +101,7 @@ def _on_certificate_removed(self, event: CertificateRemovedEvent): from typing import List, Mapping from jsonschema import exceptions, validate # type: ignore[import-untyped] +from ops import Relation from ops.charm import CharmBase, CharmEvents, RelationBrokenEvent, RelationChangedEvent from ops.framework import EventBase, EventSource, Handle, Object @@ -112,7 +113,7 @@ def _on_certificate_removed(self, event: CertificateRemovedEvent): # Increment this PATCH version before using `charmcraft publish-lib` or reset # to 0 if you are raising the major API version -LIBPATCH = 8 +LIBPATCH = 9 PYDEPS = ["jsonschema"] @@ -391,3 +392,11 @@ def _on_relation_broken(self, event: RelationBrokenEvent) -> None: None """ self.on.certificate_removed.emit(relation_id=event.relation.id) + + def is_ready(self, relation: Relation) -> bool: + """Check if the relation is ready by checking that it has valid relation data.""" + relation_data = _load_relation_data(relation.data[relation.app]) + if not self._relation_data_is_valid(relation_data): + logger.warning("Provider relation data did not pass JSON Schema validation: ") + return False + return True diff --git a/lib/charms/observability_libs/v1/cert_handler.py b/lib/charms/observability_libs/v1/cert_handler.py index 26be8793..7fcc3258 100644 --- a/lib/charms/observability_libs/v1/cert_handler.py +++ b/lib/charms/observability_libs/v1/cert_handler.py @@ -68,7 +68,7 @@ LIBID = "b5cd5cd580f3428fa5f59a8876dcbe6a" LIBAPI = 1 -LIBPATCH = 14 +LIBPATCH = 15 VAULT_SECRET_LABEL = "cert-handler-private-vault" @@ -127,7 +127,7 @@ class _RelationVaultBackend(_VaultBackend): _NEST_UNDER = "lib.charms.observability_libs.v1.cert_handler::vault" # This key needs to be relation-unique. If someone ever creates multiple Vault(_RelationVaultBackend) # instances backed by the same (peer) relation, they'll need to set different _NEST_UNDERs - # for each _RelationVaultBackend instance or they'll be fighting over it. + # for each _RelationVaultBackend instance, or they'll be fighting over it. def __init__(self, charm: CharmBase, relation_name: str): self.charm = charm @@ -344,6 +344,13 @@ def __init__( self.charm.on[self.certificates_relation_name].relation_joined, # pyright: ignore self._on_certificates_relation_joined, ) + # The following observer is a workaround. The tls-certificates lib sometimes fails to emit the custom + # "certificate_available" event on relation changed. Not sure why this was happening. We certainly have some + # tech debt here to address, but this workaround proved to work. + self.framework.observe( + self.charm.on[self.certificates_relation_name].relation_changed, # pyright: ignore + self._on_certificate_available, + ) self.framework.observe( self.certificates.on.certificate_available, # pyright: ignore self._on_certificate_available, @@ -366,7 +373,7 @@ def __init__( ) if refresh_events: - logger.warn( + logger.warning( "DEPRECATION WARNING. `refresh_events` is now deprecated. CertHandler will automatically refresh the CSR when necessary." ) @@ -429,7 +436,7 @@ def enabled(self) -> bool: See also the `available` property. """ # We need to check for units as a temporary workaround because of https://bugs.launchpad.net/juju/+bug/2024583 - # This could in theory not work correctly on scale down to 0 but it is necessary for the moment. + # This could in theory not work correctly on scale down to 0, but it is necessary for the moment. if not self.relation: return False @@ -636,7 +643,7 @@ def _on_all_certificates_invalidated(self, _: AllCertificatesInvalidatedEvent) - # Note: assuming "limit: 1" in metadata # The "certificates_relation_broken" event is converted to "all invalidated" custom # event by the tls-certificates library. Per convention, we let the lib manage the - # relation and we do not observe "certificates_relation_broken" directly. + # relation, and we do not observe "certificates_relation_broken" directly. self.vault.clear() # We do not generate a CSR here because the relation is gone. self.on.cert_changed.emit() # pyright: ignore