diff --git a/ops-sunbeam/ops_sunbeam/charm.py b/ops-sunbeam/ops_sunbeam/charm.py index d6827f9b..192258b2 100644 --- a/ops-sunbeam/ops_sunbeam/charm.py +++ b/ops-sunbeam/ops_sunbeam/charm.py @@ -636,6 +636,11 @@ class OSBaseOperatorCharmK8S(OSBaseOperatorCharm): super().__post_init__() self.pebble_handlers = self.get_pebble_handlers() + @property + def service_dns(self) -> str: + """Dns name for the service.""" + return f"{self.app.name}.{self.model.name}.svc" + def get_pebble_handlers(self) -> List[sunbeam_chandlers.PebbleHandler]: """Pebble handlers for the operator.""" return [ @@ -1025,15 +1030,16 @@ class OSBaseOperatorAPICharm(OSBaseOperatorCharmK8S): @property def admin_url(self) -> str: - """Url for accessing the admin endpoint for this service.""" + """Url for accessing the admin endpoint for this service. + + Fallback to k8s resolvable hostname if no identity-service relation. + """ binding = self.model.get_binding("identity-service") if binding and binding.network and binding.network.ingress_address: return self.add_explicit_port( self.service_url(str(binding.network.ingress_address)) ) - raise sunbeam_guard.WaitingExceptionError( - "No admin address found for service" - ) + return self.add_explicit_port(self.service_url(self.service_dns)) @property def internal_url(self) -> str: @@ -1052,9 +1058,7 @@ class OSBaseOperatorAPICharm(OSBaseOperatorCharmK8S): return self.add_explicit_port( self.service_url(str(binding.network.ingress_address)) ) - raise sunbeam_guard.WaitingExceptionError( - "No internal address found for service" - ) + return self.add_explicit_port(self.service_url(self.service_dns)) def get_pebble_handlers(self) -> list[sunbeam_chandlers.PebbleHandler]: """Pebble handlers for the service.""" diff --git a/ops-sunbeam/ops_sunbeam/core.py b/ops-sunbeam/ops_sunbeam/core.py index e2fb7b40..4017bfd0 100644 --- a/ops-sunbeam/ops_sunbeam/core.py +++ b/ops-sunbeam/ops_sunbeam/core.py @@ -25,9 +25,6 @@ from typing import ( ) import ops_sunbeam.tracing as sunbeam_tracing -from ops_sunbeam.guard import ( - BaseStatusExceptionError, -) if TYPE_CHECKING: from ops_sunbeam.charm import ( @@ -104,20 +101,5 @@ class PostInitMeta(type): def __call__(cls, *args, **kw): """Call __post_init__ after __init__.""" instance = super().__call__(*args, **kw) - try: - instance.__post_init__() - except BaseStatusExceptionError as e: - # Allow post init to raise an ops_sunbeam status - # exception without causing the charm to error. - # This status will be collected and set on the - # unit. - # import here to avoid circular import - from ops_sunbeam.charm import ( - OSBaseOperatorCharm, - ) - - if isinstance(instance, OSBaseOperatorCharm): - instance.status.set(e.to_status()) - else: - raise e + instance.__post_init__() return instance diff --git a/ops-sunbeam/tests/unit_tests/test_core.py b/ops-sunbeam/tests/unit_tests/test_core.py index ce42d8e8..9cb62cf5 100644 --- a/ops-sunbeam/tests/unit_tests/test_core.py +++ b/ops-sunbeam/tests/unit_tests/test_core.py @@ -484,6 +484,77 @@ class TestOSBaseOperatorAPICharm(_TestOSBaseOperatorAPICharm): "https://test.org:8443/something", ) + def test_admin_url_id_svc(self): + """Test admin_url with service ID.""" + test_utils.add_complete_identity_relation(self.harness) + self.assertEqual( + self.harness.charm.admin_url, + "http://10.0.0.10:789", + ) + + def test_admin_url_fallback_to_service_dns(self): + """Test admin_url fallback to service DNS.""" + with patch.object( + self.harness.charm.model, + "get_binding", + MagicMock(return_value=None), + ): + self.assertEqual( + self.harness.charm.admin_url, + "http://my-service.test-model.svc:789", + ) + + def test_internal_url_ingress_internal(self): + """Test internal_url with internal ingress.""" + test_utils.add_complete_ingress_relation(self.harness) + self.assertEqual( + self.harness.charm.internal_url, + "http://internal-url:80/", + ) + + def test_internal_url_fallback_to_id_svc(self): + """Test internal_url with service ID.""" + test_utils.add_complete_identity_relation(self.harness) + self.assertEqual( + self.harness.charm.internal_url, + "http://10.0.0.10:789", + ) + + def test_internal_url_fallback_to_service_dns(self): + """Test internal fallback to service DNS.""" + with patch.object( + self.harness.charm.model, + "get_binding", + MagicMock(return_value=None), + ): + self.assertEqual( + self.harness.charm.internal_url, + "http://my-service.test-model.svc:789", + ) + + def test_public_url_ingress_public(self): + """Test public_url with public ingress.""" + test_utils.add_complete_ingress_relation(self.harness) + self.assertEqual( + self.harness.charm.public_url, + "http://public-url:80/", + ) + + def test_public_url_fallback_to_internal(self): + """Test public_url fallback to internal.""" + self.assertEqual( + self.harness.charm.public_url, + self.harness.charm.internal_url, + ) + + def test_public_url_attribute_error(self): + """Test public_url with attribute error.""" + del self.harness.charm.ingress_public + self.assertEqual( + self.harness.charm.public_url, + self.harness.charm.internal_url, + ) + class TestOSBaseOperatorMultiSVCAPICharm(_TestOSBaseOperatorAPICharm): """Test Charm with multiple services."""