Browse Source

Fix missing import in audiencia/views.py; use hostname as default namespace

- sapl/audiencia/views.py: relative import 'from ..utils import ratelimit_ip'
  missed in previous migration; updated to
  'from sapl.middleware.ratelimit import ratelimit_ip'.

- settings.py: POD_NAMESPACE now defaults to `host` (socket.gethostname()
  result already computed at line 29) so bare-metal, VM and docker-compose
  deployments get a meaningful, unique KEY_PREFIX without any extra config.
  K8s deployments override it via POD_NAMESPACE env var (Downward API /
  start.sh service-account detection).

- ratelimit.py: _NAMESPACE = settings.POD_NAMESPACE — single source of
  truth; removes duplicate K8s SA-file reading that settings.py/start.sh
  already handle. Drops now-unused `import os`.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
rate-limiter-2026
Edward Ribeiro 3 weeks ago
parent
commit
2253e8b8f2
  1. 2
      sapl/audiencia/views.py
  2. 17
      sapl/middleware/ratelimit.py
  3. 11
      sapl/settings.py

2
sapl/audiencia/views.py

@ -13,7 +13,7 @@ from ratelimit.decorators import ratelimit
from django.utils.decorators import method_decorator
from ..settings import RATE_LIMITER_RATE
from ..utils import ratelimit_ip
from sapl.middleware.ratelimit import ratelimit_ip
def index(request):

17
sapl/middleware/ratelimit.py

@ -26,7 +26,6 @@ no per-request lookup is needed or correct.
import hashlib
import logging
import os
import time
from django.conf import settings
@ -36,20 +35,12 @@ from django.http import HttpResponse
logger = logging.getLogger('sapl.ratelimit')
# ---------------------------------------------------------------------------
# Tenant namespace — pod-level constant
# Tenant namespace — resolved once at startup from settings.POD_NAMESPACE.
# On K8s: the k8s namespace (e.g. "patobranco-pr"), set by start.sh.
# On bare-metal / VM / docker-compose: the machine hostname (default).
# ---------------------------------------------------------------------------
def _resolve_namespace():
ns = os.environ.get('POD_NAMESPACE', '')
if ns:
return ns
try:
with open('/var/run/secrets/kubernetes.io/serviceaccount/namespace') as f:
return f.read().strip()
except OSError:
return 'global'
_NAMESPACE = _resolve_namespace()
_NAMESPACE = settings.POD_NAMESPACE
# ---------------------------------------------------------------------------
# Redis key templates — module-level constants, never inline strings

11
sapl/settings.py

@ -205,12 +205,13 @@ SPECTACULAR_SETTINGS = {
}
# ---------------------------------------------------------------------------
# Tenant namespace — identifies this pod's municipality (e.g. patobranco-pr).
# Resolved by start.sh from POD_NAMESPACE env var (K8s Downward API) or the
# service-account namespace file, then written into .env before Gunicorn starts.
# Used as KEY_PREFIX so each tenant's cache keys are isolated in shared Redis.
# Tenant namespace — used as Redis KEY_PREFIX and rate-limiter scope.
# Defaults to the machine hostname so self-hosted (bare-metal / VM /
# docker-compose) deployments work without any extra config.
# On Kubernetes, POD_NAMESPACE is set by start.sh via the Downward API or
# the service-account namespace file (e.g. "patobranco-pr").
# ---------------------------------------------------------------------------
POD_NAMESPACE = config('POD_NAMESPACE', default='sapl')
POD_NAMESPACE = config('POD_NAMESPACE', default=host)
# ---------------------------------------------------------------------------
# Cache — switches between file-based (default) and Redis at pod startup.

Loading…
Cancel
Save