Initial import: bare-metal stacks, Server UI, GPU fan, tutorials.
Infrastructure configs for GMKtec K11 (Docker, vLLM, LocalAI, ComfyUI, control-plane, gpu-fan agent, Server UI with CLI/file explorer/GPU fan curve). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
"""Load unified control-plane environment from file + os.environ."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
_ENV_OVERRIDE_KEYS = (
|
||||
"API_KEY",
|
||||
"SERVER_UI_HOST",
|
||||
"SERVER_UI_PORT",
|
||||
"REPO_ROOT",
|
||||
"DOCKER_GID",
|
||||
"GPU_FAN_AGENT_URL",
|
||||
"GPU_FAN_API_HOST",
|
||||
"GPU_FAN_API_PORT",
|
||||
"GPU_FAN_HOST",
|
||||
"GPU_FAN_PORT",
|
||||
"CURVE_PATH",
|
||||
"POLL_INTERVAL",
|
||||
"GPU_INDEX",
|
||||
"DRY_RUN",
|
||||
"FILE_EXPLORER_ROOT",
|
||||
"FILE_EXPLORER_MAX_BYTES",
|
||||
"CLI_ENABLED",
|
||||
"CLI_SHELL",
|
||||
"CLI_DEFAULT_CWD",
|
||||
"CLI_MAX_SESSIONS",
|
||||
)
|
||||
|
||||
|
||||
def _parse_env_file(path: Path) -> dict[str, str]:
|
||||
values: dict[str, str] = {}
|
||||
if not path.is_file():
|
||||
return values
|
||||
try:
|
||||
text = path.read_text(encoding="utf-8")
|
||||
except OSError:
|
||||
# e.g. /opt/control-plane/.env is root-only; systemd still injects via os.environ
|
||||
return values
|
||||
for line in text.splitlines():
|
||||
line = line.strip()
|
||||
if not line or line.startswith("#") or "=" not in line:
|
||||
continue
|
||||
key, _, val = line.partition("=")
|
||||
values[key.strip()] = val.strip()
|
||||
return values
|
||||
|
||||
|
||||
def _merge_into(target: dict[str, str], source: dict[str, str]) -> None:
|
||||
for key, val in source.items():
|
||||
if val:
|
||||
target[key] = val
|
||||
|
||||
|
||||
def _is_production_stack_dir(stack_dir: Path) -> bool:
|
||||
try:
|
||||
return stack_dir.resolve().parts[1:2] == ("opt",)
|
||||
except IndexError:
|
||||
return False
|
||||
|
||||
|
||||
def control_plane_env_paths(stack_dir: Path) -> list[Path]:
|
||||
"""Candidate .env files in load order (earlier = lower priority among files)."""
|
||||
paths: list[Path] = []
|
||||
custom = os.environ.get("CONTROL_PLANE_ENV", "").strip()
|
||||
if custom:
|
||||
paths.append(Path(custom))
|
||||
|
||||
if _is_production_stack_dir(stack_dir):
|
||||
# Production (/opt/server-ui, /opt/gpu-fan): single canonical file only.
|
||||
prod = Path("/opt/control-plane/.env")
|
||||
if prod not in paths:
|
||||
paths.append(prod)
|
||||
docker_repo = Path("/repo/stacks/control-plane/.env")
|
||||
if docker_repo.is_file() and docker_repo not in paths:
|
||||
paths.append(docker_repo)
|
||||
return paths
|
||||
|
||||
# Dev (repo stacks/*): stacks/control-plane/.env only — no legacy per-service .env.
|
||||
repo_control_plane = stack_dir.parent / "control-plane" / ".env"
|
||||
if repo_control_plane.is_file() and repo_control_plane not in paths:
|
||||
paths.append(repo_control_plane)
|
||||
docker_repo = Path("/repo/stacks/control-plane/.env")
|
||||
if docker_repo.is_file() and docker_repo not in paths:
|
||||
paths.append(docker_repo)
|
||||
return paths
|
||||
|
||||
|
||||
def api_key_source(stack_dir: Path, values: dict[str, str]) -> str:
|
||||
"""Human-readable hint for logs (no secret values)."""
|
||||
if os.environ.get("API_KEY"):
|
||||
return "systemd/os.environ"
|
||||
for path in control_plane_env_paths(stack_dir):
|
||||
parsed = _parse_env_file(path)
|
||||
if parsed.get("API_KEY"):
|
||||
return str(path)
|
||||
if values.get("API_KEY"):
|
||||
return "merged env"
|
||||
return "not configured"
|
||||
|
||||
|
||||
def load_control_plane_env(stack_dir: Path) -> dict[str, str]:
|
||||
"""Merge env files then apply os.environ (systemd EnvironmentFile wins)."""
|
||||
values: dict[str, str] = {}
|
||||
for path in control_plane_env_paths(stack_dir):
|
||||
_merge_into(values, _parse_env_file(path))
|
||||
|
||||
for key in _ENV_OVERRIDE_KEYS:
|
||||
if key in os.environ:
|
||||
values[key] = os.environ[key]
|
||||
|
||||
values.setdefault("GPU_FAN_AGENT_URL", "http://127.0.0.1:18090")
|
||||
return values
|
||||
|
||||
|
||||
def ensure_control_plane_import_path() -> None:
|
||||
"""Add /opt/control-plane to sys.path for production imports."""
|
||||
import sys
|
||||
|
||||
opt = "/opt/control-plane"
|
||||
if opt not in sys.path:
|
||||
sys.path.insert(0, opt)
|
||||
repo = Path(__file__).resolve().parent
|
||||
repo_str = str(repo)
|
||||
if repo_str not in sys.path:
|
||||
sys.path.insert(0, repo_str)
|
||||
Reference in New Issue
Block a user