Matthias Nott
2026-02-25 fd03c16eca085423267c163137b28ccb60de8db0
app/routers/services.py
....@@ -1,41 +1,17 @@
1
-import os
1
+import sys
22 from typing import Any
33
4
-import yaml
54 from fastapi import APIRouter, Depends, HTTPException, Query
65
76 from app.auth import verify_token
87 from app.ops_runner import run_command
98
9
+sys.path.insert(0, "/opt/infrastructure")
10
+from toolkit.descriptor import find as find_project # noqa: E402
11
+
1012 router = APIRouter()
1113
1214 _DOCKER = "docker"
13
-_REGISTRY_PATH = os.environ.get(
14
- "REGISTRY_PATH",
15
- "/opt/infrastructure/servers/hetzner-vps/registry.yaml",
16
-)
17
-
18
-# ---------------------------------------------------------------------------
19
-# Registry-based name prefix lookup (cached)
20
-# ---------------------------------------------------------------------------
21
-_prefix_cache: dict[str, str] | None = None
22
-
23
-
24
-def _load_prefixes() -> dict[str, str]:
25
- """Load project -> name_prefix mapping from the ops registry."""
26
- global _prefix_cache
27
- if _prefix_cache is not None:
28
- return _prefix_cache
29
-
30
- try:
31
- with open(_REGISTRY_PATH) as f:
32
- data = yaml.safe_load(f)
33
- _prefix_cache = {}
34
- for proj_name, cfg in data.get("projects", {}).items():
35
- _prefix_cache[proj_name] = cfg.get("name_prefix", proj_name)
36
- return _prefix_cache
37
- except Exception:
38
- return {}
3915
4016
4117 # ---------------------------------------------------------------------------
....@@ -76,33 +52,28 @@
7652 """
7753 Resolve the actual Docker container name from project/env/service.
7854
79
- Uses the ops registry name_prefix mapping and tries patterns in order:
80
- 1. {env}-{prefix}-{service} (mdf, seriousletter: dev-mdf-mysql-UUID)
81
- 2. {prefix}-{service} (ringsaday: ringsaday-website-UUID, coolify: coolify-db)
82
- 3. {prefix}-{env} (ringsaday: ringsaday-dev-UUID)
83
- 4. exact {prefix} (coolify infra: coolify)
55
+ Loads the project descriptor and expands container_prefix for the given
56
+ env (e.g. "{env}-mdf" -> "dev-mdf"), then tries:
57
+ 1. {expanded_prefix}-{service} e.g. dev-mdf-wordpress
58
+ 2. exact match on expanded_prefix (infra containers with no service suffix)
8459 """
85
- prefixes = _load_prefixes()
86
- prefix = prefixes.get(project, project)
60
+ desc = find_project(project)
61
+ if desc is None:
62
+ raise HTTPException(
63
+ status_code=404,
64
+ detail=f"Project '{project}' not found",
65
+ )
8766
88
- # Pattern 1: {env}-{prefix}-{service}
89
- hit = await _find_by_prefix(f"{env}-{prefix}-{service}")
67
+ expanded_prefix = desc.container_prefix_for(env)
68
+
69
+ # Pattern 1: {expanded_prefix}-{service}
70
+ hit = await _find_by_prefix(f"{expanded_prefix}-{service}")
9071 if hit:
9172 return hit
9273
93
- # Pattern 2: {prefix}-{service}
94
- hit = await _find_by_prefix(f"{prefix}-{service}")
95
- if hit:
96
- return hit
97
-
98
- # Pattern 3: {prefix}-{env}
99
- hit = await _find_by_prefix(f"{prefix}-{env}")
100
- if hit:
101
- return hit
102
-
103
- # Pattern 4: exact match when service == prefix (e.g., coolify)
104
- if service == prefix:
105
- hit = await _find_exact(prefix)
74
+ # Pattern 2: exact match on prefix (infrastructure containers, e.g. "coolify")
75
+ if service == expanded_prefix or service == desc.name:
76
+ hit = await _find_exact(expanded_prefix)
10677 if hit:
10778 return hit
10879