diff --git a/README.md b/README.md index 764da06..a46ae34 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # supaspin -Version 1.6.1 +Version 1.6.2 Create, list, show and delete throwaway [Supabase](https://supabase.com) instances on a single-node [microk8s](https://microk8s.io) server, from a terminal menu. diff --git a/VERSION b/VERSION index 9c6d629..fdd3be6 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.6.1 +1.6.2 diff --git a/supaspin b/supaspin index 3ecd6b9..d51b19f 100755 --- a/supaspin +++ b/supaspin @@ -39,7 +39,7 @@ import tty import yaml -VERSION = "1.6.1" +VERSION = "1.6.2" CONFIG_PATH = os.environ.get("SUPASPIN_CONFIG", "/etc/supaspin/config.yaml") STATE_DIR = os.environ.get("SUPASPIN_STATE", "/var/lib/supaspin") CHART_REPO = "https://supabase-community.github.io/supabase-kubernetes" @@ -189,24 +189,27 @@ def buffering_middleware(n): def ingress_annotations(cfg, n): - """Ingress annotations for instance n, shaped for the configured ingress controller. - With Traefik the upload cap lives in a Middleware object created next to the instance - and the ingress points at it; with nginx it is proxy-body-size, and the chart's own - rewrite-target default must be nullified or every API path breaks. The cert-manager - annotation orders a certificate from the supaspin-letsencrypt issuer; without it the - TLS secret keeps whatever supaspin put there (a saved or a self-signed certificate).""" + """Ingress annotations for instance n. + Both controllers' annotations are always present: an annotation only takes effect + when a controller of that family actually routes the ingress, so on a Traefik + cluster the nginx keys sit inert (and vice versa) and nothing needs reconfiguring + when the router changes. The upload cap therefore lives in two places that agree: + proxy-body-size for nginx, and the Middleware object the traefik annotation points + at. The chart's own rewrite-target default must be nullified or every API path + breaks. The cert-manager annotation orders a certificate from the + supaspin-letsencrypt issuer; without it the TLS secret keeps whatever supaspin put + there (a saved or a self-signed certificate).""" anns = {} if cfg.get("lets_encrypt", True): anns["cert-manager.io/cluster-issuer"] = ISSUER + # The chart default rewrites every path to "/", which breaks all APIs; null removes it. + anns["nginx.ingress.kubernetes.io/rewrite-target"] = None + anns["nginx.ingress.kubernetes.io/proxy-body-size"] = "50m" + anns["nginx.ingress.kubernetes.io/proxy-read-timeout"] = "3600" + anns["nginx.ingress.kubernetes.io/proxy-send-timeout"] = "3600" if cfg.get("ingress_controller", "nginx") == "traefik": anns["traefik.ingress.kubernetes.io/router.middlewares"] = \ f"{namespace(n)}-{buffering_middleware(n)}@kubernetescrd" - else: - # The chart default rewrites every path to "/", which breaks all APIs; null removes it. - anns["nginx.ingress.kubernetes.io/rewrite-target"] = None - anns["nginx.ingress.kubernetes.io/proxy-body-size"] = "50m" - anns["nginx.ingress.kubernetes.io/proxy-read-timeout"] = "3600" - anns["nginx.ingress.kubernetes.io/proxy-send-timeout"] = "3600" return anns diff --git a/tests/test_supaspin.py b/tests/test_supaspin.py index e3c7fb4..25d75b2 100644 --- a/tests/test_supaspin.py +++ b/tests/test_supaspin.py @@ -216,13 +216,15 @@ class IngressShaping(unittest.TestCase): self.assertEqual(a["nginx.ingress.kubernetes.io/proxy-read-timeout"], "3600") self.assertNotIn("traefik.ingress.kubernetes.io/router.middlewares", a) - def test_traefik_native(self): + def test_traefik_also_keeps_nginx_annotations(self): + # The nginx keys must be present in traefik mode too: while nginx routes the + # ingress they enforce the cap, and they are inert the day Traefik takes over. a = self.ann({"ingress_controller": "traefik"}) self.assertEqual(a["traefik.ingress.kubernetes.io/router.middlewares"], "supaspin-2-supa2-buffering@kubernetescrd") - for nginx_key in ("rewrite-target", "proxy-body-size", "proxy-read-timeout", - "proxy-send-timeout"): - self.assertNotIn(f"nginx.ingress.kubernetes.io/{nginx_key}", a) + self.assertIsNone(a["nginx.ingress.kubernetes.io/rewrite-target"]) + self.assertEqual(a["nginx.ingress.kubernetes.io/proxy-body-size"], "50m") + self.assertEqual(a["nginx.ingress.kubernetes.io/proxy-read-timeout"], "3600") self.assertEqual(a["cert-manager.io/cluster-issuer"], "supaspin-letsencrypt") def test_lets_encrypt_off_drops_cert_manager_annotation(self):