145 lines
4.3 KiB
YAML
145 lines
4.3 KiB
YAML
# services/game-stream/wolf-config-ensure-configmap.yaml
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: wolf-config-ensure
|
|
namespace: game-stream
|
|
data:
|
|
wolf_config_ensure.py: |
|
|
#!/usr/bin/env python3
|
|
import os
|
|
import re
|
|
import sys
|
|
import uuid
|
|
from pathlib import Path
|
|
|
|
CONFIG_PATH = Path(os.environ.get("WOLF_CFG_FILE", "/etc/wolf/cfg/config.toml"))
|
|
APP_TITLE = "MECCHA CHAMELEON"
|
|
APP_ID = "4704690"
|
|
|
|
APP_BLOCK = f"""
|
|
|
|
[[profiles.apps]]
|
|
title = "{APP_TITLE}"
|
|
render_node = "/dev/dri/renderD128"
|
|
start_audio_server = true
|
|
start_virtual_compositor = true
|
|
icon_png_path = "https://shared.cloudflare.steamstatic.com/store_item_assets/steam/apps/{APP_ID}/capsule_616x353.jpg"
|
|
[profiles.apps.runner]
|
|
type = "docker"
|
|
name = "WolfSteam"
|
|
image = "ghcr.io/games-on-whales/steam:edge"
|
|
mounts = []
|
|
env = [
|
|
"PROTON_LOG=1",
|
|
"RUN_SWAY=true",
|
|
"GOW_REQUIRED_DEVICES=/dev/input/* /dev/dri/* /dev/nvidia*",
|
|
"STEAM_STARTUP_FLAGS=steam://rungameid/{APP_ID}"
|
|
]
|
|
devices = []
|
|
ports = []
|
|
base_create_json = \"\"\"
|
|
{{
|
|
"HostConfig": {{
|
|
"IpcMode": "host",
|
|
"CapAdd": ["SYS_ADMIN", "SYS_NICE", "SYS_PTRACE", "NET_RAW", "MKNOD", "NET_ADMIN"],
|
|
"SecurityOpt": ["seccomp=unconfined", "apparmor=unconfined"],
|
|
"Ulimits": [{{"Name":"nofile", "Hard":10240, "Soft":10240}}],
|
|
"Privileged": false,
|
|
"DeviceCgroupRules": ["c 13:* rmw", "c 244:* rmw"]
|
|
}}
|
|
}}
|
|
\"\"\"
|
|
""".rstrip()
|
|
|
|
PROFILE_HEADER = re.compile(r"(?m)^\s*\[\[profiles\]\]\s*$")
|
|
EMPTY_PROFILES = re.compile(r"(?m)^\s*profiles\s*=\s*\[\]\s*$\n?")
|
|
|
|
|
|
def _seed_config() -> str:
|
|
return f"""hostname = "wolf"
|
|
support_hevc = true
|
|
config_version = 2
|
|
uuid = "{uuid.uuid4()}"
|
|
|
|
paired_clients = []
|
|
gstreamer = {{}}
|
|
|
|
[[profiles]]
|
|
id = "moonlight-profile-id"
|
|
name = "Moonlight"
|
|
{APP_BLOCK}
|
|
|
|
[[profiles]]
|
|
id = "user"
|
|
name = "User"
|
|
{APP_BLOCK}
|
|
"""
|
|
|
|
|
|
def _has_app(section: str) -> bool:
|
|
return re.search(rf'(?m)^\s*title\s*=\s*["\']{re.escape(APP_TITLE)}["\']\s*$', section) is not None
|
|
|
|
|
|
def _ensure_app(text: str) -> str:
|
|
if not text.strip():
|
|
return _seed_config()
|
|
|
|
starts = [match.start() for match in PROFILE_HEADER.finditer(text)]
|
|
if not starts:
|
|
return EMPTY_PROFILES.sub("", text).rstrip() + "\n\n[[profiles]]\nid = \"moonlight-profile-id\"\nname = \"Moonlight\"" + APP_BLOCK + "\n"
|
|
|
|
parts = []
|
|
cursor = 0
|
|
changed = False
|
|
for index, start in enumerate(starts):
|
|
end = starts[index + 1] if index + 1 < len(starts) else len(text)
|
|
parts.append(text[cursor:start])
|
|
section = text[start:end]
|
|
if _has_app(section):
|
|
parts.append(section)
|
|
else:
|
|
parts.append(section.rstrip() + APP_BLOCK + "\n\n")
|
|
changed = True
|
|
cursor = end
|
|
parts.append(text[cursor:])
|
|
if not changed:
|
|
return text
|
|
return "".join(parts).rstrip() + "\n"
|
|
|
|
|
|
def _validate_toml(text: str) -> None:
|
|
try:
|
|
import tomllib
|
|
except Exception:
|
|
return
|
|
tomllib.loads(text)
|
|
|
|
|
|
def main() -> int:
|
|
CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True)
|
|
original = CONFIG_PATH.read_text(encoding="utf-8") if CONFIG_PATH.exists() else ""
|
|
updated = _ensure_app(original)
|
|
if updated == original:
|
|
print(f"{APP_TITLE} already present in {CONFIG_PATH}")
|
|
return 0
|
|
|
|
_validate_toml(updated)
|
|
if CONFIG_PATH.exists():
|
|
backup = CONFIG_PATH.with_suffix(CONFIG_PATH.suffix + ".pre-meccha-chameleon")
|
|
backup.write_text(original, encoding="utf-8")
|
|
|
|
tmp_path = CONFIG_PATH.with_suffix(CONFIG_PATH.suffix + ".tmp")
|
|
tmp_path.write_text(updated, encoding="utf-8")
|
|
tmp_path.replace(CONFIG_PATH)
|
|
print(f"ensured {APP_TITLE} Steam app {APP_ID} in {CONFIG_PATH}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
try:
|
|
raise SystemExit(main())
|
|
except Exception as exc:
|
|
print(f"failed to ensure {APP_TITLE}: {exc}", file=sys.stderr)
|
|
raise
|