diff --git a/src/charm.py b/src/charm.py index 277722ee..b684d40c 100755 --- a/src/charm.py +++ b/src/charm.py @@ -1359,6 +1359,9 @@ def _provide_all_haproxy_route_requirements(self) -> None: paths=appserver_paths, protocol="http", check_path="/", + check_interval=2, + check_rise=2, + check_fall=3, header_rewrite_expressions=forwarded_proto_https, allow_http=allow_http_default, unit_address=unit_ip, @@ -1382,6 +1385,9 @@ def _provide_all_haproxy_route_requirements(self) -> None: paths=["/ping"], protocol="http", check_path="/ping", + check_interval=2, + check_rise=2, + check_fall=3, header_rewrite_expressions=forwarded_proto_https, allow_http=allow_http_always, unit_address=unit_ip, @@ -1393,6 +1399,9 @@ def _provide_all_haproxy_route_requirements(self) -> None: paths=["/message-system", "/attachment"], protocol="http", check_path="/message-system", + check_interval=2, + check_rise=2, + check_fall=3, header_rewrite_expressions=forwarded_proto_https, allow_http=allow_http_default, unit_address=unit_ip, @@ -1403,7 +1412,10 @@ def _provide_all_haproxy_route_requirements(self) -> None: ports=api_ports, paths=["/api"], protocol="http", - check_path="/api", + check_path="/api/about", + check_interval=2, + check_rise=2, + check_fall=3, header_rewrite_expressions=forwarded_proto_https, allow_http=allow_http_default, unit_address=unit_ip, @@ -1415,7 +1427,7 @@ def _provide_all_haproxy_route_requirements(self) -> None: paths=["/upload"], protocol="http", check_path="/upload", - check_interval=2000, + check_interval=2, check_rise=2, check_fall=3, header_rewrite_expressions=forwarded_proto_https, @@ -1432,7 +1444,6 @@ def _provide_all_haproxy_route_requirements(self) -> None: ports=appserver_ports, paths=["/repository"], protocol="http", - check_path="/", header_rewrite_expressions=forwarded_proto_https, allow_http=allow_http_always, unit_address=unit_ip, diff --git a/tests/unit/test_haproxy_route.py b/tests/unit/test_haproxy_route.py index 1e40ed68..884014ff 100644 --- a/tests/unit/test_haproxy_route.py +++ b/tests/unit/test_haproxy_route.py @@ -183,7 +183,7 @@ def test_package_upload_has_health_checks(self, replicas_network_state): mock = _run_provide(context, state) calls = _calls_for(mock, "package-upload") assert calls - assert calls[0].kwargs.get("check_interval") == 2000 + assert calls[0].kwargs.get("check_interval") == 2 assert calls[0].kwargs.get("check_rise") == 2 assert calls[0].kwargs.get("check_fall") == 3 @@ -252,6 +252,98 @@ def test_pingserver_service_name_prefix(self, replicas_network_state): assert calls[0].kwargs["service"].startswith("landscape-pingserver-") +class TestHealthChecks: + """Each route uses check_path with the path the backend actually serves.""" + + def test_no_check_port_on_any_route(self, replicas_network_state): + context = Context(LandscapeServerCharm) + state = State(**replicas_network_state) + mock = _run_provide(context, state) + for c in mock.call_args_list: + assert "check_port" not in c.kwargs, ( + f"check_port should not be set for {c.kwargs.get('service')}" + ) + + def test_appserver_check_path(self, replicas_network_state): + context = Context(LandscapeServerCharm) + state = State(**replicas_network_state) + mock = _run_provide(context, state) + calls = _calls_for(mock, "appserver") + assert calls[0].kwargs.get("check_path") == "/" + + def test_pingserver_check_path(self, replicas_network_state): + context = Context(LandscapeServerCharm) + state = State(**replicas_network_state) + mock = _run_provide(context, state) + calls = _calls_for(mock, "pingserver") + assert calls[0].kwargs.get("check_path") == "/ping" + + def test_message_server_check_path(self, replicas_network_state): + context = Context(LandscapeServerCharm) + state = State(**replicas_network_state) + mock = _run_provide(context, state) + calls = _calls_for(mock, "message-server") + assert calls[0].kwargs.get("check_path") == "/message-system" + + def test_api_check_path(self, replicas_network_state): + context = Context(LandscapeServerCharm) + state = State(**replicas_network_state) + mock = _run_provide(context, state) + calls = _calls_for(mock, "api") + assert calls[0].kwargs.get("check_path") == "/api/about" + + def test_package_upload_check_path(self, replicas_network_state): + context = Context(LandscapeServerCharm) + state = State(**replicas_network_state) + mock = _run_provide(context, state) + calls = _calls_for(mock, "package-upload") + assert calls[0].kwargs.get("check_path") == "/upload" + + def test_repository_has_no_health_check(self, replicas_network_state): + context = Context(LandscapeServerCharm) + state = State(**replicas_network_state) + mock = _run_provide(context, state) + calls = _calls_for(mock, "repository") + assert "check_path" not in calls[0].kwargs + assert "check_interval" not in calls[0].kwargs + + def test_appserver_has_health_check_timing(self, replicas_network_state): + context = Context(LandscapeServerCharm) + state = State(**replicas_network_state) + mock = _run_provide(context, state) + calls = _calls_for(mock, "appserver") + assert calls[0].kwargs.get("check_interval") == 2 + assert calls[0].kwargs.get("check_rise") == 2 + assert calls[0].kwargs.get("check_fall") == 3 + + def test_pingserver_has_health_check_timing(self, replicas_network_state): + context = Context(LandscapeServerCharm) + state = State(**replicas_network_state) + mock = _run_provide(context, state) + calls = _calls_for(mock, "pingserver") + assert calls[0].kwargs.get("check_interval") == 2 + assert calls[0].kwargs.get("check_rise") == 2 + assert calls[0].kwargs.get("check_fall") == 3 + + def test_message_server_has_health_check_timing(self, replicas_network_state): + context = Context(LandscapeServerCharm) + state = State(**replicas_network_state) + mock = _run_provide(context, state) + calls = _calls_for(mock, "message-server") + assert calls[0].kwargs.get("check_interval") == 2 + assert calls[0].kwargs.get("check_rise") == 2 + assert calls[0].kwargs.get("check_fall") == 3 + + def test_api_has_health_check_timing(self, replicas_network_state): + context = Context(LandscapeServerCharm) + state = State(**replicas_network_state) + mock = _run_provide(context, state) + calls = _calls_for(mock, "api") + assert calls[0].kwargs.get("check_interval") == 2 + assert calls[0].kwargs.get("check_rise") == 2 + assert calls[0].kwargs.get("check_fall") == 3 + + class TestConditionalRoutes: """hostagent-messenger and ubuntu-installer-attach routes are conditional."""