diff --git a/src/charm.py b/src/charm.py index 9e3e0d9..10ad1fb 100755 --- a/src/charm.py +++ b/src/charm.py @@ -11,7 +11,7 @@ from charms.nginx_ingress_integrator.v0.nginx_route import require_nginx_route from jinja2 import Environment, FileSystemLoader -from ops import main +from ops import main, pebble from ops.charm import CharmBase from ops.model import ActiveStatus, BlockedStatus, MaintenanceStatus, WaitingStatus from ops.pebble import CheckStatus @@ -158,13 +158,33 @@ def _on_update_status(self, event): return container = self.unit.get_container(self.name) + valid_pebble_plan = self._validate_pebble_plan(container) + if not valid_pebble_plan: + self._update(event) + return check = container.get_check("up") if check.status != CheckStatus.UP: self.unit.status = MaintenanceStatus("Status check: DOWN") return - self.unit.status = ActiveStatus() + message = "auth enabled" if self.config["auth-enabled"] else "" + self.unit.status = ActiveStatus(message) + + def _validate_pebble_plan(self, container): + """Validate Temporal UI pebble plan. + + Args: + container: application container + + Returns: + bool of pebble plan validity + """ + try: + plan = container.get_plan().to_dict() + return bool(plan and plan["services"].get(self.name, {}).get("on-check-failure")) + except pebble.ConnectionError: + return False @log_event_handler(logger) def _on_ui_relation_joined(self, event): diff --git a/tests/unit/test_charm.py b/tests/unit/test_charm.py index c754bdb..d03757e 100644 --- a/tests/unit/test_charm.py +++ b/tests/unit/test_charm.py @@ -20,6 +20,7 @@ APP_NAME = "temporal-ui" UI_PORT = "8080" +mock_incomplete_pebble_plan = {"services": {"temporal-ui": {"override": "replace"}}} class TestCharm(TestCase): @@ -242,6 +243,37 @@ def test_update_status_down(self): self.assertEqual(harness.model.unit.status, MaintenanceStatus("Status check: DOWN")) + def test_incomplete_pebble_plan(self): + """The charm re-applies the pebble plan if incomplete.""" + harness = self.harness + simulate_lifecycle(harness) + + container = harness.model.unit.get_container("temporal-ui") + container.add_layer("temporal-ui", mock_incomplete_pebble_plan, combine=True) + harness.charm.on.update_status.emit() + + self.assertEqual( + harness.model.unit.status, + MaintenanceStatus("replanning application"), + ) + plan = harness.get_container_pebble_plan("temporal-ui").to_dict() + assert plan != mock_incomplete_pebble_plan + + @mock.patch("charm.TemporalUiK8SOperatorCharm._validate_pebble_plan", return_value=True) + def test_missing_pebble_plan(self, mock_validate_pebble_plan): + """The charm re-applies the pebble plan if missing.""" + harness = self.harness + simulate_lifecycle(harness) + + mock_validate_pebble_plan.return_value = False + harness.charm.on.update_status.emit() + self.assertEqual( + harness.model.unit.status, + MaintenanceStatus("replanning application"), + ) + plan = harness.get_container_pebble_plan("temporal-ui").to_dict() + assert plan is not None + def simulate_lifecycle(harness): """Simulate a healthy charm life-cycle.