From 124e9c26e98233dfa039880db725f0bdee10ee7a Mon Sep 17 00:00:00 2001 From: Michael Dmitry <33381599+michaeldmitry@users.noreply.github.com> Date: Thu, 19 Sep 2024 13:36:03 +0300 Subject: [PATCH] Use `traefik_route v0` library from `traefik-k8s` (#348) * use traefik_route from traefik-k8s * pin scenario --- .../v0/traefik_route.py | 53 +++++++++++++------ src/charm.py | 2 +- tests/unit/test_external_url.py | 2 +- tox.ini | 2 +- 4 files changed, 40 insertions(+), 19 deletions(-) rename lib/charms/{traefik_route_k8s => traefik_k8s}/v0/traefik_route.py (87%) diff --git a/lib/charms/traefik_route_k8s/v0/traefik_route.py b/lib/charms/traefik_k8s/v0/traefik_route.py similarity index 87% rename from lib/charms/traefik_route_k8s/v0/traefik_route.py rename to lib/charms/traefik_k8s/v0/traefik_route.py index 48bedf38..55d8eb93 100644 --- a/lib/charms/traefik_route_k8s/v0/traefik_route.py +++ b/lib/charms/traefik_k8s/v0/traefik_route.py @@ -15,7 +15,7 @@ ```shell cd some-charm -charmcraft fetch-lib charms.traefik_route_k8s.v0.traefik_route +charmcraft fetch-lib charms.traefik_k8s.v0.traefik_route ``` To use the library from the provider side (Traefik): @@ -28,7 +28,7 @@ ``` ```python -from charms.traefik_route_k8s.v0.traefik_route import TraefikRouteProvider +from charms.traefik_k8s.v0.traefik_route import TraefikRouteProvider class TraefikCharm(CharmBase): def __init__(self, *args): @@ -56,7 +56,7 @@ def _handle_traefik_route_ready(self, event): ```python # ... -from charms.traefik_route_k8s.v0.traefik_route import TraefikRouteRequirer +from charms.traefik_k8s.v0.traefik_route import TraefikRouteRequirer class TraefikRouteCharm(CharmBase): def __init__(self, *args): @@ -81,14 +81,14 @@ def __init__(self, *args): from ops.model import Relation # The unique Charmhub library identifier, never change it -LIBID = "fe2ac43a373949f2bf61383b9f35c83c" +LIBID = "f0d93d2bdf354b99a527463a9c49fce3" # Increment this major API version when introducing breaking changes LIBAPI = 0 # Increment this PATCH version before using `charmcraft publish-lib` or reset # to 0 if you are raising the major API version -LIBPATCH = 9 +LIBPATCH = 1 log = logging.getLogger(__name__) @@ -243,22 +243,35 @@ def update_traefik_address( self._stored.external_host = external_host self._stored.scheme = scheme - @staticmethod - def is_ready(relation: Relation) -> bool: + def is_ready(self, relation: Relation) -> bool: """Whether TraefikRoute is ready on this relation. Returns True when the remote app shared the config; False otherwise. """ - assert relation.app is not None # not currently handled anyway + if not relation.app or not relation.data[relation.app]: + return False return "config" in relation.data[relation.app] - @staticmethod - def get_config(relation: Relation) -> Optional[str]: - """Retrieve the config published by the remote application.""" - # TODO: validate this config - assert relation.app is not None # not currently handled anyway + def get_config(self, relation: Relation) -> Optional[str]: + """Renamed to ``get_dynamic_config``.""" + log.warning( + "``TraefikRouteProvider.get_config`` is deprecated. " + "Use ``TraefikRouteProvider.get_dynamic_config`` instead" + ) + return self.get_dynamic_config(relation) + + def get_dynamic_config(self, relation: Relation) -> Optional[str]: + """Retrieve the dynamic config published by the remote application.""" + if not self.is_ready(relation): + return None return relation.data[relation.app].get("config") + def get_static_config(self, relation: Relation) -> Optional[str]: + """Retrieve the static config published by the remote application.""" + if not self.is_ready(relation): + return None + return relation.data[relation.app].get("static") + class TraefikRouteRequirer(Object): """Wrapper for the requirer side of traefik-route. @@ -266,6 +279,7 @@ class TraefikRouteRequirer(Object): The traefik_route requirer will publish to the application databag an object like: { 'config': + 'static': # optional } NB: TraefikRouteRequirer does no validation; it assumes that the @@ -344,11 +358,15 @@ def is_ready(self) -> bool: """Is the TraefikRouteRequirer ready to submit data to Traefik?""" return self._relation is not None - def submit_to_traefik(self, config): + def submit_to_traefik(self, config: dict, static: Optional[dict] = None): """Relay an ingress configuration data structure to traefik. - This will publish to TraefikRoute's traefik-route relation databag - the config traefik needs to route the units behind this charm. + This will publish to the traefik-route relation databag + a chunk of Traefik dynamic config that the traefik charm on the other end can pick + up and apply. + + Use ``static`` if you need to update traefik's **static** configuration. + Note that this will force traefik to restart to comply. """ if not self._charm.unit.is_leader(): raise UnauthorizedError() @@ -357,3 +375,6 @@ def submit_to_traefik(self, config): # Traefik thrives on yaml, feels pointless to talk json to Route app_databag["config"] = yaml.safe_dump(config) + + if static: + app_databag["static"] = yaml.safe_dump(static) diff --git a/src/charm.py b/src/charm.py index b80f799d..2419b9a8 100755 --- a/src/charm.py +++ b/src/charm.py @@ -60,7 +60,7 @@ CertificateTransferRequires, ) from charms.prometheus_k8s.v0.prometheus_scrape import MetricsEndpointProvider -from charms.traefik_route_k8s.v0.traefik_route import TraefikRouteRequirer +from charms.traefik_k8s.v0.traefik_route import TraefikRouteRequirer from ops.charm import ( ActionEvent, CharmBase, diff --git a/tests/unit/test_external_url.py b/tests/unit/test_external_url.py index 1c824dcf..65b78480 100644 --- a/tests/unit/test_external_url.py +++ b/tests/unit/test_external_url.py @@ -8,7 +8,7 @@ from unittest.mock import MagicMock, patch import ops -from charms.traefik_route_k8s.v0.traefik_route import TraefikRouteRequirer +from charms.traefik_k8s.v0.traefik_route import TraefikRouteRequirer from ops.model import ActiveStatus from ops.testing import Harness diff --git a/tox.ini b/tox.ini index 5092e64c..ed2129d5 100644 --- a/tox.ini +++ b/tox.ini @@ -87,7 +87,7 @@ deps = pytest<8.2.0 # https://github.com/pytest-dev/pytest/issues/12263 responses cosl - ops-scenario==6 + ops-scenario<7.0.0 -r{toxinidir}/requirements.txt commands = /usr/bin/env sh -c 'stat sqlite-static > /dev/null 2>&1 || curl -L https://github.com/CompuRoot/static-sqlite3/releases/latest/download/sqlite3 -o sqlite-static && chmod +x sqlite-static'