Skip to content

Commit 4553f74

Browse files
authored
Merge pull request #19 from westbrook-ai/fix-orchestrator-dns-names
fix: ensure container names don't exceed 63-character DNS label limit
2 parents bce82b9 + e474360 commit 4553f74

File tree

4 files changed

+1124
-863
lines changed

4 files changed

+1124
-863
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "terminals"
3-
version = "0.0.1"
3+
version = "0.0.2"
44
description = "Multi-tenant terminal orchestrator for Open Terminal."
55
readme = "README.md"
66
authors = [

terminals/backends/docker.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
"""Docker backend — provisions Open Terminal inside containers via aiodocker."""
22

33
import asyncio
4+
import hashlib
45
import logging
6+
import re
57
import secrets
68
import time
79
from pathlib import Path
@@ -18,6 +20,7 @@
1820

1921
# Container name prefix used for discovery during reconciliation.
2022
_CONTAINER_PREFIX = "terminals-"
23+
_DNS_SAFE = re.compile(r"[^a-z0-9-]")
2124

2225

2326
class DockerBackend(Backend):
@@ -34,8 +37,12 @@ async def _get_docker(self) -> aiodocker.Docker:
3437

3538
@staticmethod
3639
def _container_name(policy_id: str, user_id: str) -> str:
37-
"""Build the deterministic container name."""
38-
return f"{_CONTAINER_PREFIX}{policy_id}-{user_id}"
40+
"""Build a deterministic, DNS-safe container name (≤63 chars)."""
41+
short = hashlib.sha256(user_id.encode()).hexdigest()[:12]
42+
if policy_id == "default":
43+
return f"{_CONTAINER_PREFIX}{short}"
44+
policy_slug = _DNS_SAFE.sub("-", policy_id.lower()).strip("-")[:20]
45+
return f"{_CONTAINER_PREFIX}{short}-{policy_slug}"
3946

4047
# ------------------------------------------------------------------
4148
# Backend interface

terminals/backends/kubernetes.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import asyncio
44
import base64
5+
import hashlib
56
import logging
67
import re
78
import secrets
@@ -23,10 +24,13 @@
2324
_DNS_SAFE = re.compile(r"[^a-z0-9-]")
2425

2526

26-
def _sanitize_name(user_id: str) -> str:
27-
"""Convert a user ID to a DNS-safe K8s resource name."""
28-
name = _DNS_SAFE.sub("-", user_id.lower()).strip("-")[:53]
29-
return f"terminal-{name}"
27+
def _sanitize_name(user_id: str, policy_id: str = "default") -> str:
28+
"""Deterministic, DNS-safe K8s resource name (≤63 chars)."""
29+
short = hashlib.sha256(user_id.encode()).hexdigest()[:12]
30+
if policy_id == "default":
31+
return f"terminal-{short}"
32+
policy_slug = _DNS_SAFE.sub("-", policy_id.lower()).strip("-")[:20]
33+
return f"terminal-{short}-{policy_slug}"
3034

3135

3236
def _parse_labels() -> dict[str, str]:
@@ -87,9 +91,8 @@ async def provision(
8791
s = spec or {}
8892

8993
api_key = secrets.token_urlsafe(24)
90-
base_name = _sanitize_name(user_id)
94+
name = _sanitize_name(user_id, policy_id)
9195
policy_slug = _DNS_SAFE.sub("-", policy_id.lower()).strip("-")[:20]
92-
name = f"{base_name}-{policy_slug}" if policy_id != "default" else base_name
9396
ns = settings.kubernetes_namespace
9497
labels = _base_labels(user_id)
9598
labels["openwebui.com/policy"] = policy_slug

0 commit comments

Comments
 (0)