From 13be2fe601170d68c869faf68682d0503d5615e7 Mon Sep 17 00:00:00 2001 From: Ahmad Hassan Date: Wed, 30 Jul 2025 16:27:21 +0500 Subject: [PATCH] [epa-orchestrator] Add noop relation handler for sunbeam-machine relation Add relation handler for the subordinate charm Change-Id: I0d561fda38bfef5262e9d9a88ce5ac97f0cfea31 Signed-off-by: Ahmad Hassan --- charms/epa-orchestrator/src/charm.py | 42 ++++++++++++++++++- .../epa-orchestrator/tests/unit/test_charm.py | 8 ++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/charms/epa-orchestrator/src/charm.py b/charms/epa-orchestrator/src/charm.py index c7b03b04..8d9b407a 100755 --- a/charms/epa-orchestrator/src/charm.py +++ b/charms/epa-orchestrator/src/charm.py @@ -20,15 +20,38 @@ This charm is used to install the epa-orchestrator snap as a part of the opensta """ import logging +from typing import ( + List, +) import charms.operator_libs_linux.v2.snap as snap import ops import ops_sunbeam.charm as sunbeam_charm +import ops_sunbeam.relation_handlers as sunbeam_rhandlers import ops_sunbeam.tracing as sunbeam_tracing logger = logging.getLogger(__name__) +@sunbeam_tracing.trace_type +class SunbeamMachineRequiresHandler(sunbeam_rhandlers.RelationHandler): + """Handler for sunbeam-machine relation on the requires side.""" + + def setup_event_handler(self): + """Noop event handler for sunbeam-machine relation.""" + return ops.framework.Object(self.charm, self.relation_name) + + def interface_properties(self) -> dict: + """Return empty interface properties.""" + return {} + + @property + def ready(self) -> bool: + """Report if relation is ready.""" + relations = self.model.relations.get(self.relation_name, []) + return len(relations) > 0 + + @sunbeam_tracing.trace_sunbeam_charm(extra_types=(snap.SnapCache, snap.Snap)) class EpaOrchestratorCharm(sunbeam_charm.OSBaseOperatorCharmSnap): """Charm the service.""" @@ -45,7 +68,7 @@ class EpaOrchestratorCharm(sunbeam_charm.OSBaseOperatorCharmSnap): """Returns the snap channel.""" return str(self.model.config["snap-channel"]) - def ensure_services_running(self, enable) -> None: + def ensure_services_running(self, enable: bool = True) -> None: """Override to prevent service start - this snap has no services.""" logger.debug( "Skipping service start - %s snap has no services", self.snap_name @@ -59,6 +82,23 @@ class EpaOrchestratorCharm(sunbeam_charm.OSBaseOperatorCharmSnap): ) pass + def relation_ready(self, event) -> None: + """Noop callback for sunbeam-machine relation.""" + pass + + def get_relation_handlers( + self, handlers: List[sunbeam_rhandlers.RelationHandler] = None + ) -> List[sunbeam_rhandlers.RelationHandler]: + """Relation handlers for the service.""" + handlers = handlers or [] + if self.can_add_handler("sunbeam-machine", handlers): + self.sunbeam_machine = SunbeamMachineRequiresHandler( + self, "sunbeam-machine", self.relation_ready, mandatory=True + ) + handlers.append(self.sunbeam_machine) + + return super().get_relation_handlers(handlers) + if __name__ == "__main__": # pragma: nocover ops.main(EpaOrchestratorCharm) diff --git a/charms/epa-orchestrator/tests/unit/test_charm.py b/charms/epa-orchestrator/tests/unit/test_charm.py index b0bb44d2..6a097d52 100644 --- a/charms/epa-orchestrator/tests/unit/test_charm.py +++ b/charms/epa-orchestrator/tests/unit/test_charm.py @@ -86,3 +86,11 @@ class TestEpaOrchestratorCharm(test_utils.CharmTestCase): # Should return None (no-op) self.assertIsNone(result) + + def test_all_relations(self): + """Test that all relation handlers are properly configured.""" + self.harness.begin() + + self.assertFalse(self.harness.charm.sunbeam_machine.ready) + self.harness.add_relation("sunbeam-machine", "sunbeam-machine") + self.assertTrue(self.harness.charm.sunbeam_machine.ready)