prole/tests/test_render_supabase_hostname.py
chrisfu 35299fdd52 chore: add hostPath jemalloc optimization and enhance monitoring storage class handling
- Introduced jemalloc hostPath optimizations with configurable modes (`auto`, `off`, `force`).
- Integrated jemalloc setup with best-effort and forced validation flows for ensuring cluster compatibility.
- Enhanced monitoring storage class logic with mode-specific handling (`k3s`, `k3d`, `gke`) and improved validation of required classes.
- Added safeguards and detailed logging for unsupported configurations and failure scenarios.
2026-04-12 21:20:05 -07:00

295 lines
11 KiB
Python

from __future__ import annotations
import importlib.util
from argparse import Namespace
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[1]
_RENDER_PATH = REPO_ROOT / "supabase" / "helm" / "render_supabase.py"
def _load_render_module():
spec = importlib.util.spec_from_file_location("prole_render_supabase", _RENDER_PATH)
assert spec is not None and spec.loader is not None
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
return module
_render_mod = _load_render_module()
_build_overlay = _render_mod._build_overlay
_read_cfg = _render_mod._read_cfg
_split_frontdoor_docs = _render_mod._split_frontdoor_docs
def _write_cfg(path: Path, content: str) -> None:
path.write_text(content.strip() + "\n", encoding="utf-8")
def test_render_supabase_uses_supabase_hostname_for_public_urls(tmp_path: Path, monkeypatch):
# Ensure env doesn't interfere with config-driven behavior.
monkeypatch.delenv("SUPABASE_HOST", raising=False)
monkeypatch.delenv("SUPABASE_HOSTNAME", raising=False)
monkeypatch.delenv("KNOE_DB_NAMESPACE", raising=False)
monkeypatch.delenv("KNOE_DB_SERVICE", raising=False)
cfg_path = tmp_path / "prole.cfg"
_write_cfg(
cfg_path,
"""
[User]
supabase_hostname = db.prole.org
[Inputs]
init_password.db_password = test-password
init_password.db_host_port = 5432
[Global]
NAMESPACE = test-ns
STORAGE_BACKEND = local
""",
)
cfg = _read_cfg(cfg_path)
args = Namespace(output_dir=str(tmp_path / "gen"), manifests_dir=str(tmp_path / "k8s"))
overlay, _meta = _build_overlay(cfg, args)
assert overlay["ingress"]["hosts"][0]["host"] == "db.prole.org"
assert overlay["environment"]["auth"]["API_EXTERNAL_URL"] == "https://db.prole.org"
assert overlay["environment"]["auth"]["GOTRUE_SITE_URL"] == "https://db.prole.org"
assert overlay["environment"]["studio"]["SUPABASE_PUBLIC_URL"] == "https://db.prole.org"
def test_render_supabase_allows_scheme_in_supabase_hostname(tmp_path: Path, monkeypatch):
monkeypatch.delenv("SUPABASE_HOST", raising=False)
monkeypatch.delenv("SUPABASE_HOSTNAME", raising=False)
monkeypatch.delenv("KNOE_DB_NAMESPACE", raising=False)
monkeypatch.delenv("KNOE_DB_SERVICE", raising=False)
cfg_path = tmp_path / "prole.cfg"
_write_cfg(
cfg_path,
"""
[User]
supabase_hostname = http://db.prole.org
[Inputs]
init_password.db_password = test-password
init_password.db_host_port = 5432
[Global]
NAMESPACE = test-ns
STORAGE_BACKEND = local
""",
)
cfg = _read_cfg(cfg_path)
args = Namespace(output_dir=str(tmp_path / "gen"), manifests_dir=str(tmp_path / "k8s"))
overlay, _meta = _build_overlay(cfg, args)
assert overlay["ingress"]["hosts"][0]["host"] == "db.prole.org"
assert overlay["environment"]["auth"]["API_EXTERNAL_URL"] == "http://db.prole.org"
assert overlay["environment"]["studio"]["SUPABASE_PUBLIC_URL"] == "http://db.prole.org"
def test_render_supabase_splits_api_and_studio_hosts_for_k8s(tmp_path: Path, monkeypatch):
monkeypatch.delenv("SUPABASE_HOST", raising=False)
monkeypatch.delenv("SUPABASE_HOSTNAME", raising=False)
monkeypatch.delenv("KNOE_DB_NAMESPACE", raising=False)
monkeypatch.delenv("KNOE_DB_SERVICE", raising=False)
cfg_path = tmp_path / "prole.cfg"
_write_cfg(
cfg_path,
"""
[Inputs]
init_password.db_password = test-password
init_password.db_host_port = 5432
[Global]
NAMESPACE = test-ns
DEPLOYMENT_MODE = k8s
SUPABASE_API_HOSTNAME = api.0.knoe.dev
SUPABASE_STUDIO_HOSTNAME = db.0.knoe.dev
STORAGE_BACKEND = local
""",
)
cfg = _read_cfg(cfg_path)
args = Namespace(output_dir=str(tmp_path / "gen"), manifests_dir=str(tmp_path / "k8s"))
overlay, _meta = _build_overlay(cfg, args)
assert overlay["ingress"]["hosts"][0]["host"] == "api.0.knoe.dev"
assert overlay["studioIngress"]["hosts"][0]["host"] == "db.0.knoe.dev"
assert overlay["ingress"]["className"] == "gce"
assert overlay["studioIngress"]["className"] == "gce"
assert overlay["environment"]["auth"]["API_EXTERNAL_URL"] == "https://api.0.knoe.dev"
assert overlay["environment"]["auth"]["GOTRUE_SITE_URL"] == "https://db.0.knoe.dev"
assert overlay["environment"]["studio"]["SUPABASE_PUBLIC_URL"] == "https://db.0.knoe.dev"
assert overlay["environment"]["auth"]["GOTRUE_URI_ALLOW_LIST"] == (
"https://db.0.knoe.dev/**,https://api.0.knoe.dev/**"
)
def test_render_supabase_derives_env_indexed_api_host_for_k8s(tmp_path: Path, monkeypatch):
monkeypatch.delenv("SUPABASE_HOST", raising=False)
monkeypatch.delenv("SUPABASE_HOSTNAME", raising=False)
monkeypatch.delenv("SUPABASE_API_HOSTNAME", raising=False)
monkeypatch.delenv("KNOE_DB_NAMESPACE", raising=False)
monkeypatch.delenv("KNOE_DB_SERVICE", raising=False)
cfg_path = tmp_path / "prole.cfg"
_write_cfg(
cfg_path,
"""
[Inputs]
init_password.db_password = test-password
init_password.db_host_port = 5432
[Global]
NAMESPACE = test-ns
DEPLOYMENT_MODE = k8s
AUTH_HOSTNAME = api.knoe.dev
SUPABASE_STUDIO_HOSTNAME = db.33.knoe.dev
STORAGE_BACKEND = local
""",
)
cfg = _read_cfg(cfg_path)
args = Namespace(output_dir=str(tmp_path / "gen"), manifests_dir=str(tmp_path / "k8s"))
overlay, _meta = _build_overlay(cfg, args)
assert overlay["ingress"]["hosts"][0]["host"] == "api.33.knoe.dev"
assert overlay["studioIngress"]["hosts"][0]["host"] == "db.33.knoe.dev"
assert overlay["environment"]["auth"]["API_EXTERNAL_URL"] == "https://api.33.knoe.dev"
assert overlay["environment"]["auth"]["GOTRUE_SITE_URL"] == "https://db.33.knoe.dev"
assert overlay["environment"]["auth"]["GOTRUE_URI_ALLOW_LIST"] == (
"https://db.33.knoe.dev/**,https://api.33.knoe.dev/**"
)
def test_render_supabase_rejects_duplicate_api_and_studio_host_claims(tmp_path: Path, monkeypatch):
monkeypatch.delenv("SUPABASE_HOST", raising=False)
monkeypatch.delenv("SUPABASE_HOSTNAME", raising=False)
monkeypatch.delenv("KNOE_DB_NAMESPACE", raising=False)
monkeypatch.delenv("KNOE_DB_SERVICE", raising=False)
cfg_path = tmp_path / "prole.cfg"
_write_cfg(
cfg_path,
"""
[Inputs]
init_password.db_password = test-password
init_password.db_host_port = 5432
[Global]
NAMESPACE = test-ns
DEPLOYMENT_MODE = k8s
SUPABASE_API_HOSTNAME = db.0.knoe.dev
SUPABASE_STUDIO_HOSTNAME = db.0.knoe.dev
STORAGE_BACKEND = local
""",
)
cfg = _read_cfg(cfg_path)
args = Namespace(output_dir=str(tmp_path / "gen"), manifests_dir=str(tmp_path / "k8s"))
try:
_build_overlay(cfg, args)
except SystemExit as exc:
assert "Duplicate ingress host/path claim detected" in str(exc)
else:
raise AssertionError("Expected duplicate host/path guardrail to abort")
def test_render_supabase_allows_db_cluster_context_for_public_ingress(tmp_path: Path, monkeypatch):
monkeypatch.delenv("SUPABASE_HOST", raising=False)
monkeypatch.delenv("SUPABASE_HOSTNAME", raising=False)
monkeypatch.delenv("KNOE_DB_NAMESPACE", raising=False)
monkeypatch.delenv("KNOE_DB_SERVICE", raising=False)
monkeypatch.setenv("KUBECONTEXT", "knoe-dev-cnpg-0")
cfg_path = tmp_path / "prole.cfg"
_write_cfg(
cfg_path,
"""
[Inputs]
init_password.db_password = test-password
init_password.db_host_port = 5432
init_cluster.app_cluster_kubecontext = knoe-dev-0
init_cluster.db_cluster_kubecontext = knoe-dev-cnpg-0
[Global]
NAMESPACE = test-ns
DEPLOYMENT_MODE = k8s
SUPABASE_API_HOSTNAME = api.0.knoe.dev
SUPABASE_STUDIO_HOSTNAME = db.0.knoe.dev
STORAGE_BACKEND = local
""",
)
cfg = _read_cfg(cfg_path)
args = Namespace(output_dir=str(tmp_path / "gen"), manifests_dir=str(tmp_path / "k8s"))
overlay, _meta = _build_overlay(cfg, args)
assert overlay["ingress"]["hosts"][0]["host"] == "api.0.knoe.dev"
assert overlay["studioIngress"]["hosts"][0]["host"] == "db.0.knoe.dev"
def test_render_supabase_rejects_traefik_class_in_k8s_without_opt_in(tmp_path: Path, monkeypatch):
monkeypatch.delenv("SUPABASE_HOST", raising=False)
monkeypatch.delenv("SUPABASE_HOSTNAME", raising=False)
monkeypatch.delenv("KNOE_DB_NAMESPACE", raising=False)
monkeypatch.delenv("KNOE_DB_SERVICE", raising=False)
cfg_path = tmp_path / "prole.cfg"
_write_cfg(
cfg_path,
"""
[Inputs]
init_password.db_password = test-password
init_password.db_host_port = 5432
[Global]
NAMESPACE = test-ns
DEPLOYMENT_MODE = k8s
SUPABASE_API_HOSTNAME = api.0.knoe.dev
SUPABASE_STUDIO_HOSTNAME = db.0.knoe.dev
SUPABASE_INGRESS_CLASS = traefik
STORAGE_BACKEND = local
""",
)
cfg = _read_cfg(cfg_path)
args = Namespace(output_dir=str(tmp_path / "gen"), manifests_dir=str(tmp_path / "k8s"))
try:
_build_overlay(cfg, args)
except SystemExit as exc:
assert "incompatible with k8s mode" in str(exc)
else:
raise AssertionError("Expected ingress-class guardrail to abort")
def test_render_supabase_splits_frontdoor_manifests_for_db_cluster_rollout():
rendered_manifest = "\n---\n".join(
(
'{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"name":"supabase-auth","namespace":"supabase"}}',
'{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"name":"supabase-kong","namespace":"supabase"}}',
'{"apiVersion":"v1","kind":"Service","metadata":{"name":"supabase-kong","namespace":"supabase"}}',
'{"apiVersion":"networking.k8s.io/v1","kind":"Ingress","metadata":{"name":"supabase-kong","namespace":"supabase"}}',
'{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"name":"supabase-studio","namespace":"supabase"}}',
'{"apiVersion":"networking.k8s.io/v1","kind":"Ingress","metadata":{"name":"supabase-studio","namespace":"supabase"}}',
)
)
app_docs, frontdoor_docs = _split_frontdoor_docs(rendered_manifest)
app_names = {doc["metadata"]["name"] for doc in app_docs}
frontdoor_names = {doc["metadata"]["name"] for doc in frontdoor_docs}
assert "supabase-auth" in app_names
assert "supabase-kong" in frontdoor_names
assert "supabase-studio" in frontdoor_names