diff --git a/lib/charms/certificate_transfer_interface/v0/certificate_transfer.py b/lib/charms/certificate_transfer_interface/v0/certificate_transfer.py index dd1b6a3..b07b835 100644 --- a/lib/charms/certificate_transfer_interface/v0/certificate_transfer.py +++ b/lib/charms/certificate_transfer_interface/v0/certificate_transfer.py @@ -21,7 +21,9 @@ from ops.charm import CharmBase, RelationJoinedEvent from ops.main import main -from lib.charms.certificate_transfer_interface.v0.certificate_transfer import CertificateTransferProvides # noqa: E501 W505 +from lib.charms.certificate_transfer_interface.v0.certificate_transfer import( + CertificateTransferProvides, +) class DummyCertificateTransferProviderCharm(CharmBase): @@ -36,7 +38,9 @@ def _on_certificates_relation_joined(self, event: RelationJoinedEvent): certificate = "my certificate" ca = "my CA certificate" chain = ["certificate 1", "certificate 2"] - self.certificate_transfer.set_certificate(certificate=certificate, ca=ca, chain=chain, relation_id=event.relation.id) + self.certificate_transfer.set_certificate( + certificate=certificate, ca=ca, chain=chain, relation_id=event.relation.id + ) if __name__ == "__main__": @@ -95,7 +99,7 @@ def _on_certificate_removed(self, event: CertificateRemovedEvent): import json import logging -from typing import List +from typing import List, Mapping from jsonschema import exceptions, validate # type: ignore[import-untyped] from ops.charm import CharmBase, CharmEvents, RelationBrokenEvent, RelationChangedEvent @@ -109,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 = 6 +LIBPATCH = 7 PYDEPS = ["jsonschema"] @@ -210,7 +214,7 @@ def restore(self, snapshot: dict): self.relation_id = snapshot["relation_id"] -def _load_relation_data(raw_relation_data: dict) -> dict: +def _load_relation_data(raw_relation_data: Mapping[str, str]) -> dict: """Load relation data from the relation data bag. Args: @@ -313,7 +317,7 @@ def remove_certificate(self, relation_id: int) -> None: class CertificateTransferRequires(Object): """TLS certificates requirer class to be instantiated by TLS certificates requirers.""" - on = CertificateTransferRequirerCharmEvents() + on = CertificateTransferRequirerCharmEvents() # type: ignore def __init__( self, diff --git a/lib/charms/loki_k8s/v1/loki_push_api.py b/lib/charms/loki_k8s/v1/loki_push_api.py index 6c8549c..4bc4e22 100644 --- a/lib/charms/loki_k8s/v1/loki_push_api.py +++ b/lib/charms/loki_k8s/v1/loki_push_api.py @@ -497,6 +497,7 @@ def _alert_rules_error(self, event): from ops.charm import ( CharmBase, HookEvent, + PebbleReadyEvent, RelationBrokenEvent, RelationCreatedEvent, RelationDepartedEvent, @@ -518,7 +519,7 @@ def _alert_rules_error(self, event): # Increment this PATCH version before using `charmcraft publish-lib` or reset # to 0 if you are raising the major API version -LIBPATCH = 5 +LIBPATCH = 6 logger = logging.getLogger(__name__) @@ -2486,7 +2487,10 @@ def enable_endpoints( class LogForwarder(ConsumerBase): - """Forward the standard outputs of all workloads operated by a charm to one or multiple Loki endpoints.""" + """Forward the standard outputs of all workloads operated by a charm to one or multiple Loki endpoints. + + This class implements Pebble log forwarding. Juju >= 3.4 is needed. + """ def __init__( self, @@ -2510,27 +2514,47 @@ def __init__( self.framework.observe(on.relation_departed, self._update_logging) self.framework.observe(on.relation_broken, self._update_logging) + for container_name in self._charm.meta.containers.keys(): + snake_case_container_name = container_name.replace("-", "_") + self.framework.observe( + getattr(self._charm.on, f"{snake_case_container_name}_pebble_ready"), + self._on_pebble_ready, + ) + + def _on_pebble_ready(self, event: PebbleReadyEvent): + if not (loki_endpoints := self._retrieve_endpoints_from_relation()): + logger.warning("No Loki endpoints available") + return + + self._update_endpoints(event.workload, loki_endpoints) + def _update_logging(self, _): """Update the log forwarding to match the active Loki endpoints.""" + if not (loki_endpoints := self._retrieve_endpoints_from_relation()): + logger.warning("No Loki endpoints available") + return + + for container in self._charm.unit.containers.values(): + self._update_endpoints(container, loki_endpoints) + + def _retrieve_endpoints_from_relation(self) -> dict: loki_endpoints = {} # Get the endpoints from relation data for relation in self._charm.model.relations[self._relation_name]: loki_endpoints.update(self._fetch_endpoints(relation)) - if not loki_endpoints: - logger.warning("No Loki endpoints available") - return + return loki_endpoints - for container in self._charm.unit.containers.values(): - _PebbleLogClient.disable_inactive_endpoints( - container=container, - active_endpoints=loki_endpoints, - topology=self.topology, - ) - _PebbleLogClient.enable_endpoints( - container=container, active_endpoints=loki_endpoints, topology=self.topology - ) + def _update_endpoints(self, container: Container, loki_endpoints: dict): + _PebbleLogClient.disable_inactive_endpoints( + container=container, + active_endpoints=loki_endpoints, + topology=self.topology, + ) + _PebbleLogClient.enable_endpoints( + container=container, active_endpoints=loki_endpoints, topology=self.topology + ) def is_ready(self, relation: Optional[Relation] = None): """Check if the relation is active and healthy."""