game-stream: add Meccha Chameleon launcher

This commit is contained in:
jenkins 2026-07-13 20:20:50 -03:00
parent 9d0356a357
commit 9bc01aaaf0
3 changed files with 164 additions and 0 deletions

View File

@ -4,6 +4,7 @@ kind: Kustomization
resources:
- namespace.yaml
- vault-serviceaccount.yaml
- wolf-config-ensure-configmap.yaml
- wolf-api-proxy-configmap.yaml
- wolf-gatekeeper-configmap.yaml
- wolf-service.yaml

View File

@ -0,0 +1,144 @@
# 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

View File

@ -17,6 +17,8 @@ spec:
labels:
app: wolf
atlas.bstein.dev/game-mode: wolf
annotations:
game-stream.bstein.dev/wolf-config-revision: "2026-07-13-meccha-chameleon"
spec:
hostNetwork: true
dnsPolicy: ClusterFirstWithHostNet
@ -39,6 +41,19 @@ spec:
mountPath: /wolf-runtime
- name: wolf-socket
mountPath: /wolf-socket
- name: wolf-config-ensure
image: ghcr.io/games-on-whales/wolf:stable
imagePullPolicy: IfNotPresent
command: ["/usr/bin/python3", "/opt/wolf-config-ensure/wolf_config_ensure.py"]
env:
- name: WOLF_CFG_FILE
value: /etc/wolf/cfg/config.toml
volumeMounts:
- name: wolf-state
mountPath: /etc/wolf
- name: wolf-config-ensure
mountPath: /opt/wolf-config-ensure
readOnly: true
nodeSelector:
kubernetes.io/hostname: titan-24
tolerations:
@ -175,6 +190,10 @@ spec:
configMap:
name: wolf-api-proxy
defaultMode: 0555
- name: wolf-config-ensure
configMap:
name: wolf-config-ensure
defaultMode: 0555
- name: wolfmanager-data
hostPath:
path: /etc/wolfmanager