diff --git a/shard_core/service/traefik_dynamic_config.py b/shard_core/service/traefik_dynamic_config.py index bab844e..8915c3a 100644 --- a/shard_core/service/traefik_dynamic_config.py +++ b/shard_core/service/traefik_dynamic_config.py @@ -69,6 +69,14 @@ def _add_http_section(model: t.Model, portal: SafeIdentity): service="web-terminal", tls=make_http_cert_resolver(portal), ), + "sundial": t.HttpRouter( + rule="PathPrefix(`/sundial`)", + priority=2, + entryPoints=[http_entrypoint], + service="sundial", + middlewares=["redirect-sundial-slash", "strip-sundial"], + tls=make_http_cert_resolver(portal), + ), "traefik": t.HttpRouter( rule=f"HostRegexp(`traefik.{portal.domain}`)", entryPoints=[http_entrypoint], @@ -84,6 +92,20 @@ def _add_http_section(model: t.Model, portal: SafeIdentity): stripPrefix=t.StripPrefixMiddleware(prefixes=["/core/"]) ) ), + "strip-sundial": t.HttpMiddleware( + root=t.HttpMiddlewareItem21( + stripPrefix=t.StripPrefixMiddleware(prefixes=["/sundial"]) + ) + ), + "redirect-sundial-slash": t.HttpMiddleware( + root=t.HttpMiddlewareItem16( + redirectRegex=t.RedirectRegexMiddleware( + regex="^(https?://[^/]+)/sundial$", + replacement="${1}/sundial/", + permanent=True, + ) + ) + ), "auth-private": t.HttpMiddleware( root=t.HttpMiddlewareItem9( forwardAuth=t.ForwardAuthMiddleware( @@ -147,6 +169,13 @@ def _add_http_section(model: t.Model, portal: SafeIdentity): ) ) ), + "sundial": t.HttpService( + root=t.HttpServiceItem( + loadBalancer=t.HttpLoadBalancerService( + servers=[t.Server(url="http://sundial:80/")] + ) + ) + ), } model.http = t.Http(routers=_routers, middlewares=_middlewares, services=_services) diff --git a/tests/test_traefik_dyn_spec.py b/tests/test_traefik_dyn_spec.py index d379a76..04249e4 100644 --- a/tests/test_traefik_dyn_spec.py +++ b/tests/test_traefik_dyn_spec.py @@ -23,20 +23,34 @@ async def test_template_is_written(api_client): "app-error", "auth", "strip", + "strip-sundial", + "redirect-sundial-slash", "auth-public", "auth-private", "auth-management", } assert "authResponseHeadersRegex" in out_middlewares["auth"]["forwardAuth"] + assert out_middlewares["strip-sundial"]["stripPrefix"]["prefixes"] == [ + "/sundial" + ] + assert out_middlewares["redirect-sundial-slash"]["redirectRegex"] == { + "regex": "^(https?://[^/]+)/sundial$", + "replacement": "${1}/sundial/", + "permanent": True, + } out_services_http: dict = output["http"]["services"] assert set(out_services_http.keys()) == { "shard_core", "web-terminal", + "sundial", "filebrowser_http", "paperless-ngx_http", "immich_http", } + assert out_services_http["sundial"]["loadBalancer"]["servers"] == [ + {"url": "http://sundial:80/"} + ] assert out_services_http["filebrowser_http"]["loadBalancer"]["servers"] == [ {"url": "http://filebrowser:80"} ] @@ -47,6 +61,7 @@ async def test_template_is_written(api_client): "shard_core_public", "shard_core_management", "web-terminal", + "sundial", "traefik", "filebrowser_http", "paperless-ngx_http", @@ -54,6 +69,16 @@ async def test_template_is_written(api_client): } assert out_routers_http["filebrowser_http"]["service"] == "filebrowser_http" + sundial_router = out_routers_http["sundial"] + assert sundial_router["rule"] == "PathPrefix(`/sundial`)" + assert sundial_router["service"] == "sundial" + assert sundial_router["middlewares"] == [ + "redirect-sundial-slash", + "strip-sundial", + ] + assert sundial_router["priority"] > out_routers_http["web-terminal"]["priority"] + assert out_routers_http["web-terminal"]["rule"] == "PathPrefix(`/`)" + def _write_app_meta(app_name: str): app_path = get_installed_apps_path() / app_name