#!/usr/bin/env python3 # Copyright 2026 Valentin Haudiquet # See LICENSE file for licensing details. """Charm the application.""" import logging import time import ops from charms.traefik_k8s.v2.ingress import ( IngressPerAppReadyEvent, IngressPerAppRequirer, IngressPerAppRevokedEvent, ) # A standalone module for workload-specific logic (no charming concerns): import charmed_server logger = logging.getLogger(__name__) class CharmedServerCharm(ops.CharmBase): """Charm the application.""" def __init__(self, framework: ops.Framework): super().__init__(framework) framework.observe(self.on.install, self._on_install) framework.observe(self.on.start, self._on_start) framework.observe(self.on.config_changed, self._on_config_changed) self.ingress = IngressPerAppRequirer(self, port=80) framework.observe(self.ingress.on.ready, self._on_ingress_ready) framework.observe(self.ingress.on.revoked, self._on_ingress_revoked) def _on_ingress_ready(self, event: IngressPerAppReadyEvent): logger.info("This app's ingress URL: %s", event.url) def _on_ingress_revoked(self, event: IngressPerAppRevokedEvent): logger.info("This app no longer has ingress") def _on_install(self, event: ops.InstallEvent): """Install the workload on the machine.""" charmed_server.install() def _on_start(self, event: ops.StartEvent): """Handle start event.""" self.unit.status = ops.MaintenanceStatus("starting workload") self.configure_and_run() version = charmed_server.get_version() if version is not None: self.unit.set_workload_version(version) self.unit.status = ops.ActiveStatus() def _on_config_changed(self, event: ops.ConfigChangedEvent) -> None: """Handle config-changed event.""" self.configure_and_run() def configure_and_run(self) -> None: """Ensure that nginx is running with the correct config.""" if not charmed_server.is_installed(): return changed = charmed_server.ensure_config() if not charmed_server.is_running(): charmed_server.start() self.wait_for_running() elif changed: logger.info("Config changed while nginx is running. Updating nginx config") charmed_server.reload_config() def wait_for_running(self) -> None: """Wait for nginx to be running.""" for _ in range(3): if charmed_server.is_running(): return time.sleep(1) raise RuntimeError("nginx was not running within the expected time") def _on_stop(self, event: ops.StopEvent) -> None: """Handle stop event.""" charmed_server.stop() if __name__ == "__main__": # pragma: nocover ops.main(CharmedServerCharm)